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