Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2016 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 #include "Test.h"
      9 
     10 #if SK_SUPPORT_GPU
     11 #include "GrClip.h"
     12 #include "GrContext.h"
     13 #include "GrRenderTargetContext.h"
     14 #include "GrResourceProvider.h"
     15 #include "GrTexture.h"
     16 #include "effects/GrSimpleTextureEffect.h"
     17 
     18 template <typename I>
     19 static SK_WHEN(std::is_integral<I>::value && 4 == sizeof(I), void)
     20 check_pixels(skiatest::Reporter* reporter, int w, int h, const I exepctedData[],
     21              const I actualData[], const char* testName) {
     22     for (int j = 0; j < h; ++j) {
     23         for (int i = 0; i < w; ++i) {
     24             I expected = exepctedData[j * w + i];
     25             I actual = actualData[j * w + i];
     26             if (expected != actual) {
     27                 ERRORF(reporter, "[%s] Expected 0x08%x, got 0x%08x at %d, %d.", testName, expected,
     28                        actual, i, j);
     29                 return;
     30             }
     31         }
     32     }
     33 }
     34 
     35 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(IntTexture, reporter, ctxInfo) {
     36     GrContext* context = ctxInfo.grContext();
     37     if (!context->caps()->isConfigTexturable(kRGBA_8888_sint_GrPixelConfig)) {
     38         return;
     39     }
     40     static const int kS = UINT8_MAX + 1;
     41     static const size_t kRowBytes = kS * sizeof(int32_t);
     42 
     43     GrSurfaceDesc desc;
     44     desc.fConfig = kRGBA_8888_sint_GrPixelConfig;
     45     desc.fWidth = kS;
     46     desc.fHeight = kS;
     47 
     48     std::unique_ptr<int32_t[]> testData(new int32_t[kS * kS]);
     49     for (int j = 0; j < kS; ++j) {
     50         for (int i = 0; i < kS; ++i) {
     51             uint32_t r = i - INT8_MIN;
     52             uint32_t g = j - INT8_MIN;
     53             uint32_t b = INT8_MAX - r;
     54             uint32_t a = INT8_MAX - g;
     55             testData.get()[j * kS + i] = (a << 24) | (b << 16) | (g << 8) | r;
     56         }
     57     }
     58 
     59     // Test that attempting to create a integer texture with multiple MIP levels fails.
     60     {
     61         GrMipLevel levels[2];
     62         levels[0].fPixels = testData.get();
     63         levels[0].fRowBytes = kRowBytes;
     64         levels[1].fPixels = testData.get();
     65         levels[1].fRowBytes = (kS / 2) * sizeof(int32_t);
     66 
     67         sk_sp<GrTexture> temp(context->resourceProvider()->createMipMappedTexture(desc,
     68                                                                                   SkBudgeted::kYes,
     69                                                                                   levels, 2));
     70         REPORTER_ASSERT(reporter, !temp);
     71     }
     72 
     73     // Test that we can create an integer texture.
     74     sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
     75                                                                desc, SkBudgeted::kYes,
     76                                                                testData.get(),
     77                                                                kRowBytes);
     78     REPORTER_ASSERT(reporter, proxy);
     79     if (!proxy) {
     80         return;
     81     }
     82 
     83     GrTexture* texture = proxy->instantiate(context->resourceProvider());
     84     REPORTER_ASSERT(reporter, texture);
     85     if (!texture) {
     86         return;
     87     }
     88 
     89     std::unique_ptr<int32_t[]> readData(new int32_t[kS * kS]);
     90     // Test that reading to a non-integer config fails.
     91     {
     92         bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_GrPixelConfig, readData.get());
     93         REPORTER_ASSERT(reporter, !success);
     94     }
     95     {
     96         std::unique_ptr<uint16_t[]> halfData(new uint16_t[4 * kS * kS]);
     97         bool success = texture->readPixels(0, 0, kS, kS, kRGBA_half_GrPixelConfig, halfData.get());
     98         REPORTER_ASSERT(reporter, !success);
     99     }
    100     {
    101         // Can read back as ints. (ES only requires being able to read back into 32bit ints which
    102         // we don't support. Right now this test is counting on GR_RGBA_INTEGER/GL_BYTE being the
    103         // implementation-dependent second format).
    104         sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
    105         bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig,
    106                                            readData.get());
    107         REPORTER_ASSERT(reporter, success);
    108         if (success) {
    109             check_pixels(reporter, kS, kS, testData.get(), readData.get(), "readPixels");
    110         }
    111     }
    112     {
    113         // readPixels should fail if we attempt to use the unpremul flag with an integer texture.
    114         bool success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig,
    115                                            readData.get(), 0, GrContext::kUnpremul_PixelOpsFlag);
    116         REPORTER_ASSERT(reporter, !success);
    117     }
    118 
    119     // Test that copying from one integer texture to another succeeds.
    120     {
    121         sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, desc,
    122                                                                     proxy.get()));
    123         REPORTER_ASSERT(reporter, dstContext);
    124         if (!dstContext || !dstContext->asTextureProxy()) {
    125             return;
    126         }
    127 
    128         GrSurface* copySurface = dstContext->asTextureProxy()->instantiate(
    129                                                                     context->resourceProvider());
    130         REPORTER_ASSERT(reporter, copySurface);
    131         if (!copySurface) {
    132             return;
    133         }
    134 
    135         sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
    136         bool success = copySurface->readPixels(0, 0, kS, kS,
    137                                                kRGBA_8888_sint_GrPixelConfig, readData.get());
    138         REPORTER_ASSERT(reporter, success);
    139         if (success) {
    140             check_pixels(reporter, kS, kS, testData.get(), readData.get(), "copyIntegerToInteger");
    141         }
    142     }
    143 
    144 
    145     // Test that copying to a non-integer (8888) texture fails.
    146     {
    147         GrSurfaceDesc nonIntDesc = desc;
    148         nonIntDesc.fConfig = kRGBA_8888_GrPixelConfig;
    149 
    150         sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
    151                                                                     proxy.get()));
    152         REPORTER_ASSERT(reporter, !dstContext);
    153     }
    154 
    155     // Test that copying to a non-integer (RGBA_half) texture fails.
    156     if (context->caps()->isConfigTexturable(kRGBA_half_GrPixelConfig)) {
    157         GrSurfaceDesc nonIntDesc = desc;
    158         nonIntDesc.fConfig = kRGBA_half_GrPixelConfig;
    159 
    160         sk_sp<GrSurfaceContext> dstContext(GrSurfaceProxy::TestCopy(context, nonIntDesc,
    161                                                                     proxy.get()));
    162         REPORTER_ASSERT(reporter, !dstContext);
    163     }
    164 
    165     // We overwrite the top left quarter of the texture with the bottom right quarter of the
    166     // original data.
    167     const void* bottomRightQuarter = testData.get() + kS / 2 * kS + kS / 2;
    168 
    169     {
    170         // Can't write pixels from a non-int config.
    171         bool success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_GrPixelConfig,
    172                                             bottomRightQuarter, kRowBytes);
    173         REPORTER_ASSERT(reporter, !success);
    174     }
    175     {
    176         // Can't use unpremul flag.
    177         bool success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
    178                                             bottomRightQuarter, kRowBytes,
    179                                             GrContext::kUnpremul_PixelOpsFlag);
    180         REPORTER_ASSERT(reporter, !success);
    181     }
    182     {
    183         bool success = texture->writePixels(0, 0, kS/2, kS/2, kRGBA_8888_sint_GrPixelConfig,
    184                                             bottomRightQuarter, kRowBytes);
    185         REPORTER_ASSERT(reporter, success);
    186         if (!success) {
    187             return;
    188         }
    189 
    190         sk_bzero(readData.get(), sizeof(int32_t) * kS * kS);
    191         success = texture->readPixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, readData.get());
    192         REPORTER_ASSERT(reporter, success);
    193         if (!success) {
    194             return;
    195         }
    196         std::unique_ptr<int32_t[]> overwrittenTestData(new int32_t[kS * kS]);
    197         memcpy(overwrittenTestData.get(), testData.get(), sizeof(int32_t) * kS * kS);
    198         char* dst = (char*)overwrittenTestData.get();
    199         char* src = (char*)(testData.get() + kS/2 * kS + kS/2);
    200         for (int i = 0; i < kS/2; ++i) {
    201             memcpy(dst, src, sizeof(int32_t) * kS/2);
    202             dst += kRowBytes;
    203             src += kRowBytes;
    204         }
    205         check_pixels(reporter, kS, kS, overwrittenTestData.get(), readData.get(), "overwrite");
    206     }
    207 
    208     // Test drawing from the integer texture to a fixed point texture. To avoid any premul issues
    209     // we init the int texture with 0s and 1s and make alpha always be 1. We expect that 1s turn
    210     // into 0xffs and zeros stay zero.
    211     std::unique_ptr<uint32_t[]> expectedData(new uint32_t[kS * kS]);
    212     std::unique_ptr<uint32_t[]> actualData(new uint32_t[kS * kS]);
    213     for (int i = 0; i < kS*kS; ++i) {
    214         int32_t a = 0x1;
    215         int32_t b = ((i & 0x1) ? 1 : 0);
    216         int32_t g = ((i & 0x1) ? 0 : 1);
    217         int32_t r = ((i & 0x2) ? 1 : 0);
    218         testData.get()[i] = (a << 24) | (b << 16) | (g << 8) | r;
    219         expectedData.get()[i] = ((0xFF * a) << 24) | ((0xFF * b) << 16) |
    220                                 ((0xFF * g) << 8) | (0xFF * r);
    221     }
    222     texture->writePixels(0, 0, kS, kS, kRGBA_8888_sint_GrPixelConfig, testData.get());
    223 
    224     sk_sp<GrRenderTargetContext> rtContext = context->makeRenderTargetContext(
    225             SkBackingFit::kExact, kS, kS, kRGBA_8888_GrPixelConfig, nullptr);
    226 
    227     struct {
    228         GrSamplerParams::FilterMode fMode;
    229         const char* fName;
    230     } kNamedFilters[] ={
    231         { GrSamplerParams::kNone_FilterMode, "filter-none" },
    232         { GrSamplerParams::kBilerp_FilterMode, "filter-bilerp" },
    233         { GrSamplerParams::kMipMap_FilterMode, "filter-mipmap" }
    234     };
    235 
    236     for (auto filter : kNamedFilters) {
    237         sk_sp<GrFragmentProcessor> fp(GrSimpleTextureEffect::Make(texture, nullptr,
    238                                                                   SkMatrix::I(),
    239                                                                   filter.fMode));
    240         REPORTER_ASSERT(reporter, fp);
    241         if (!fp) {
    242             return;
    243         }
    244         rtContext->clear(nullptr, 0xDDAABBCC, true);
    245         GrPaint paint;
    246         paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
    247         paint.addColorFragmentProcessor(fp);
    248         rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
    249         SkImageInfo readInfo = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
    250                                                  kPremul_SkAlphaType);
    251         rtContext->readPixels(readInfo, actualData.get(), 0, 0, 0);
    252         check_pixels(reporter, kS, kS, expectedData.get(), actualData.get(), filter.fName);
    253     }
    254 
    255     {
    256         // No rendering to integer textures.
    257         GrSurfaceDesc intRTDesc = desc;
    258         intRTDesc.fFlags = kRenderTarget_GrSurfaceFlag;
    259         sk_sp<GrTexture> temp(context->resourceProvider()->createTexture(intRTDesc,
    260                                                                          SkBudgeted::kYes));
    261         REPORTER_ASSERT(reporter, !temp);
    262     }
    263 }
    264 
    265 #endif
    266