• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "SkBlendMode.h"
18 #include "TestSceneBase.h"
19 #include "tests/common/BitmapAllocationTestUtils.h"
20 
21 class TvApp;
22 class TvAppNoRoundedCorner;
23 class TvAppColorFilter;
24 class TvAppNoRoundedCornerColorFilter;
25 
26 static bool _TvApp(BitmapAllocationTestUtils::registerBitmapAllocationScene<TvApp>(
27         "tvapp",
28         "A dense grid of cards:"
29         "with rounded corner, using overlay RenderNode for dimming."));
30 
31 static bool _TvAppNoRoundedCorner(
32         BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCorner>(
33                 "tvapp_norc",
34                 "A dense grid of cards:"
35                 "no rounded corner, using overlay RenderNode for dimming"));
36 
37 static bool _TvAppColorFilter(
38         BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppColorFilter>(
39                 "tvapp_cf",
40                 "A dense grid of cards:"
41                 "with rounded corner, using ColorFilter for dimming"));
42 
43 static bool _TvAppNoRoundedCornerColorFilter(
44         BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCornerColorFilter>(
45                 "tvapp_norc_cf",
46                 "A dense grid of cards:"
47                 "no rounded corner, using ColorFilter for dimming"));
48 
49 class TvApp : public TestScene {
50 public:
TvApp(BitmapAllocationTestUtils::BitmapAllocator allocator)51     TvApp(BitmapAllocationTestUtils::BitmapAllocator allocator)
52             : TestScene(), mAllocator(allocator) {}
53 
54     sp<RenderNode> mBg;
55     std::vector<sp<RenderNode>> mCards;
56     std::vector<sp<RenderNode>> mInfoAreas;
57     std::vector<sp<RenderNode>> mImages;
58     std::vector<sp<RenderNode>> mOverlays;
59     std::vector<sk_sp<Bitmap>> mCachedBitmaps;
60     BitmapAllocationTestUtils::BitmapAllocator mAllocator;
61     sk_sp<Bitmap> mSingleBitmap;
62     int mSeed = 0;
63     int mSeed2 = 0;
64 
createContent(int width,int height,Canvas & canvas)65     void createContent(int width, int height, Canvas& canvas) override {
66         mBg = createBitmapNode(canvas, 0xFF9C27B0, 0, 0, width, height);
67         canvas.drawRenderNode(mBg.get());
68 
69         canvas.insertReorderBarrier(true);
70         mSingleBitmap = mAllocator(dp(160), dp(120), kRGBA_8888_SkColorType,
71                                    [](SkBitmap& skBitmap) { skBitmap.eraseColor(0xFF0000FF); });
72 
73         for (int y = dp(18) - dp(178); y < height - dp(18); y += dp(178)) {
74             bool isFirstCard = true;
75             for (int x = dp(18); x < width - dp(18); x += dp(178)) {
76                 sp<RenderNode> card = createCard(x, y, dp(160), dp(160), isFirstCard);
77                 isFirstCard = false;
78                 canvas.drawRenderNode(card.get());
79                 mCards.push_back(card);
80             }
81         }
82         canvas.insertReorderBarrier(false);
83     }
84 
doFrame(int frameNr)85     void doFrame(int frameNr) override {
86         size_t numCards = mCards.size();
87         for (size_t ci = 0; ci < numCards; ci++) {
88             updateCard(ci, frameNr);
89         }
90     }
91 
92 private:
createBitmapNode(Canvas & canvas,SkColor color,int left,int top,int width,int height)93     sp<RenderNode> createBitmapNode(Canvas& canvas, SkColor color, int left, int top, int width,
94                                     int height) {
95         return TestUtils::createNode(
96                 left, top, left + width, top + height,
97                 [this, width, height, color](RenderProperties& props, Canvas& canvas) {
98                     sk_sp<Bitmap> bitmap =
99                             mAllocator(width, height, kRGBA_8888_SkColorType,
100                                        [color](SkBitmap& skBitmap) { skBitmap.eraseColor(color); });
101                     canvas.drawBitmap(*bitmap, 0, 0, nullptr);
102                 });
103     }
104 
createSharedBitmapNode(Canvas & canvas,int left,int top,int width,int height,sk_sp<Bitmap> bitmap)105     sp<RenderNode> createSharedBitmapNode(Canvas& canvas, int left, int top, int width, int height,
106                                           sk_sp<Bitmap> bitmap) {
107         return TestUtils::createNode(left, top, left + width, top + height,
108                                      [bitmap](RenderProperties& props, Canvas& canvas) {
109                                          canvas.drawBitmap(*bitmap, 0, 0, nullptr);
110                                      });
111     }
112 
createInfoNode(Canvas & canvas,int left,int top,int width,int height,const char * text,const char * text2)113     sp<RenderNode> createInfoNode(Canvas& canvas, int left, int top, int width, int height,
114                                   const char* text, const char* text2) {
115         return TestUtils::createNode(left, top, left + width, top + height,
116                                      [text, text2](RenderProperties& props, Canvas& canvas) {
117                                          canvas.drawColor(0xFFFFEEEE, SkBlendMode::kSrcOver);
118 
119                                          SkPaint paint;
120                                          paint.setAntiAlias(true);
121                                          paint.setTextSize(24);
122 
123                                          paint.setColor(Color::Black);
124                                          TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 10, 30);
125                                          paint.setTextSize(20);
126                                          TestUtils::drawUtf8ToCanvas(&canvas, text2, paint, 10, 54);
127 
128                                      });
129     }
130 
createColorNode(Canvas & canvas,int left,int top,int width,int height,SkColor color)131     sp<RenderNode> createColorNode(Canvas& canvas, int left, int top, int width, int height,
132                                    SkColor color) {
133         return TestUtils::createNode(left, top, left + width, top + height,
134                                      [color](RenderProperties& props, Canvas& canvas) {
135                                          canvas.drawColor(color, SkBlendMode::kSrcOver);
136                                      });
137     }
138 
useSingleBitmap()139     virtual bool useSingleBitmap() { return false; }
140 
roundedCornerRadius()141     virtual float roundedCornerRadius() { return dp(2); }
142 
143     // when true, use overlay RenderNode for dimming, otherwise apply a ColorFilter to dim image
useOverlay()144     virtual bool useOverlay() { return true; }
145 
createCard(int x,int y,int width,int height,bool selected)146     sp<RenderNode> createCard(int x, int y, int width, int height, bool selected) {
147         return TestUtils::createNode(x, y, x + width, y + height, [width, height, selected, this](
148                                                                           RenderProperties& props,
149                                                                           Canvas& canvas) {
150             if (selected) {
151                 props.setElevation(dp(16));
152                 props.setScaleX(1.2);
153                 props.setScaleY(1.2);
154             }
155             props.mutableOutline().setRoundRect(0, 0, width, height, roundedCornerRadius(), 1);
156             props.mutableOutline().setShouldClip(true);
157 
158             sk_sp<Bitmap> bitmap =
159                     useSingleBitmap() ? mSingleBitmap
160                                       : mAllocator(width, dp(120), kRGBA_8888_SkColorType,
161                                                    [this](SkBitmap& skBitmap) {
162                                                        skBitmap.eraseColor(0xFF000000 |
163                                                                            ((mSeed << 3) & 0xFF));
164                                                    });
165             sp<RenderNode> cardImage = createSharedBitmapNode(canvas, 0, 0, width, dp(120), bitmap);
166             canvas.drawRenderNode(cardImage.get());
167             mCachedBitmaps.push_back(bitmap);
168             mImages.push_back(cardImage);
169 
170             char buffer[128];
171             sprintf(buffer, "Video %d-%d", mSeed, mSeed + 1);
172             mSeed++;
173             char buffer2[128];
174             sprintf(buffer2, "Studio %d", mSeed2++);
175             sp<RenderNode> infoArea =
176                     createInfoNode(canvas, 0, dp(120), width, height, buffer, buffer2);
177             canvas.drawRenderNode(infoArea.get());
178             mInfoAreas.push_back(infoArea);
179 
180             if (useOverlay()) {
181                 sp<RenderNode> overlayColor =
182                         createColorNode(canvas, 0, 0, width, height, 0x00000000);
183                 canvas.drawRenderNode(overlayColor.get());
184                 mOverlays.push_back(overlayColor);
185             }
186         });
187     }
188 
updateCard(int ci,int curFrame)189     void updateCard(int ci, int curFrame) {
190         // updating card's translation Y
191         sp<RenderNode> card = mCards[ci];
192         card->setPropertyFieldsDirty(RenderNode::Y);
193         card->mutateStagingProperties().setTranslationY(curFrame % 150);
194 
195         // re-recording card's canvas, not necessary but to add some burden to CPU
196         std::unique_ptr<Canvas> cardcanvas(Canvas::create_recording_canvas(
197                 card->stagingProperties().getWidth(), card->stagingProperties().getHeight(),
198                 card.get()));
199         sp<RenderNode> image = mImages[ci];
200         sp<RenderNode> infoArea = mInfoAreas[ci];
201         cardcanvas->drawRenderNode(infoArea.get());
202 
203         if (useOverlay()) {
204             cardcanvas->drawRenderNode(image.get());
205             // re-recording card overlay's canvas, animating overlay color alpha
206             sp<RenderNode> overlay = mOverlays[ci];
207             std::unique_ptr<Canvas> canvas(
208                     Canvas::create_recording_canvas(overlay->stagingProperties().getWidth(),
209                                                     overlay->stagingProperties().getHeight(),
210                                                     overlay.get()));
211             canvas->drawColor((curFrame % 150) << 24, SkBlendMode::kSrcOver);
212             overlay->setStagingDisplayList(canvas->finishRecording());
213             cardcanvas->drawRenderNode(overlay.get());
214         } else {
215             // re-recording image node's canvas, animating ColorFilter
216             std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
217                     image->stagingProperties().getWidth(), image->stagingProperties().getHeight(),
218                     image.get()));
219             SkPaint paint;
220             sk_sp<SkColorFilter> filter(
221                     SkColorFilter::MakeModeFilter((curFrame % 150) << 24, SkBlendMode::kSrcATop));
222             paint.setColorFilter(filter);
223             sk_sp<Bitmap> bitmap = mCachedBitmaps[ci];
224             canvas->drawBitmap(*bitmap, 0, 0, &paint);
225             image->setStagingDisplayList(canvas->finishRecording());
226             cardcanvas->drawRenderNode(image.get());
227         }
228 
229         card->setStagingDisplayList(cardcanvas->finishRecording());
230     }
231 };
232 
233 class TvAppNoRoundedCorner : public TvApp {
234 public:
TvAppNoRoundedCorner(BitmapAllocationTestUtils::BitmapAllocator allocator)235     TvAppNoRoundedCorner(BitmapAllocationTestUtils::BitmapAllocator allocator) : TvApp(allocator) {}
236 
237 private:
roundedCornerRadius()238     virtual float roundedCornerRadius() override { return dp(0); }
239 };
240 
241 class TvAppColorFilter : public TvApp {
242 public:
TvAppColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator)243     TvAppColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator) : TvApp(allocator) {}
244 
245 private:
useOverlay()246     virtual bool useOverlay() override { return false; }
247 };
248 
249 class TvAppNoRoundedCornerColorFilter : public TvApp {
250 public:
TvAppNoRoundedCornerColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator)251     TvAppNoRoundedCornerColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator)
252             : TvApp(allocator) {}
253 
254 private:
roundedCornerRadius()255     virtual float roundedCornerRadius() override { return dp(0); }
256 
useOverlay()257     virtual bool useOverlay() override { return false; }
258 };
259