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