Flutter Engine
The Flutter Engine
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
Definition: FontMgrTest.cpp:39
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)
Definition: SkColorPriv.h:126
@ 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
static bool b
struct MyStruct a[10]
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_sp< const SkImage > image
Definition: SkRecords.h:269
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)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
dst
Definition: cp.py:12
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)