Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2015 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "GrTextureProvider.h"
     10 #include "GrTexturePriv.h"
     11 #include "GrResourceCache.h"
     12 #include "GrGpu.h"
     13 
     14 enum ScratchTextureFlags {
     15     kExact_ScratchTextureFlag           = 0x1,
     16     kNoPendingIO_ScratchTextureFlag     = 0x2,
     17     kNoCreate_ScratchTextureFlag        = 0x4,
     18 };
     19 
     20 GrTexture* GrTextureProvider::createTexture(const GrSurfaceDesc& desc, bool budgeted,
     21                                             const void* srcData, size_t rowBytes) {
     22     if (this->isAbandoned()) {
     23         return NULL;
     24     }
     25     if ((desc.fFlags & kRenderTarget_GrSurfaceFlag) &&
     26         !fGpu->caps()->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
     27         return NULL;
     28     }
     29     if (!GrPixelConfigIsCompressed(desc.fConfig)) {
     30         static const uint32_t kFlags = kExact_ScratchTextureFlag |
     31                                        kNoCreate_ScratchTextureFlag;
     32         if (GrTexture* texture = this->internalRefScratchTexture(desc, kFlags)) {
     33             if (!srcData || texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
     34                                                  srcData, rowBytes)) {
     35                 if (!budgeted) {
     36                     texture->resourcePriv().makeUnbudgeted();
     37                 }
     38                 return texture;
     39             }
     40             texture->unref();
     41         }
     42     }
     43     return fGpu->createTexture(desc, budgeted, srcData, rowBytes);
     44 }
     45 
     46 GrTexture* GrTextureProvider::refScratchTexture(const GrSurfaceDesc& desc, ScratchTexMatch match,
     47                                                 bool calledDuringFlush) {
     48     if (this->isAbandoned()) {
     49         return NULL;
     50     }
     51     // Currently we don't recycle compressed textures as scratch.
     52     if (GrPixelConfigIsCompressed(desc.fConfig)) {
     53         return NULL;
     54     } else {
     55         uint32_t flags = 0;
     56         if (kExact_ScratchTexMatch == match) {
     57             flags |= kExact_ScratchTextureFlag;
     58         }
     59         if (calledDuringFlush) {
     60             flags |= kNoPendingIO_ScratchTextureFlag;
     61         }
     62         return this->internalRefScratchTexture(desc, flags);
     63     }
     64 }
     65 
     66 GrTexture* GrTextureProvider::internalRefScratchTexture(const GrSurfaceDesc& inDesc,
     67                                                         uint32_t flags) {
     68     SkASSERT(!this->isAbandoned());
     69     SkASSERT(!GrPixelConfigIsCompressed(inDesc.fConfig));
     70 
     71     SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc);
     72 
     73     if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
     74         if (!(kExact_ScratchTextureFlag & flags)) {
     75             // bin by pow2 with a reasonable min
     76             static const int MIN_SIZE = 16;
     77             GrSurfaceDesc* wdesc = desc.writable();
     78             wdesc->fWidth  = SkTMax(MIN_SIZE, GrNextPow2(desc->fWidth));
     79             wdesc->fHeight = SkTMax(MIN_SIZE, GrNextPow2(desc->fHeight));
     80         }
     81 
     82         GrScratchKey key;
     83         GrTexturePriv::ComputeScratchKey(*desc, &key);
     84         uint32_t scratchFlags = 0;
     85         if (kNoPendingIO_ScratchTextureFlag & flags) {
     86             scratchFlags = GrResourceCache::kRequireNoPendingIO_ScratchFlag;
     87         } else  if (!(desc->fFlags & kRenderTarget_GrSurfaceFlag)) {
     88             // If it is not a render target then it will most likely be populated by
     89             // writePixels() which will trigger a flush if the texture has pending IO.
     90             scratchFlags = GrResourceCache::kPreferNoPendingIO_ScratchFlag;
     91         }
     92         GrGpuResource* resource = fCache->findAndRefScratchResource(key, scratchFlags);
     93         if (resource) {
     94             GrSurface* surface = static_cast<GrSurface*>(resource);
     95             GrRenderTarget* rt = surface->asRenderTarget();
     96             if (rt && fGpu->caps()->discardRenderTargetSupport()) {
     97                 rt->discard();
     98             }
     99             return surface->asTexture();
    100         }
    101     }
    102 
    103     if (!(kNoCreate_ScratchTextureFlag & flags)) {
    104         return fGpu->createTexture(*desc, true, NULL, 0);
    105     }
    106 
    107     return NULL;
    108 }
    109 
    110 GrTexture* GrTextureProvider::wrapBackendTexture(const GrBackendTextureDesc& desc) {
    111     if (this->isAbandoned()) {
    112         return NULL;
    113     }
    114     return fGpu->wrapBackendTexture(desc);
    115 }
    116 
    117 GrRenderTarget* GrTextureProvider::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
    118     return this->isAbandoned() ? NULL : fGpu->wrapBackendRenderTarget(desc);
    119 }
    120 
    121 void GrTextureProvider::assignUniqueKeyToResource(const GrUniqueKey& key, GrGpuResource* resource) {
    122     if (this->isAbandoned() || !resource) {
    123         return;
    124     }
    125     resource->resourcePriv().setUniqueKey(key);
    126 }
    127 
    128 bool GrTextureProvider::existsResourceWithUniqueKey(const GrUniqueKey& key) const {
    129     return this->isAbandoned() ? false : fCache->hasUniqueKey(key);
    130 }
    131 
    132 GrGpuResource* GrTextureProvider::findAndRefResourceByUniqueKey(const GrUniqueKey& key) {
    133     return this->isAbandoned() ? NULL : fCache->findAndRefUniqueResource(key);
    134 }
    135