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