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