xref: /aosp_15_r20/external/skia/tests/graphite/AHardwareBufferTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 Google LLC
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 #include "include/core/SkTypes.h"
9 
10 #if __ANDROID_API__ >= 26
11 
12 #include "include/android/graphite/SurfaceAndroid.h"
13 #include "include/core/SkBitmap.h"
14 #include "include/core/SkCanvas.h"
15 #include "include/core/SkColorPriv.h"
16 #include "include/core/SkColorSpace.h"
17 #include "include/core/SkSurface.h"
18 #include "include/gpu/graphite/Context.h"
19 #include "include/gpu/graphite/Image.h"
20 #include "src/gpu/graphite/Caps.h"
21 #include "src/gpu/graphite/ContextPriv.h"
22 #include "tests/Test.h"
23 
24 #include <android/hardware_buffer.h>
25 
26 using namespace skgpu::graphite;
27 
28 static const int DEV_W = 16, DEV_H = 16;
29 
30 namespace {
31 
get_src_color(int x,int y)32 SkPMColor get_src_color(int x, int y) {
33     SkASSERT(x >= 0 && x < DEV_W);
34     SkASSERT(y >= 0 && y < DEV_H);
35 
36     U8CPU r = x;
37     U8CPU g = y;
38     U8CPU b = 0xc;
39 
40     U8CPU a = 0xff;
41     switch ((x+y) % 5) {
42         case 0:
43             a = 0xff;
44             break;
45         case 1:
46             a = 0x80;
47             break;
48         case 2:
49             a = 0xCC;
50             break;
51         case 4:
52             a = 0x01;
53             break;
54         case 3:
55             a = 0x00;
56             break;
57     }
58     a = 0xff;
59     return SkPremultiplyARGBInline(a, r, g, b);
60 }
61 
make_src_bitmap()62 SkBitmap make_src_bitmap() {
63     static SkBitmap bmp;
64     if (bmp.isNull()) {
65         bmp.allocN32Pixels(DEV_W, DEV_H);
66         intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
67         for (int y = 0; y < DEV_H; ++y) {
68             for (int x = 0; x < DEV_W; ++x) {
69                 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(
70                         pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
71                 *pixel = get_src_color(x, y);
72             }
73         }
74     }
75     return bmp;
76 }
77 
check_read(skiatest::Reporter * reporter,const SkBitmap & expectedBitmap,const SkBitmap & actualBitmap)78 bool check_read(skiatest::Reporter* reporter, const SkBitmap& expectedBitmap,
79                 const SkBitmap& actualBitmap) {
80     bool result = true;
81     for (int y = 0; y < DEV_H && result; ++y) {
82         for (int x = 0; x < DEV_W && result; ++x) {
83             const uint32_t srcPixel = *expectedBitmap.getAddr32(x, y);
84             const uint32_t dstPixel = *actualBitmap.getAddr32(x, y);
85             if (srcPixel != dstPixel) {
86                 ERRORF(reporter, "Expected readback pixel (%d, %d) value 0x%08x, got 0x%08x.",
87                        x, y,  srcPixel, dstPixel);
88                 result = false;
89             }/* else {
90                 SkDebugf("Got good pixel (%d, %d) value 0x%08x, got 0x%08x.\n",
91                        x, y,  srcPixel, dstPixel);
92             }*/
93         }
94     }
95     return result;
96 }
97 
create_AHB(skiatest::Reporter * reporter,int width,int height,bool forSurface,bool isProtected,const SkBitmap * data)98 AHardwareBuffer* create_AHB(skiatest::Reporter* reporter,
99                             int width, int height,
100                             bool forSurface, bool isProtected,
101                             const SkBitmap* data) {
102 
103     AHardwareBuffer_Desc hwbDesc;
104     hwbDesc.width = width;
105     hwbDesc.height = height;
106     hwbDesc.layers = 1;
107     hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
108                     AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
109                     (isProtected ? AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT : 0);
110 
111     if (forSurface) {
112         SkASSERT(!data);
113         hwbDesc.usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
114                          AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
115     } else {
116         hwbDesc.usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
117     }
118 
119     hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
120     // The following three are not used by AHardwareBuffer_allocate
121     hwbDesc.stride = 0;
122     hwbDesc.rfu0= 0;
123     hwbDesc.rfu1= 0;
124 
125     AHardwareBuffer* buffer = nullptr;
126     if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
127         ERRORF(reporter, "Failed to allocated hardware buffer, error: %d", error);
128         return nullptr;
129     }
130 
131     if (data) {
132         SkASSERT(data->width() == width && data->height() == height);
133         // Get actual desc for allocated buffer so we know the stride for uploading cpu data.
134         AHardwareBuffer_describe(buffer, &hwbDesc);
135 
136         uint32_t* bufferAddr;
137         if (AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr,
138                                  reinterpret_cast<void**>(&bufferAddr))) {
139             ERRORF(reporter, "Failed to lock hardware buffer");
140             AHardwareBuffer_release(buffer);
141             return nullptr;
142         }
143 
144         int bbp = data->bytesPerPixel();
145         uint32_t* src = (uint32_t*)data->getPixels();
146         int nextLineStep = width;
147         uint32_t* dst = bufferAddr;
148         for (int y = 0; y < height; ++y) {
149             memcpy(dst, src, width * bbp);
150             src += nextLineStep;
151             dst += hwbDesc.stride;
152         }
153         AHardwareBuffer_unlock(buffer, nullptr);
154     }
155 
156     return buffer;
157 }
158 
delete_buffer(void * context)159 void delete_buffer(void* context) {
160     AHardwareBuffer* buffer = static_cast<AHardwareBuffer*>(context);
161     if (buffer) {
162         AHardwareBuffer_release(buffer);
163     }
164 }
165 
166 } // anonymous namespace
167 
168 // Test to make sure we can import an AHardwareBuffer into an SkSurface and draw into it.
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(Graphite_AHardwareBuffer_ImportAsSurface,reporter,context,CtsEnforcement::kApiLevel_V)169 DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(Graphite_AHardwareBuffer_ImportAsSurface,
170                                          reporter,
171                                          context,
172                                          CtsEnforcement::kApiLevel_V) {
173     if (!context->priv().caps()->supportsAHardwareBufferImages()) {
174         return;
175     }
176 
177     bool isProtected = context->priv().caps()->protectedSupport();
178 
179     std::unique_ptr<Recorder> recorder = context->makeRecorder();
180 
181     ///////////////////////////////////////////////////////////////////////////
182     // Setup SkBitmaps
183     ///////////////////////////////////////////////////////////////////////////
184 
185     const SkBitmap srcBitmap = make_src_bitmap();
186 
187     AHardwareBuffer* buffer = create_AHB(reporter,
188                                          DEV_W, DEV_H,
189                                          /* writeable= */ true,
190                                          isProtected,
191                                          /* data= */ nullptr);
192     if (!buffer) {
193         return;
194     }
195 
196     sk_sp<SkSurface> surface = SkSurfaces::WrapAndroidHardwareBuffer(recorder.get(),
197                                                                      buffer,
198                                                                      /* colorSpace= */ nullptr,
199                                                                      /* surfaceProps= */ nullptr,
200                                                                      delete_buffer,
201                                                                      buffer);
202     if (!surface) {
203         ERRORF(reporter, "Failed to make SkSurface.");
204         return;
205     }
206 
207     sk_sp<SkImage> grBacked = SkImages::TextureFromImage(recorder.get(), srcBitmap.asImage().get());
208 
209     surface->getCanvas()->drawImage(grBacked, 0, 0);
210 
211     if (!isProtected) {
212         // In Protected mode we can't readback so we just test that we can wrap the AHB and
213         // draw it w/o errors
214         SkBitmap readbackBitmap;
215         readbackBitmap.allocN32Pixels(DEV_W, DEV_H);
216 
217         REPORTER_ASSERT(reporter, surface->readPixels(readbackBitmap, 0, 0));
218         REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, readbackBitmap));
219     }
220 
221     surface.reset();
222 }
223 
224 #endif // __ANDROID_API__ >= 26
225