xref: /aosp_15_r20/external/skia/tests/GrAHardwareBufferTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2018 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 // This is a GPU-backend specific test. It relies on static initializers to work
9 
10 #include "include/core/SkTypes.h"
11 
12 #if defined(SK_GANESH) && defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
13 
14 #include "include/android/SkImageAndroid.h"
15 #include "include/android/SkSurfaceAndroid.h"
16 #include "include/core/SkBitmap.h"
17 #include "include/core/SkCanvas.h"
18 #include "include/core/SkColorSpace.h"
19 #include "include/core/SkImage.h"
20 #include "include/core/SkSurface.h"
21 #include "include/gpu/ganesh/GrDirectContext.h"
22 #include "include/gpu/ganesh/SkSurfaceGanesh.h"
23 #include "src/gpu/ganesh/GrAHardwareBufferImageGenerator.h"
24 #include "src/gpu/ganesh/GrDirectContextPriv.h"
25 #include "src/gpu/ganesh/GrGpu.h"
26 #include "tests/Test.h"
27 #include "tools/gpu/GrContextFactory.h"
28 
29 #include <android/hardware_buffer.h>
30 #include <cinttypes>
31 
32 static const int DEV_W = 16, DEV_H = 16;
33 
get_src_color(int x,int y)34 static SkPMColor get_src_color(int x, int y) {
35     SkASSERT(x >= 0 && x < DEV_W);
36     SkASSERT(y >= 0 && y < DEV_H);
37 
38     U8CPU r = x;
39     U8CPU g = y;
40     U8CPU b = 0xc;
41 
42     U8CPU a = 0xff;
43     switch ((x+y) % 5) {
44         case 0:
45             a = 0xff;
46             break;
47         case 1:
48             a = 0x80;
49             break;
50         case 2:
51             a = 0xCC;
52             break;
53         case 4:
54             a = 0x01;
55             break;
56         case 3:
57             a = 0x00;
58             break;
59     }
60     a = 0xff;
61     return SkPremultiplyARGBInline(a, r, g, b);
62 }
63 
make_src_bitmap()64 static SkBitmap make_src_bitmap() {
65     static SkBitmap bmp;
66     if (bmp.isNull()) {
67         bmp.allocN32Pixels(DEV_W, DEV_H);
68         intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
69         for (int y = 0; y < DEV_H; ++y) {
70             for (int x = 0; x < DEV_W; ++x) {
71                 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(
72                         pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
73                 *pixel = get_src_color(x, y);
74             }
75         }
76     }
77     return bmp;
78 }
79 
check_read(skiatest::Reporter * reporter,const SkBitmap & expectedBitmap,const SkBitmap & actualBitmap)80 static bool check_read(skiatest::Reporter* reporter, const SkBitmap& expectedBitmap,
81                        const SkBitmap& actualBitmap) {
82     bool result = true;
83     for (int y = 0; y < DEV_H && result; ++y) {
84         for (int x = 0; x < DEV_W && result; ++x) {
85             const uint32_t srcPixel = *expectedBitmap.getAddr32(x, y);
86             const uint32_t dstPixel = *actualBitmap.getAddr32(x, y);
87             if (srcPixel != dstPixel) {
88                 ERRORF(reporter, "Expected readback pixel (%d, %d) value 0x%08x, got 0x%08x.",
89                        x, y,  srcPixel, dstPixel);
90                 result = false;
91             }/* else {
92                 SkDebugf("Got good pixel (%d, %d) value 0x%08x, got 0x%08x.\n",
93                        x, y,  srcPixel, dstPixel);
94             }*/
95         }
96     }
97     return result;
98 }
99 
cleanup_resources(AHardwareBuffer * buffer)100 static void cleanup_resources(AHardwareBuffer* buffer) {
101     if (buffer) {
102         AHardwareBuffer_release(buffer);
103     }
104 }
105 
basic_draw_test_helper(skiatest::Reporter * reporter,const sk_gpu_test::ContextInfo & info,GrSurfaceOrigin surfaceOrigin)106 static void basic_draw_test_helper(skiatest::Reporter* reporter,
107                                    const sk_gpu_test::ContextInfo& info,
108                                    GrSurfaceOrigin surfaceOrigin) {
109 
110     auto context = info.directContext();
111     if (!context->priv().caps()->supportsAHardwareBufferImages()) {
112         return;
113     }
114 
115     ///////////////////////////////////////////////////////////////////////////
116     // Setup SkBitmaps
117     ///////////////////////////////////////////////////////////////////////////
118 
119     const SkBitmap srcBitmap = make_src_bitmap();
120 
121     ///////////////////////////////////////////////////////////////////////////
122     // Setup AHardwareBuffer
123     ///////////////////////////////////////////////////////////////////////////
124 
125     AHardwareBuffer* buffer = nullptr;
126 
127     AHardwareBuffer_Desc hwbDesc;
128     hwbDesc.width = DEV_W;
129     hwbDesc.height = DEV_H;
130     hwbDesc.layers = 1;
131     hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
132                     AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
133                     AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
134     hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
135     // The following three are not used in the allocate
136     hwbDesc.stride = 0;
137     hwbDesc.rfu0= 0;
138     hwbDesc.rfu1= 0;
139 
140     if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
141         ERRORF(reporter, "Failed to allocated hardware buffer, error: %d", error);
142         cleanup_resources(buffer);
143         return;
144     }
145 
146     // Get actual desc for allocated buffer so we know the stride for uploading cpu data.
147     AHardwareBuffer_describe(buffer, &hwbDesc);
148 
149     uint32_t* bufferAddr;
150     if (AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr,
151                              reinterpret_cast<void**>(&bufferAddr))) {
152         ERRORF(reporter, "Failed to lock hardware buffer");
153         cleanup_resources(buffer);
154         return;
155     }
156 
157     int bbp = srcBitmap.bytesPerPixel();
158     uint32_t* src = (uint32_t*)srcBitmap.getPixels();
159     int nextLineStep = DEV_W;
160     if (surfaceOrigin == kBottomLeft_GrSurfaceOrigin) {
161         nextLineStep = -nextLineStep;
162         src += (DEV_H-1)*DEV_W;
163     }
164     uint32_t* dst = bufferAddr;
165     for (int y = 0; y < DEV_H; ++y) {
166         memcpy(dst, src, DEV_W * bbp);
167         src += nextLineStep;
168         dst += hwbDesc.stride;
169     }
170     AHardwareBuffer_unlock(buffer, nullptr);
171 
172     ///////////////////////////////////////////////////////////////////////////
173     // Wrap AHardwareBuffer in SkImage
174     ///////////////////////////////////////////////////////////////////////////
175 
176     sk_sp<SkImage> image = SkImages::DeferredFromAHardwareBuffer(
177             buffer, kPremul_SkAlphaType, nullptr, surfaceOrigin);
178     REPORTER_ASSERT(reporter, image);
179 
180     ///////////////////////////////////////////////////////////////////////////
181     // Make a surface to draw into
182     ///////////////////////////////////////////////////////////////////////////
183 
184     SkImageInfo imageInfo = SkImageInfo::Make(DEV_W, DEV_H, kRGBA_8888_SkColorType,
185                                               kPremul_SkAlphaType);
186     sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(context, skgpu::Budgeted::kNo, imageInfo);
187     REPORTER_ASSERT(reporter, surface);
188 
189     ///////////////////////////////////////////////////////////////////////////
190     // Draw the AHardwareBuffer SkImage into surface
191     ///////////////////////////////////////////////////////////////////////////
192 
193     surface->getCanvas()->drawImage(image, 0, 0);
194 
195     SkBitmap readbackBitmap;
196     readbackBitmap.allocN32Pixels(DEV_W, DEV_H);
197 
198     REPORTER_ASSERT(reporter, surface->readPixels(readbackBitmap, 0, 0));
199     REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, readbackBitmap));
200 
201     // Draw the image a second time to make sure we get the correct origin when we get the cached
202     // proxy from the generator.
203     surface->getCanvas()->drawImage(image, 0, 0);
204     REPORTER_ASSERT(reporter, surface->readPixels(readbackBitmap, 0, 0));
205     REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, readbackBitmap));
206 
207     image.reset();
208 
209     cleanup_resources(buffer);
210 }
211 
212 // Basic test to make sure we can import an AHardwareBuffer into an SkImage and draw it into a
213 // surface.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrAHardwareBuffer_BasicDrawTest,reporter,context_info,CtsEnforcement::kApiLevel_T)214 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrAHardwareBuffer_BasicDrawTest,
215                                        reporter,
216                                        context_info,
217                                        CtsEnforcement::kApiLevel_T) {
218     basic_draw_test_helper(reporter, context_info, kTopLeft_GrSurfaceOrigin);
219     basic_draw_test_helper(reporter, context_info, kBottomLeft_GrSurfaceOrigin);
220 }
221 
surface_draw_test_helper(skiatest::Reporter * reporter,const sk_gpu_test::ContextInfo & info,GrSurfaceOrigin surfaceOrigin)222 static void surface_draw_test_helper(skiatest::Reporter* reporter,
223                                      const sk_gpu_test::ContextInfo& info,
224                                      GrSurfaceOrigin surfaceOrigin) {
225 
226     auto context = info.directContext();
227     if (!context->priv().caps()->supportsAHardwareBufferImages()) {
228         return;
229     }
230 
231     bool isProtected = context->priv().caps()->supportsProtectedContent();
232 
233     ///////////////////////////////////////////////////////////////////////////
234     // Setup SkBitmaps
235     ///////////////////////////////////////////////////////////////////////////
236 
237     const SkBitmap srcBitmap = make_src_bitmap();
238 
239     ///////////////////////////////////////////////////////////////////////////
240     // Setup AHardwareBuffer
241     ///////////////////////////////////////////////////////////////////////////
242 
243     AHardwareBuffer* buffer = nullptr;
244 
245     AHardwareBuffer_Desc hwbDesc;
246     hwbDesc.width = DEV_W;
247     hwbDesc.height = DEV_H;
248     hwbDesc.layers = 1;
249     hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
250                     AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
251                     AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
252                     AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
253                     (isProtected ? AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT : 0);
254 
255     hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
256     // The following three are not used in the allocate
257     hwbDesc.stride = 0;
258     hwbDesc.rfu0= 0;
259     hwbDesc.rfu1= 0;
260 
261     if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
262         ERRORF(reporter, "Failed to allocated hardware buffer, error: %d", error);
263         cleanup_resources(buffer);
264         return;
265     }
266 
267     sk_sp<SkSurface> surface =
268             SkSurfaces::WrapAndroidHardwareBuffer(context, buffer, surfaceOrigin, nullptr, nullptr);
269     if (!surface) {
270         ERRORF(reporter, "Failed to make SkSurface.");
271         cleanup_resources(buffer);
272         return;
273     }
274 
275     surface->getCanvas()->drawImage(srcBitmap.asImage(), 0, 0);
276 
277     if (!isProtected) {
278         // In Protected mode we can't readback so we just test that we can wrap the AHB and
279         // draw it w/o errors
280         SkBitmap readbackBitmap;
281         readbackBitmap.allocN32Pixels(DEV_W, DEV_H);
282 
283         REPORTER_ASSERT(reporter, surface->readPixels(readbackBitmap, 0, 0));
284         REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, readbackBitmap));
285     }
286 
287     cleanup_resources(buffer);
288 }
289 
290 // Test to make sure we can import an AHardwareBuffer into an SkSurface and draw into it.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrAHardwareBuffer_ImportAsSurface,reporter,context_info,CtsEnforcement::kApiLevel_T)291 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrAHardwareBuffer_ImportAsSurface,
292                                        reporter,
293                                        context_info,
294                                        CtsEnforcement::kApiLevel_T) {
295     surface_draw_test_helper(reporter, context_info, kTopLeft_GrSurfaceOrigin);
296     surface_draw_test_helper(reporter, context_info, kBottomLeft_GrSurfaceOrigin);
297 }
298 
299 #endif
300