Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2017 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 "SkTypes.h"
      9 
     10 #include "GrBackendSurface.h"
     11 #include "GrBackendTextureImageGenerator.h"
     12 #include "GrContext.h"
     13 #include "GrContextPriv.h"
     14 #include "GrGpu.h"
     15 #include "GrRenderTargetContext.h"
     16 #include "GrSemaphore.h"
     17 #include "GrSurfaceProxyPriv.h"
     18 #include "GrTexturePriv.h"
     19 #include "GrTextureProxy.h"
     20 #include "SkCanvas.h"
     21 #include "SkImage_Base.h"
     22 #include "SkGpuDevice.h"
     23 #include "SkPoint.h"
     24 #include "SkSurface.h"
     25 #include "SkSurface_Gpu.h"
     26 #include "Test.h"
     27 
     28 static constexpr int kSize = 8;
     29 
     30 // Test that the correct mip map states are on the GrTextures when wrapping GrBackendTextures in
     31 // SkImages and SkSurfaces
     32 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrWrappedMipMappedTest, reporter, ctxInfo) {
     33     GrContext* context = ctxInfo.grContext();
     34     if (!context->priv().caps()->mipMapSupport()) {
     35         return;
     36     }
     37     GrGpu* gpu = context->priv().getGpu();
     38 
     39     for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
     40         for (auto isRT : {false, true}) {
     41             // CreateTestingOnlyBackendTexture currently doesn't support uploading data to mip maps
     42             // so we don't send any. However, we pretend there is data for the checks below which is
     43             // fine since we are never actually using these textures for any work on the gpu.
     44             GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
     45                     nullptr, kSize, kSize, GrColorType::kRGBA_8888, isRT, mipMapped);
     46 
     47             sk_sp<GrTextureProxy> proxy;
     48             sk_sp<SkImage> image;
     49             if (isRT) {
     50                 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTexture(
     51                                                                            context,
     52                                                                            backendTex,
     53                                                                            kTopLeft_GrSurfaceOrigin,
     54                                                                            0,
     55                                                                            kRGBA_8888_SkColorType,
     56                                                                            nullptr,
     57                                                                            nullptr);
     58 
     59                 SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
     60                 proxy = device->accessRenderTargetContext()->asTextureProxyRef();
     61             } else {
     62                 image = SkImage::MakeFromTexture(context, backendTex,
     63                                                  kTopLeft_GrSurfaceOrigin,
     64                                                  kRGBA_8888_SkColorType,
     65                                                  kPremul_SkAlphaType, nullptr,
     66                                                  nullptr, nullptr);
     67                 proxy = as_IB(image)->asTextureProxyRef(context);
     68             }
     69             REPORTER_ASSERT(reporter, proxy);
     70             if (!proxy) {
     71                 gpu->deleteTestingOnlyBackendTexture(backendTex);
     72                 return;
     73             }
     74 
     75             REPORTER_ASSERT(reporter, proxy->isInstantiated());
     76 
     77             GrTexture* texture = proxy->peekTexture();
     78             REPORTER_ASSERT(reporter, texture);
     79             if (!texture) {
     80                 gpu->deleteTestingOnlyBackendTexture(backendTex);
     81                 return;
     82             }
     83 
     84             if (GrMipMapped::kYes == mipMapped) {
     85                 REPORTER_ASSERT(reporter, GrMipMapped::kYes == texture->texturePriv().mipMapped());
     86                 if (isRT) {
     87                     REPORTER_ASSERT(reporter, texture->texturePriv().mipMapsAreDirty());
     88                 } else {
     89                     REPORTER_ASSERT(reporter, !texture->texturePriv().mipMapsAreDirty());
     90                 }
     91             } else {
     92                 REPORTER_ASSERT(reporter, GrMipMapped::kNo == texture->texturePriv().mipMapped());
     93             }
     94             gpu->deleteTestingOnlyBackendTexture(backendTex);
     95         }
     96     }
     97 }
     98 
     99 // Test that we correctly copy or don't copy GrBackendTextures in the GrBackendTextureImageGenerator
    100 // based on if we will use mips in the draw and the mip status of the GrBackendTexture.
    101 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrBackendTextureImageMipMappedTest, reporter, ctxInfo) {
    102     GrContext* context = ctxInfo.grContext();
    103     if (!context->priv().caps()->mipMapSupport()) {
    104         return;
    105     }
    106     GrGpu* gpu = context->priv().getGpu();
    107 
    108     for (auto mipMapped : {GrMipMapped::kNo, GrMipMapped::kYes}) {
    109         for (auto willUseMips : {false, true}) {
    110             GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
    111                     nullptr, kSize, kSize, GrColorType::kRGBA_8888, false, mipMapped);
    112 
    113             sk_sp<SkImage> image = SkImage::MakeFromTexture(context, backendTex,
    114                                                             kTopLeft_GrSurfaceOrigin,
    115                                                             kRGBA_8888_SkColorType,
    116                                                             kPremul_SkAlphaType, nullptr,
    117                                                             nullptr, nullptr);
    118 
    119             GrTextureProxy* proxy = as_IB(image)->peekProxy();
    120             REPORTER_ASSERT(reporter, proxy);
    121             if (!proxy) {
    122                 gpu->deleteTestingOnlyBackendTexture(backendTex);
    123                 return;
    124             }
    125 
    126             REPORTER_ASSERT(reporter, proxy->isInstantiated());
    127 
    128             sk_sp<GrTexture> texture = sk_ref_sp(proxy->peekTexture());
    129             REPORTER_ASSERT(reporter, texture);
    130             if (!texture) {
    131                 gpu->deleteTestingOnlyBackendTexture(backendTex);
    132                 return;
    133             }
    134 
    135             std::unique_ptr<SkImageGenerator> imageGen = GrBackendTextureImageGenerator::Make(
    136                     texture, kTopLeft_GrSurfaceOrigin, nullptr, kRGBA_8888_SkColorType,
    137                     kPremul_SkAlphaType, nullptr);
    138             REPORTER_ASSERT(reporter, imageGen);
    139             if (!imageGen) {
    140                 gpu->deleteTestingOnlyBackendTexture(backendTex);
    141                 return;
    142             }
    143 
    144             SkIPoint origin = SkIPoint::Make(0,0);
    145             SkImageInfo imageInfo = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
    146                                                       kPremul_SkAlphaType);
    147             sk_sp<GrTextureProxy> genProxy = imageGen->generateTexture(context, imageInfo,
    148                                                                        origin, willUseMips);
    149 
    150             REPORTER_ASSERT(reporter, genProxy);
    151             if (!genProxy) {
    152                 gpu->deleteTestingOnlyBackendTexture(backendTex);
    153                 return;
    154             }
    155 
    156             if (GrSurfaceProxy::LazyState::kNot != genProxy->lazyInstantiationState()) {
    157                 genProxy->priv().doLazyInstantiation(context->priv().resourceProvider());
    158             } else if (!genProxy->isInstantiated()) {
    159                 genProxy->instantiate(context->priv().resourceProvider());
    160             }
    161 
    162             REPORTER_ASSERT(reporter, genProxy->isInstantiated());
    163             if (!genProxy->isInstantiated()) {
    164                 gpu->deleteTestingOnlyBackendTexture(backendTex);
    165                 return;
    166             }
    167 
    168             GrTexture* genTexture = genProxy->peekTexture();
    169             REPORTER_ASSERT(reporter, genTexture);
    170             if (!genTexture) {
    171                 gpu->deleteTestingOnlyBackendTexture(backendTex);
    172                 return;
    173             }
    174 
    175             GrBackendTexture genBackendTex = genTexture->getBackendTexture();
    176 
    177             if (GrBackendApi::kOpenGL == genBackendTex.backend()) {
    178                 GrGLTextureInfo genTexInfo;
    179                 GrGLTextureInfo origTexInfo;
    180                 if (genBackendTex.getGLTextureInfo(&genTexInfo) &&
    181                     backendTex.getGLTextureInfo(&origTexInfo)) {
    182                     if (willUseMips && GrMipMapped::kNo == mipMapped) {
    183                         // We did a copy so the texture IDs should be different
    184                         REPORTER_ASSERT(reporter, origTexInfo.fID != genTexInfo.fID);
    185                     } else {
    186                         REPORTER_ASSERT(reporter, origTexInfo.fID == genTexInfo.fID);
    187                     }
    188                 } else {
    189                     ERRORF(reporter, "Failed to get GrGLTextureInfo");
    190                 }
    191 #ifdef SK_VULKAN
    192             } else if (GrBackendApi::kVulkan == genBackendTex.backend()) {
    193                 GrVkImageInfo genImageInfo;
    194                 GrVkImageInfo origImageInfo;
    195                 if (genBackendTex.getVkImageInfo(&genImageInfo) &&
    196                     backendTex.getVkImageInfo(&origImageInfo)) {
    197                     if (willUseMips && GrMipMapped::kNo == mipMapped) {
    198                         // We did a copy so the texture IDs should be different
    199                         REPORTER_ASSERT(reporter, origImageInfo.fImage != genImageInfo.fImage);
    200                     } else {
    201                         REPORTER_ASSERT(reporter, origImageInfo.fImage == genImageInfo.fImage);
    202                     }
    203                 } else {
    204                     ERRORF(reporter, "Failed to get GrVkImageInfo");
    205                 }
    206 #endif
    207             } else {
    208                 REPORTER_ASSERT(reporter, false);
    209             }
    210 
    211             // Must make sure the uses of the backend texture have finished (we possibly have a
    212             // queued up copy) before we delete the backend texture.
    213             context->flush();
    214             gpu->testingOnly_flushGpuAndSync();
    215 
    216             gpu->deleteTestingOnlyBackendTexture(backendTex);
    217         }
    218     }
    219 }
    220 
    221 // Test that when we call makeImageSnapshot on an SkSurface we retains the same mip status as the
    222 // resource we took the snapshot of.
    223 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrImageSnapshotMipMappedTest, reporter, ctxInfo) {
    224     GrContext* context = ctxInfo.grContext();
    225     if (!context->priv().caps()->mipMapSupport()) {
    226         return;
    227     }
    228 
    229     auto resourceProvider = context->priv().resourceProvider();
    230     GrGpu* gpu = context->priv().getGpu();
    231 
    232     for (auto willUseMips : {false, true}) {
    233         for (auto isWrapped : {false, true}) {
    234             GrMipMapped mipMapped = willUseMips ? GrMipMapped::kYes : GrMipMapped::kNo;
    235             sk_sp<SkSurface> surface;
    236             GrBackendTexture backendTex = gpu->createTestingOnlyBackendTexture(
    237                     nullptr, kSize, kSize, GrColorType::kRGBA_8888, true, mipMapped);
    238             if (isWrapped) {
    239                 surface = SkSurface::MakeFromBackendTexture(context,
    240                                                             backendTex,
    241                                                             kTopLeft_GrSurfaceOrigin,
    242                                                             0,
    243                                                             kRGBA_8888_SkColorType,
    244                                                             nullptr,
    245                                                             nullptr);
    246             } else {
    247                 SkImageInfo info = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
    248                                                      kPremul_SkAlphaType);
    249                 surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 0,
    250                                                       kTopLeft_GrSurfaceOrigin, nullptr,
    251                                                       willUseMips);
    252             }
    253             REPORTER_ASSERT(reporter, surface);
    254             if (!surface) {
    255                 gpu->deleteTestingOnlyBackendTexture(backendTex);
    256             }
    257             SkGpuDevice* device = ((SkSurface_Gpu*)surface.get())->getDevice();
    258             GrTextureProxy* texProxy = device->accessRenderTargetContext()->asTextureProxy();
    259             REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
    260 
    261             texProxy->instantiate(resourceProvider);
    262             GrTexture* texture = texProxy->peekTexture();
    263             REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
    264 
    265             sk_sp<SkImage> image = surface->makeImageSnapshot();
    266             REPORTER_ASSERT(reporter, image);
    267             if (!image) {
    268                 gpu->deleteTestingOnlyBackendTexture(backendTex);
    269             }
    270             texProxy = as_IB(image)->peekProxy();
    271             REPORTER_ASSERT(reporter, mipMapped == texProxy->mipMapped());
    272 
    273             texProxy->instantiate(resourceProvider);
    274             texture = texProxy->peekTexture();
    275             REPORTER_ASSERT(reporter, mipMapped == texture->texturePriv().mipMapped());
    276 
    277             // Must flush the context to make sure all the cmds (copies, etc.) from above are sent
    278             // to the gpu before we delete the backendHandle.
    279             context->flush();
    280             gpu->testingOnly_flushGpuAndSync();
    281             gpu->deleteTestingOnlyBackendTexture(backendTex);
    282         }
    283     }
    284 }
    285 
    286 // Test that we don't create a mip mapped texture if the size is 1x1 even if the filter mode is set
    287 // to use mips. This test passes by not crashing or hitting asserts in code.
    288 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(Gr1x1TextureMipMappedTest, reporter, ctxInfo) {
    289     GrContext* context = ctxInfo.grContext();
    290     if (!context->priv().caps()->mipMapSupport()) {
    291         return;
    292     }
    293 
    294     // Make surface to draw into
    295     SkImageInfo info = SkImageInfo::MakeN32(16, 16, kPremul_SkAlphaType);
    296     sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info);
    297 
    298     // Make 1x1 raster bitmap
    299     SkBitmap bmp;
    300     bmp.allocN32Pixels(1, 1);
    301     SkPMColor* pixel = reinterpret_cast<SkPMColor*>(bmp.getPixels());
    302     *pixel = 0;
    303 
    304     sk_sp<SkImage> bmpImage = SkImage::MakeFromBitmap(bmp);
    305 
    306     // Make sure we scale so we don't optimize out the use of mips.
    307     surface->getCanvas()->scale(0.5f, 0.5f);
    308 
    309     SkPaint paint;
    310     // This should upload the image to a non mipped GrTextureProxy.
    311     surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
    312     surface->flush();
    313 
    314     // Now set the filter quality to high so we use mip maps. We should find the non mipped texture
    315     // in the cache for the SkImage. Since the texture is 1x1 we should just use that texture
    316     // instead of trying to do a copy to a mipped texture.
    317     paint.setFilterQuality(kHigh_SkFilterQuality);
    318     surface->getCanvas()->drawImage(bmpImage, 0, 0, &paint);
    319     surface->flush();
    320 }
    321 
    322