diff options
| -rw-r--r-- | libs/hwui/tests/common/scenes/TvApp.cpp | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/libs/hwui/tests/common/scenes/TvApp.cpp b/libs/hwui/tests/common/scenes/TvApp.cpp new file mode 100644 index 000000000000..04fc2d46f946 --- /dev/null +++ b/libs/hwui/tests/common/scenes/TvApp.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "TestSceneBase.h" +#include "tests/common/BitmapAllocationTestUtils.h" +#include "SkBlendMode.h" + +class TvApp; +class TvAppNoRoundedCorner; +class TvAppColorFilter; +class TvAppNoRoundedCornerColorFilter; + +static bool _TvApp( + BitmapAllocationTestUtils::registerBitmapAllocationScene<TvApp>( + "tvapp", "A dense grid of cards:" + "with rounded corner, using overlay RenderNode for dimming.")); + +static bool _TvAppNoRoundedCorner( + BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCorner>( + "tvapp_norc", "A dense grid of cards:" + "no rounded corner, using overlay RenderNode for dimming")); + +static bool _TvAppColorFilter( + BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppColorFilter>( + "tvapp_cf", "A dense grid of cards:" + "with rounded corner, using ColorFilter for dimming")); + +static bool _TvAppNoRoundedCornerColorFilter( + BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCornerColorFilter>( + "tvapp_norc_cf", "A dense grid of cards:" + "no rounded corner, using ColorFilter for dimming")); + +class TvApp : public TestScene { +public: + TvApp(BitmapAllocationTestUtils::BitmapAllocator allocator) + : TestScene() + , mAllocator(allocator) { } + + sp<RenderNode> mBg; + std::vector<sp<RenderNode>> mCards; + std::vector<sp<RenderNode>> mInfoAreas; + std::vector<sp<RenderNode>> mImages; + std::vector<sp<RenderNode>> mOverlays; + std::vector<sk_sp<Bitmap>> mCachedBitmaps; + BitmapAllocationTestUtils::BitmapAllocator mAllocator; + sk_sp<Bitmap> mSingleBitmap; + int mSeed = 0; + int mSeed2 = 0; + + void createContent(int width, int height, Canvas& canvas) override { + mBg = createBitmapNode(canvas, 0xFF9C27B0, 0, 0, width, height); + canvas.drawRenderNode(mBg.get()); + + canvas.insertReorderBarrier(true); + mSingleBitmap = mAllocator(dp(160), dp(120), kRGBA_8888_SkColorType, + [](SkBitmap& skBitmap) { + skBitmap.eraseColor(0xFF0000FF); + }); + + for (int y = dp(18) - dp(178); y < height - dp(18); y += dp(178)) { + bool isFirstCard = true; + for (int x = dp(18); x < width - dp(18); x += dp(178)) { + sp<RenderNode> card = createCard(x, y, dp(160), dp(160), isFirstCard); + isFirstCard = false; + canvas.drawRenderNode(card.get()); + mCards.push_back(card); + } + } + canvas.insertReorderBarrier(false); + } + + void doFrame(int frameNr) override { + size_t numCards = mCards.size(); + for (size_t ci = 0; ci < numCards; ci++) { + updateCard(ci, frameNr); + } + } + +private: + sp<RenderNode> createBitmapNode(Canvas& canvas, SkColor color, int left, int top, + int width, int height) { + return TestUtils::createNode(left, top, left + width , top + height, + [this, width, height, color](RenderProperties& props, Canvas& canvas) { + sk_sp<Bitmap> bitmap = mAllocator(width, height, kRGBA_8888_SkColorType, + [color](SkBitmap& skBitmap) { + skBitmap.eraseColor(color); + }); + canvas.drawBitmap(*bitmap, 0, 0, nullptr); + }); + } + + sp<RenderNode> createSharedBitmapNode(Canvas& canvas, int left, int top, + int width, int height, sk_sp<Bitmap>bitmap) { + return TestUtils::createNode(left, top, left + width , top + height, + [bitmap](RenderProperties& props, Canvas& canvas) { + canvas.drawBitmap(*bitmap, 0, 0, nullptr); + }); + } + + sp<RenderNode> createInfoNode(Canvas& canvas, int left, int top, + int width, int height, const char* text, const char* text2) { + return TestUtils::createNode(left, top, left + width , top + height, + [text, text2](RenderProperties& props, Canvas& canvas) { + canvas.drawColor(0xFFFFEEEE, SkBlendMode::kSrcOver); + + SkPaint paint; + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + paint.setAntiAlias(true); + paint.setTextSize(24); + + paint.setColor(Color::Black); + TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 10, 30); + paint.setTextSize(20); + TestUtils::drawUtf8ToCanvas(&canvas, text2, paint, 10, 54); + + }); + } + + sp<RenderNode> createColorNode(Canvas& canvas, int left, int top, + int width, int height, SkColor color) { + return TestUtils::createNode(left, top, left + width , top + height, + [color](RenderProperties& props, Canvas& canvas) { + canvas.drawColor(color, SkBlendMode::kSrcOver); + }); + } + + virtual bool useSingleBitmap() { + return false; + } + + virtual float roundedCornerRadius() { + return dp(2); + } + + // when true, use overlay RenderNode for dimming, otherwise apply a ColorFilter to dim image + virtual bool useOverlay() { + return true; + } + + sp<RenderNode> createCard(int x, int y, int width, int height, bool selected) { + return TestUtils::createNode(x, y, x + width, y + height, + [width, height, selected, this](RenderProperties& props, Canvas& canvas) { + if (selected) { + props.setElevation(dp(16)); + props.setScaleX(1.2); + props.setScaleY(1.2); + } + props.mutableOutline().setRoundRect(0, 0, width, height, roundedCornerRadius(), 1); + props.mutableOutline().setShouldClip(true); + + sk_sp<Bitmap> bitmap = useSingleBitmap() ? mSingleBitmap + : mAllocator(width, dp(120), kRGBA_8888_SkColorType, [this](SkBitmap& skBitmap) { + skBitmap.eraseColor(0xFF000000 | ((mSeed << 3) & 0xFF)); + }); + sp<RenderNode> cardImage = createSharedBitmapNode(canvas, 0, 0, width, dp(120), + bitmap); + canvas.drawRenderNode(cardImage.get()); + mCachedBitmaps.push_back(bitmap); + mImages.push_back(cardImage); + + char buffer[128]; + sprintf(buffer, "Video %d-%d", mSeed, mSeed + 1); + mSeed++; + char buffer2[128]; + sprintf(buffer2, "Studio %d", mSeed2++); + sp<RenderNode> infoArea = createInfoNode(canvas, 0, dp(120), width, height, buffer, buffer2); + canvas.drawRenderNode(infoArea.get()); + mInfoAreas.push_back(infoArea); + + if (useOverlay()) { + sp<RenderNode> overlayColor = createColorNode(canvas, 0, 0, width, height, 0x00000000); + canvas.drawRenderNode(overlayColor.get()); + mOverlays.push_back(overlayColor); + } + }); + } + + void updateCard(int ci, int curFrame) { + // updating card's translation Y + sp<RenderNode> card = mCards[ci]; + card->setPropertyFieldsDirty(RenderNode::Y); + card->mutateStagingProperties().setTranslationY(curFrame % 150); + + // re-recording card's canvas, not necessary but to add some burden to CPU + std::unique_ptr<Canvas> cardcanvas(Canvas::create_recording_canvas( + card->stagingProperties().getWidth(), + card->stagingProperties().getHeight())); + sp<RenderNode> image = mImages[ci]; + sp<RenderNode> infoArea = mInfoAreas[ci]; + cardcanvas->drawRenderNode(infoArea.get()); + + if (useOverlay()) { + cardcanvas->drawRenderNode(image.get()); + // re-recording card overlay's canvas, animating overlay color alpha + sp<RenderNode> overlay = mOverlays[ci]; + std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas( + overlay->stagingProperties().getWidth(), + overlay->stagingProperties().getHeight())); + canvas->drawColor((curFrame % 150) << 24, SkBlendMode::kSrcOver); + overlay->setStagingDisplayList(canvas->finishRecording()); + cardcanvas->drawRenderNode(overlay.get()); + } else { + // re-recording image node's canvas, animating ColorFilter + std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas( + image->stagingProperties().getWidth(), + image->stagingProperties().getHeight())); + SkPaint paint; + sk_sp<SkColorFilter> filter(SkColorFilter::MakeModeFilter((curFrame % 150) << 24, + SkBlendMode::kSrcATop)); + paint.setColorFilter(filter); + sk_sp<Bitmap> bitmap = mCachedBitmaps[ci]; + canvas->drawBitmap(*bitmap, 0, 0, &paint); + image->setStagingDisplayList(canvas->finishRecording()); + cardcanvas->drawRenderNode(image.get()); + } + + card->setStagingDisplayList(cardcanvas->finishRecording()); + } +}; + +class TvAppNoRoundedCorner : public TvApp { +public: + TvAppNoRoundedCorner(BitmapAllocationTestUtils::BitmapAllocator allocator) + : TvApp(allocator) { } + +private: + + virtual float roundedCornerRadius() override { + return dp(0); + } +}; + +class TvAppColorFilter : public TvApp { +public: + TvAppColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator) + : TvApp(allocator) { } + +private: + + virtual bool useOverlay() override { + return false; + } +}; + +class TvAppNoRoundedCornerColorFilter : public TvApp { +public: + TvAppNoRoundedCornerColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator) + : TvApp(allocator) { } + +private: + + virtual float roundedCornerRadius() override { + return dp(0); + } + + virtual bool useOverlay() override { + return false; + } +}; + + |