blob: c5fb7c7911546e2578c4b1247c450de3bc12097e [file] [log] [blame]
Greg Danielb2acf0a2018-09-12 09:17:11 -04001/*
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 intializers to work
9
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkTypes.h"
Greg Danielb2acf0a2018-09-12 09:17:11 -040011
12#if SK_SUPPORT_GPU && defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
13
Robert Phillipse19babf2020-04-06 13:57:30 -040014#include "include/core/SkCanvas.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "include/core/SkImage.h"
16#include "include/core/SkSurface.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040017#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrAHardwareBufferImageGenerator.h"
19#include "src/gpu/GrContextPriv.h"
20#include "src/gpu/GrGpu.h"
21#include "tests/Test.h"
22#include "tools/gpu/GrContextFactory.h"
Greg Danielb2acf0a2018-09-12 09:17:11 -040023
24#include <android/hardware_buffer.h>
25#include <cinttypes>
26
27static const int DEV_W = 16, DEV_H = 16;
28
29static SkPMColor get_src_color(int x, int y) {
30 SkASSERT(x >= 0 && x < DEV_W);
31 SkASSERT(y >= 0 && y < DEV_H);
32
33 U8CPU r = x;
34 U8CPU g = y;
35 U8CPU b = 0xc;
36
37 U8CPU a = 0xff;
38 switch ((x+y) % 5) {
39 case 0:
40 a = 0xff;
41 break;
42 case 1:
43 a = 0x80;
44 break;
45 case 2:
46 a = 0xCC;
47 break;
48 case 4:
49 a = 0x01;
50 break;
51 case 3:
52 a = 0x00;
53 break;
54 }
55 a = 0xff;
56 return SkPremultiplyARGBInline(a, r, g, b);
57}
58
59static SkBitmap make_src_bitmap() {
60 static SkBitmap bmp;
61 if (bmp.isNull()) {
62 bmp.allocN32Pixels(DEV_W, DEV_H);
63 intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
64 for (int y = 0; y < DEV_H; ++y) {
65 for (int x = 0; x < DEV_W; ++x) {
66 SkPMColor* pixel = reinterpret_cast<SkPMColor*>(
67 pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
68 *pixel = get_src_color(x, y);
69 }
70 }
71 }
72 return bmp;
73}
74
75static bool check_read(skiatest::Reporter* reporter, const SkBitmap& expectedBitmap,
76 const SkBitmap& actualBitmap) {
77 bool result = true;
78 for (int y = 0; y < DEV_H && result; ++y) {
79 for (int x = 0; x < DEV_W && result; ++x) {
80 const uint32_t srcPixel = *expectedBitmap.getAddr32(x, y);
81 const uint32_t dstPixel = *actualBitmap.getAddr32(x, y);
82 if (srcPixel != dstPixel) {
83 ERRORF(reporter, "Expected readback pixel (%d, %d) value 0x%08x, got 0x%08x.",
84 x, y, srcPixel, dstPixel);
85 result = false;
Greg Daniel637c06a2018-09-12 09:44:25 -040086 }/* else {
87 SkDebugf("Got good pixel (%d, %d) value 0x%08x, got 0x%08x.\n",
88 x, y, srcPixel, dstPixel);
89 }*/
Greg Danielb2acf0a2018-09-12 09:17:11 -040090 }
91 }
92 return result;
93}
94
95static void cleanup_resources(AHardwareBuffer* buffer) {
96 if (buffer) {
97 AHardwareBuffer_release(buffer);
98 }
99}
100
Stan Iliev505dd572018-09-13 14:20:03 -0400101static void basic_draw_test_helper(skiatest::Reporter* reporter,
102 const sk_gpu_test::ContextInfo& info,
103 GrSurfaceOrigin surfaceOrigin) {
104
Robert Phillips6d344c32020-07-06 10:56:46 -0400105 auto context = info.directContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500106 if (!context->priv().caps()->supportsAHardwareBufferImages()) {
Greg Danielb2acf0a2018-09-12 09:17:11 -0400107 return;
108 }
109
110 ///////////////////////////////////////////////////////////////////////////
111 // Setup SkBitmaps
112 ///////////////////////////////////////////////////////////////////////////
113
114 const SkBitmap srcBitmap = make_src_bitmap();
115
116 ///////////////////////////////////////////////////////////////////////////
117 // Setup AHardwareBuffer
118 ///////////////////////////////////////////////////////////////////////////
119
120 AHardwareBuffer* buffer = nullptr;
121
122 AHardwareBuffer_Desc hwbDesc;
123 hwbDesc.width = DEV_W;
124 hwbDesc.height = DEV_H;
125 hwbDesc.layers = 1;
126 hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
127 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
128 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
129 hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
130 // The following three are not used in the allocate
131 hwbDesc.stride = 0;
132 hwbDesc.rfu0= 0;
133 hwbDesc.rfu1= 0;
134
135 if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
136 ERRORF(reporter, "Failed to allocated hardware buffer, error: %d", error);
137 cleanup_resources(buffer);
138 return;
139 }
140
141 // Get actual desc for allocated buffer so we know the stride for uploading cpu data.
142 AHardwareBuffer_describe(buffer, &hwbDesc);
143
144 uint32_t* bufferAddr;
145 if (AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr,
146 reinterpret_cast<void**>(&bufferAddr))) {
147 ERRORF(reporter, "Failed to lock hardware buffer");
148 cleanup_resources(buffer);
149 return;
150 }
151
152 int bbp = srcBitmap.bytesPerPixel();
153 uint32_t* src = (uint32_t*)srcBitmap.getPixels();
Stan Iliev505dd572018-09-13 14:20:03 -0400154 int nextLineStep = DEV_W;
155 if (surfaceOrigin == kBottomLeft_GrSurfaceOrigin) {
156 nextLineStep = -nextLineStep;
157 src += (DEV_H-1)*DEV_W;
158 }
Greg Danielb2acf0a2018-09-12 09:17:11 -0400159 uint32_t* dst = bufferAddr;
160 for (int y = 0; y < DEV_H; ++y) {
161 memcpy(dst, src, DEV_W * bbp);
Stan Iliev505dd572018-09-13 14:20:03 -0400162 src += nextLineStep;
Greg Danielb2acf0a2018-09-12 09:17:11 -0400163 dst += hwbDesc.stride;
164 }
165 AHardwareBuffer_unlock(buffer, nullptr);
166
167 ///////////////////////////////////////////////////////////////////////////
168 // Wrap AHardwareBuffer in SkImage
169 ///////////////////////////////////////////////////////////////////////////
170
Stan Iliev505dd572018-09-13 14:20:03 -0400171 sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(buffer, kPremul_SkAlphaType,
172 nullptr, surfaceOrigin);
Greg Danielb2acf0a2018-09-12 09:17:11 -0400173 REPORTER_ASSERT(reporter, image);
174
175 ///////////////////////////////////////////////////////////////////////////
176 // Make a surface to draw into
177 ///////////////////////////////////////////////////////////////////////////
178
179 SkImageInfo imageInfo = SkImageInfo::Make(DEV_W, DEV_H, kRGBA_8888_SkColorType,
180 kPremul_SkAlphaType);
181 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo,
182 imageInfo);
183 REPORTER_ASSERT(reporter, surface);
184
185 ///////////////////////////////////////////////////////////////////////////
186 // Draw the AHardwareBuffer SkImage into surface
187 ///////////////////////////////////////////////////////////////////////////
188
189 surface->getCanvas()->drawImage(image, 0, 0);
190
191 SkBitmap readbackBitmap;
192 readbackBitmap.allocN32Pixels(DEV_W, DEV_H);
193
194 REPORTER_ASSERT(reporter, surface->readPixels(readbackBitmap, 0, 0));
195 REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, readbackBitmap));
196
197 image.reset();
198
199 cleanup_resources(buffer);
Stan Iliev505dd572018-09-13 14:20:03 -0400200
201}
202
203// Basic test to make sure we can import an AHardwareBuffer into an SkImage and draw it into a
204// surface.
205DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrAHardwareBuffer_BasicDrawTest,
206 reporter, context_info) {
207 basic_draw_test_helper(reporter, context_info, kTopLeft_GrSurfaceOrigin);
208 basic_draw_test_helper(reporter, context_info, kBottomLeft_GrSurfaceOrigin);
Greg Danielb2acf0a2018-09-12 09:17:11 -0400209}
210
Greg Daniel173464d2019-02-06 15:30:34 -0500211static void surface_draw_test_helper(skiatest::Reporter* reporter,
212 const sk_gpu_test::ContextInfo& info,
213 GrSurfaceOrigin surfaceOrigin) {
214
Robert Phillips6d344c32020-07-06 10:56:46 -0400215 auto context = info.directContext();
Greg Daniel173464d2019-02-06 15:30:34 -0500216 if (!context->priv().caps()->supportsAHardwareBufferImages()) {
217 return;
218 }
219
220 ///////////////////////////////////////////////////////////////////////////
221 // Setup SkBitmaps
222 ///////////////////////////////////////////////////////////////////////////
223
224 const SkBitmap srcBitmap = make_src_bitmap();
225
226 ///////////////////////////////////////////////////////////////////////////
227 // Setup AHardwareBuffer
228 ///////////////////////////////////////////////////////////////////////////
229
230 AHardwareBuffer* buffer = nullptr;
231
232 AHardwareBuffer_Desc hwbDesc;
233 hwbDesc.width = DEV_W;
234 hwbDesc.height = DEV_H;
235 hwbDesc.layers = 1;
236 hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
237 AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
238 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
239 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
240
241 hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
242 // The following three are not used in the allocate
243 hwbDesc.stride = 0;
244 hwbDesc.rfu0= 0;
245 hwbDesc.rfu1= 0;
246
247 if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
248 ERRORF(reporter, "Failed to allocated hardware buffer, error: %d", error);
249 cleanup_resources(buffer);
250 return;
251 }
252
253 sk_sp<SkSurface> surface = SkSurface::MakeFromAHardwareBuffer(context, buffer, surfaceOrigin,
254 nullptr, nullptr);
255 if (!surface) {
256 ERRORF(reporter, "Failed to make SkSurface.");
257 cleanup_resources(buffer);
258 return;
259 }
260
261 surface->getCanvas()->drawBitmap(srcBitmap, 0, 0);
262
263 SkBitmap readbackBitmap;
264 readbackBitmap.allocN32Pixels(DEV_W, DEV_H);
265
266 REPORTER_ASSERT(reporter, surface->readPixels(readbackBitmap, 0, 0));
267 REPORTER_ASSERT(reporter, check_read(reporter, srcBitmap, readbackBitmap));
268
269 cleanup_resources(buffer);
270}
271
272// Test to make sure we can import an AHardwareBuffer into an SkSurface and draw into it.
273DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrAHardwareBuffer_ImportAsSurface,
274 reporter, context_info) {
275 surface_draw_test_helper(reporter, context_info, kTopLeft_GrSurfaceOrigin);
276 surface_draw_test_helper(reporter, context_info, kBottomLeft_GrSurfaceOrigin);
277}
278
Greg Danielb2acf0a2018-09-12 09:17:11 -0400279#endif