• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 <android/gui/ISurfaceComposerClient.h>
18 #include <gtest/gtest.h>
19 #include <gui/DisplayCaptureArgs.h>
20 #include <ui/GraphicTypes.h>
21 #include <ui/Rect.h>
22 
23 #include "LayerTransactionTest.h"
24 
25 namespace android {
26 
operator ==(const Color & left,const Color & right)27 bool operator==(const Color& left, const Color& right) {
28     return left.a == right.a && left.r == right.r && left.g == right.g && left.b == right.b;
29 }
30 
31 class TextureFilteringTest : public LayerTransactionTest {
32 protected:
SetUp()33     virtual void SetUp() {
34         LayerTransactionTest::SetUp();
35 
36         mParent = createLayer("test-parent", 100, 100,
37                               gui::ISurfaceComposerClient::eFXSurfaceContainer);
38         mLayer = createLayer("test-child", 100, 100,
39                              gui::ISurfaceComposerClient::eFXSurfaceBufferState, mParent.get());
40         sp<GraphicBuffer> buffer =
41                 sp<GraphicBuffer>::make(static_cast<uint32_t>(100), static_cast<uint32_t>(100),
42                                         PIXEL_FORMAT_RGBA_8888, 1u,
43                                         BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
44                                                 BufferUsage::COMPOSER_OVERLAY |
45                                                 BufferUsage::GPU_TEXTURE,
46                                         "test");
47         TransactionUtils::fillGraphicBufferColor(buffer, Rect{0, 0, 50, 100}, Color::RED);
48         TransactionUtils::fillGraphicBufferColor(buffer, Rect{50, 0, 100, 100}, Color::BLUE);
49         Transaction()
50                 .setBuffer(mLayer, buffer)
51                 .setDataspace(mLayer, ui::Dataspace::V0_SRGB)
52                 .setLayer(mLayer, INT32_MAX)
53                 .apply();
54     }
55 
TearDown()56     virtual void TearDown() { LayerTransactionTest::TearDown(); }
57 
expectFiltered(Rect redRect,Rect blueRect)58     void expectFiltered(Rect redRect, Rect blueRect) {
59         // Check that at least some of the pixels in the red rectangle aren't solid red
60         int redPixels = 0;
61         for (int x = redRect.left; x < redRect.right; x++) {
62             for (int y = redRect.top; y < redRect.bottom; y++) {
63                 redPixels += mCapture->getPixelColor(static_cast<uint32_t>(x),
64                                                      static_cast<uint32_t>(y)) == Color::RED;
65             }
66         }
67         ASSERT_LT(redPixels, redRect.getWidth() * redRect.getHeight());
68 
69         // Check that at least some of the pixels in the blue rectangle aren't solid blue
70         int bluePixels = 0;
71         for (int x = blueRect.left; x < blueRect.right; x++) {
72             for (int y = blueRect.top; y < blueRect.bottom; y++) {
73                 bluePixels += mCapture->getPixelColor(static_cast<uint32_t>(x),
74                                                       static_cast<uint32_t>(y)) == Color::BLUE;
75             }
76         }
77         ASSERT_LT(bluePixels, blueRect.getWidth() * blueRect.getHeight());
78     }
79 
80     sp<SurfaceControl> mParent;
81     sp<SurfaceControl> mLayer;
82     std::unique_ptr<ScreenCapture> mCapture;
83 };
84 
TEST_F(TextureFilteringTest,NoFiltering)85 TEST_F(TextureFilteringTest, NoFiltering) {
86     gui::DisplayCaptureArgs captureArgs;
87     captureArgs.displayToken = mDisplay;
88     captureArgs.width = 100;
89     captureArgs.height = 100;
90     captureArgs.sourceCrop = Rect{100, 100};
91     ScreenCapture::captureDisplay(&mCapture, captureArgs);
92 
93     mCapture->expectColor(Rect{0, 0, 50, 100}, Color::RED);
94     mCapture->expectColor(Rect{50, 0, 100, 100}, Color::BLUE);
95 }
96 
TEST_F(TextureFilteringTest,BufferCropNoFiltering)97 TEST_F(TextureFilteringTest, BufferCropNoFiltering) {
98     Transaction().setBufferCrop(mLayer, Rect{0, 0, 100, 100}).apply();
99 
100     gui::DisplayCaptureArgs captureArgs;
101     captureArgs.displayToken = mDisplay;
102     captureArgs.width = 100;
103     captureArgs.height = 100;
104     captureArgs.sourceCrop = Rect{0, 0, 100, 100};
105     ScreenCapture::captureDisplay(&mCapture, captureArgs);
106 
107     mCapture->expectColor(Rect{0, 0, 50, 100}, Color::RED);
108     mCapture->expectColor(Rect{50, 0, 100, 100}, Color::BLUE);
109 }
110 
111 // Expect filtering because the buffer is stretched to the layer's bounds.
TEST_F(TextureFilteringTest,BufferCropIsFiltered)112 TEST_F(TextureFilteringTest, BufferCropIsFiltered) {
113     Transaction().setBufferCrop(mLayer, Rect{25, 25, 75, 75}).apply();
114 
115     gui::DisplayCaptureArgs captureArgs;
116     captureArgs.displayToken = mDisplay;
117     captureArgs.width = 100;
118     captureArgs.height = 100;
119     captureArgs.sourceCrop = Rect{0, 0, 100, 100};
120     ScreenCapture::captureDisplay(&mCapture, captureArgs);
121 
122     expectFiltered({0, 0, 50, 100}, {50, 0, 100, 100});
123 }
124 
125 // Expect filtering because the output source crop is stretched to the output buffer's size.
TEST_F(TextureFilteringTest,OutputSourceCropIsFiltered)126 TEST_F(TextureFilteringTest, OutputSourceCropIsFiltered) {
127     gui::DisplayCaptureArgs captureArgs;
128     captureArgs.displayToken = mDisplay;
129     captureArgs.width = 100;
130     captureArgs.height = 100;
131     captureArgs.sourceCrop = Rect{25, 25, 75, 75};
132     ScreenCapture::captureDisplay(&mCapture, captureArgs);
133 
134     expectFiltered({0, 0, 50, 100}, {50, 0, 100, 100});
135 }
136 
137 // Expect filtering because the layer crop and output source crop are stretched to the output
138 // buffer's size.
TEST_F(TextureFilteringTest,LayerCropOutputSourceCropIsFiltered)139 TEST_F(TextureFilteringTest, LayerCropOutputSourceCropIsFiltered) {
140     Transaction().setCrop(mLayer, Rect{25, 25, 75, 75}).apply();
141 
142     gui::DisplayCaptureArgs captureArgs;
143     captureArgs.displayToken = mDisplay;
144     captureArgs.width = 100;
145     captureArgs.height = 100;
146     captureArgs.sourceCrop = Rect{25, 25, 75, 75};
147     ScreenCapture::captureDisplay(&mCapture, captureArgs);
148 
149     expectFiltered({0, 0, 50, 100}, {50, 0, 100, 100});
150 }
151 
152 // Expect filtering because the layer is scaled up.
TEST_F(TextureFilteringTest,LayerCaptureWithScalingIsFiltered)153 TEST_F(TextureFilteringTest, LayerCaptureWithScalingIsFiltered) {
154     LayerCaptureArgs captureArgs;
155     captureArgs.layerHandle = mLayer->getHandle();
156     captureArgs.frameScaleX = 2;
157     captureArgs.frameScaleY = 2;
158     ScreenCapture::captureLayers(&mCapture, captureArgs);
159 
160     expectFiltered({0, 0, 100, 200}, {100, 0, 200, 200});
161 }
162 
163 // Expect no filtering because the output buffer's size matches the source crop.
TEST_F(TextureFilteringTest,LayerCaptureOutputSourceCropNoFiltering)164 TEST_F(TextureFilteringTest, LayerCaptureOutputSourceCropNoFiltering) {
165     LayerCaptureArgs captureArgs;
166     captureArgs.layerHandle = mLayer->getHandle();
167     captureArgs.sourceCrop = Rect{25, 25, 75, 75};
168     ScreenCapture::captureLayers(&mCapture, captureArgs);
169 
170     mCapture->expectColor(Rect{0, 0, 25, 50}, Color::RED);
171     mCapture->expectColor(Rect{25, 0, 50, 50}, Color::BLUE);
172 }
173 
174 // Expect no filtering because the output buffer's size matches the source crop (with a cropped
175 // layer).
TEST_F(TextureFilteringTest,LayerCaptureWithCropNoFiltering)176 TEST_F(TextureFilteringTest, LayerCaptureWithCropNoFiltering) {
177     Transaction().setCrop(mLayer, Rect{10, 10, 90, 90}).apply();
178 
179     LayerCaptureArgs captureArgs;
180     captureArgs.layerHandle = mLayer->getHandle();
181     captureArgs.sourceCrop = Rect{25, 25, 75, 75};
182     ScreenCapture::captureLayers(&mCapture, captureArgs);
183 
184     mCapture->expectColor(Rect{0, 0, 25, 50}, Color::RED);
185     mCapture->expectColor(Rect{25, 0, 50, 50}, Color::BLUE);
186 }
187 
188 // Expect no filtering because the output source crop and output buffer are the same size.
TEST_F(TextureFilteringTest,OutputSourceCropDisplayFrameMatchNoFiltering)189 TEST_F(TextureFilteringTest, OutputSourceCropDisplayFrameMatchNoFiltering) {
190     gui::DisplayCaptureArgs captureArgs;
191     captureArgs.displayToken = mDisplay;
192     captureArgs.width = 50;
193     captureArgs.height = 50;
194     captureArgs.sourceCrop = Rect{25, 25, 75, 75};
195     ScreenCapture::captureDisplay(&mCapture, captureArgs);
196 
197     mCapture->expectColor(Rect{0, 0, 25, 50}, Color::RED);
198     mCapture->expectColor(Rect{25, 0, 50, 50}, Color::BLUE);
199 }
200 
201 // Expect no filtering because the layer crop shouldn't scale the layer.
TEST_F(TextureFilteringTest,LayerCropDisplayFrameMatchNoFiltering)202 TEST_F(TextureFilteringTest, LayerCropDisplayFrameMatchNoFiltering) {
203     Transaction().setCrop(mLayer, Rect{25, 25, 75, 75}).apply();
204 
205     gui::DisplayCaptureArgs captureArgs;
206     captureArgs.displayToken = mDisplay;
207     ScreenCapture::captureDisplay(&mCapture, captureArgs);
208 
209     mCapture->expectColor(Rect{25, 25, 50, 75}, Color::RED);
210     mCapture->expectColor(Rect{50, 25, 75, 75}, Color::BLUE);
211 }
212 
213 // Expect no filtering because the parent layer crop shouldn't scale the layer.
TEST_F(TextureFilteringTest,ParentCropNoFiltering)214 TEST_F(TextureFilteringTest, ParentCropNoFiltering) {
215     Transaction().setCrop(mParent, Rect{25, 25, 75, 75}).apply();
216 
217     gui::DisplayCaptureArgs captureArgs;
218     captureArgs.displayToken = mDisplay;
219     ScreenCapture::captureDisplay(&mCapture, captureArgs);
220 
221     mCapture->expectColor(Rect{25, 25, 50, 75}, Color::RED);
222     mCapture->expectColor(Rect{50, 25, 75, 75}, Color::BLUE);
223 }
224 
225 // Expect no filtering because parent's position transform shouldn't scale the layer.
TEST_F(TextureFilteringTest,ParentHasTransformNoFiltering)226 TEST_F(TextureFilteringTest, ParentHasTransformNoFiltering) {
227     Transaction().setPosition(mParent, 100, 100).apply();
228 
229     LayerCaptureArgs captureArgs;
230     captureArgs.layerHandle = mParent->getHandle();
231     captureArgs.sourceCrop = Rect{0, 0, 100, 100};
232     ScreenCapture::captureLayers(&mCapture, captureArgs);
233 
234     mCapture->expectColor(Rect{0, 0, 50, 100}, Color::RED);
235     mCapture->expectColor(Rect{50, 0, 100, 100}, Color::BLUE);
236 }
237 
238 } // namespace android
239