Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrAHardwareBufferTest.cpp
Go to the documentation of this file.
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
11
12#if defined(SK_GANESH) && defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
13
26#include "tests/Test.h"
28
30#include <cinttypes>
31
32static const int DEV_W = 16, DEV_H = 16;
33
34static 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
64static SkBitmap make_src_bitmap() {
65 static SkBitmap bmp;
66 if (bmp.isNull()) {
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
80static 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
100static void cleanup_resources(AHardwareBuffer* buffer) {
101 if (buffer) {
102 AHardwareBuffer_release(buffer);
103 }
104}
105
106static void basic_draw_test_helper(skiatest::Reporter* reporter,
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
177 buffer, kPremul_SkAlphaType, nullptr, surfaceOrigin);
179
180 ///////////////////////////////////////////////////////////////////////////
181 // Make a surface to draw into
182 ///////////////////////////////////////////////////////////////////////////
183
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.
214DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrAHardwareBuffer_BasicDrawTest,
215 reporter,
216 context_info,
218 basic_draw_test_helper(reporter, context_info, kTopLeft_GrSurfaceOrigin);
219 basic_draw_test_helper(reporter, context_info, kBottomLeft_GrSurfaceOrigin);
220}
221
222static void surface_draw_test_helper(skiatest::Reporter* reporter,
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
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.
291DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(GrAHardwareBuffer_ImportAsSurface,
292 reporter,
293 context_info,
295 surface_draw_test_helper(reporter, context_info, kTopLeft_GrSurfaceOrigin);
296 surface_draw_test_helper(reporter, context_info, kBottomLeft_GrSurfaceOrigin);
297}
298
299#endif
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
static const int DEV_H
static const int DEV_W
reporter
struct AHardwareBuffer AHardwareBuffer
static bool check_read(skiatest::Reporter *reporter, const SkBitmap &bitmap)
GrSurfaceOrigin
Definition GrTypes.h:147
@ kBottomLeft_GrSurfaceOrigin
Definition GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition GrTypes.h:148
static SkPMColor get_src_color(int x, int y)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
#define SkASSERT(cond)
Definition SkAssert.h:116
unsigned U8CPU
Definition SkCPUTypes.h:18
static SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
uint32_t SkPMColor
Definition SkColor.h:205
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
#define ERRORF(r,...)
Definition Test.h:293
#define DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info, ctsEnforcement)
Definition Test.h:434
sk_sp< SkImage > asImage() const
Definition SkBitmap.cpp:645
size_t rowBytes() const
Definition SkBitmap.h:238
bool isNull() const
Definition SkBitmap.h:219
void * getPixels() const
Definition SkBitmap.h:283
int bytesPerPixel() const
Definition SkBitmap.h:187
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition SkBitmap.cpp:232
uint32_t * getAddr32(int x, int y) const
Definition SkBitmap.h:1260
void reset(T *ptr=nullptr)
Definition SkRefCnt.h:310
VkSurfaceKHR surface
Definition main.cc:49
sk_sp< SkImage > image
Definition examples.cpp:29
static bool b
struct MyStruct a[10]
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
double y
double x
SK_API sk_sp< SkImage > DeferredFromAHardwareBuffer(AHardwareBuffer *hardwareBuffer, SkAlphaType alphaType=kPremul_SkAlphaType)
SK_API sk_sp< SkSurface > WrapAndroidHardwareBuffer(skgpu::graphite::Recorder *recorder, AHardwareBuffer *hardwareBuffer, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, BufferReleaseProc=nullptr, ReleaseContext=nullptr, bool fromWindow=false)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
dst
Definition cp.py:12
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)