Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2015 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 "GrTextureProvider.h"
      9 #include "GrTexturePriv.h"
     10 #include "GrResourceCache.h"
     11 #include "GrGpu.h"
     12 #include "../private/GrSingleOwner.h"
     13 
     14 #define ASSERT_SINGLE_OWNER \
     15     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
     16 
     17 enum ScratchTextureFlags {
     18     kExact_ScratchTextureFlag           = 0x1,
     19     kNoPendingIO_ScratchTextureFlag     = 0x2,
     20     kNoCreate_ScratchTextureFlag        = 0x4,
     21 };
     22 
     23 GrTextureProvider::GrTextureProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* singleOwner)
     24     : fCache(cache)
     25     , fGpu(gpu)
     26 #ifdef SK_DEBUG
     27     , fSingleOwner(singleOwner)
     28 #endif
     29     {
     30 }
     31 
     32 GrTexture* GrTextureProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
     33                                             const void* srcData, size_t rowBytes) {
     34     ASSERT_SINGLE_OWNER
     35     if (this->isAbandoned()) {
     36         return nullptr;
     37     }
     38     if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) &&
     39         !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
     40         return nullptr;
     41     }
     42     if (!GrPixelConfigIsCompressed(desc.fConfig) &&
     43         !desc.fTextureStorageAllocator.fAllocateTextureStorage) {
     44         static const uint32_t kFlags = kExact_ScratchTextureFlag |
     45                                        kNoCreate_ScratchTextureFlag;
     46         if (GrTexture* texture = this->refScratchTexture(desc, kFlags)) {
     47             if (!srcData || texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
     48                                                  srcData, rowBytes)) {
     49                 if (SkBudgeted::kNo == budgeted) {
     50                     texture->resourcePriv().makeUnbudgeted();
     51                 }
     52                 return texture;
     53             }
     54             texture->unref();
     55         }
     56     }
     57     return fGpu->createTexture(desc, budgeted, srcData, rowBytes);
     58 }
     59 
     60 GrTexture* GrTextureProvider::createApproxTexture(const GrSurfaceDesc& desc) {
     61     ASSERT_SINGLE_OWNER
     62     return this->internalCreateApproxTexture(desc, 0);
     63 }
     64 
     65 GrTexture* GrTextureProvider::internalCreateApproxTexture(const GrSurfaceDesc& desc,
     66                                                           uint32_t scratchFlags) {
     67     ASSERT_SINGLE_OWNER
     68     if (this->isAbandoned()) {
     69         return nullptr;
     70     }
     71     // Currently we don't recycle compressed textures as scratch.
     72     if (GrPixelConfigIsCompressed(desc.fConfig)) {
     73         return nullptr;
     74     } else {
     75         return this->refScratchTexture(desc, scratchFlags);
     76     }
     77 }
     78 
     79 GrTexture* GrTextureProvider::refScratchTexture(const GrSurfaceDesc& inDesc,
     80                                                 uint32_t flags) {
     81     ASSERT_SINGLE_OWNER
     82     SkASSERT(!this->isAbandoned());
     83     SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig));
     84 
     85     SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
     86 
     87     if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
     88         if (!(kExact_ScratchTextureFlag & flags)) {
     89             // bin by pow2 with a reasonable min
     90             const int kMinSize = 16;
     91             GrSurfaceDesc* wdesc = desc.writable();
     92             wdesc->fWidth  = SkTMax(kMinSize, GrNextPow2(desc->fWidth));
     93             wdesc->fHeight = SkTMax(kMinSize, GrNextPow2(desc->fHeight));
     94         }
     95 
     96         GrScratchKey key;
     97         GrTexturePriv::ComputeScratchKey(*desc, &key);
     98         uint32_t scratchFlags = 0;
     99         if (kNoPendingIO_ScratchTextureFlag & flags) {
    100             scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
    101         } else  if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
    102             // If it is not a render target then it will most likely be populated by
    103             // writePixels() which will trigger a flush if the texture has pending IO.
    104             scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
    105         }
    106         GrGpuResource* resource = fCache->findAndRefScratchResource(key,
    107                                                                    GrSurface::WorseCaseSize(*desc),
    108                                                                    scratchFlags);
    109         if (resource) {
    110             GrSurface* surface = static_cast<GrSurface*>(resource);
    111             GrRenderTarget* rt = surface->asRenderTarget();
    112             if (rt && fGpu->caps()->discardRenderTargetSupport()) {
    113                 rt->discard();
    114             }
    115             return surface->asTexture();
    116         }
    117     }
    118 
    119     if (!(kNoCreate_ScratchTextureFlag & flags)) {
    120         return fGpu->createTexture(*desc, SkBudgeted::kYes, nullptr, 0);
    121     }
    122 
    123     return nullptr;
    124 }
    125 
    126 GrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc,
    127                                                  GrWrapOwnership ownership) {
    128     ASSERT_SINGLE_OWNER
    129     if (this->isAbandoned()) {
    130         return nullptr;
    131     }
    132     return fGpu->wrapBackendTexture(desc, ownership);
    133 }
    134 
    135 GrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
    136     ASSERT_SINGLE_OWNER
    137     return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(desc,
    138                                                                          kBorrow_GrWrapOwnership);
    139 }
    140 
    141 void GrTextureProvider::assignUniqueKeyToResource(const GrUniqueKey& key, GrGpuResource* resource) {
    142     ASSERT_SINGLE_OWNER
    143     if (this->isAbandoned() || !resource) {
    144         return;
    145     }
    146     resource->resourcePriv().setUniqueKey(key);
    147 }
    148 
    149 bool GrTextureProvider::existsResourceWithUniqueKey(const GrUniqueKey& key) const {
    150     ASSERT_SINGLE_OWNER
    151     return this->isAbandoned() ? false : fCache->hasUniqueKey(key);
    152 }
    153 
    154 GrGpuResource* GrTextureProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) {
    155     ASSERT_SINGLE_OWNER
    156     return this->isAbandoned() ? nullptr : fCache->findAndRefUniqueResource(key);
    157 }
    158 
    159 GrTexture* GrTextureProvider::findAndRefTextureByUniqueKey(const GrUniqueKey& key) {
    160     ASSERT_SINGLE_OWNER
    161     GrGpuResource* resource = this->findAndRefResourceByUniqueKey(key);
    162     if (resource) {
    163         GrTexture* texture = static_cast<GrSurface*>(resource)->asTexture();
    164         SkASSERT(texture);
    165         return texture;
    166     }
    167     return NULL;
    168 }
    169