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