Flutter Engine
The Flutter Engine
AHardwareBufferTest.cpp
Go to the documentation of this file.
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
9
10#if __ANDROID_API__ >= 26
11
22#include "tests/Test.h"
23
25
26using namespace skgpu::graphite;
27
28static const int DEV_W = 16, DEV_H = 16;
29
30namespace {
31
32SkPMColor 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
62SkBitmap make_src_bitmap() {
63 static SkBitmap bmp;
64 if (bmp.isNull()) {
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
78bool 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
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
159void 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.
169DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(Graphite_AHardwareBuffer_ImportAsSurface,
170 reporter,
171 context,
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
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
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)
static SkPMColor get_src_color(int x, int y)
#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
uint32_t SkPMColor
Definition: SkColor.h:205
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(name, reporter, graphite_context, ctsEnforcement)
Definition: Test.h:377
#define ERRORF(r,...)
Definition: Test.h:293
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
T * get() const
Definition: SkRefCnt.h:303
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 > TextureFromImage(GrDirectContext *, const SkImage *, skgpu::Mipmapped=skgpu::Mipmapped::kNo, skgpu::Budgeted=skgpu::Budgeted::kYes)
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)
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
int32_t height
int32_t width
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63