Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2011 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 "GrGLTexture.h"
      9 #include "GrGLGpu.h"
     10 #include "GrSemaphore.h"
     11 #include "GrShaderCaps.h"
     12 #include "GrTexturePriv.h"
     13 #include "SkTraceMemoryDump.h"
     14 
     15 #define GPUGL static_cast<GrGLGpu*>(this->getGpu())
     16 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
     17 
     18 static inline GrSLType sampler_type(const GrGLTexture::IDDesc& idDesc, GrPixelConfig config,
     19                                     const GrGLGpu* gpu) {
     20     if (idDesc.fInfo.fTarget == GR_GL_TEXTURE_EXTERNAL) {
     21         SkASSERT(gpu->caps()->shaderCaps()->externalTextureSupport());
     22         return kTextureExternalSampler_GrSLType;
     23     } else if (idDesc.fInfo.fTarget == GR_GL_TEXTURE_RECTANGLE) {
     24         SkASSERT(gpu->glCaps().rectangleTextureSupport());
     25         return kTexture2DRectSampler_GrSLType;
     26     } else {
     27         SkASSERT(idDesc.fInfo.fTarget == GR_GL_TEXTURE_2D);
     28         return kTexture2DSampler_GrSLType;
     29     }
     30 }
     31 
     32 // This method parallels GrTextureProxy::highestFilterMode
     33 static inline GrSamplerState::Filter highest_filter_mode(const GrGLTexture::IDDesc& idDesc,
     34                                                          GrPixelConfig config) {
     35     if (idDesc.fInfo.fTarget == GR_GL_TEXTURE_RECTANGLE ||
     36         idDesc.fInfo.fTarget == GR_GL_TEXTURE_EXTERNAL) {
     37         return GrSamplerState::Filter::kBilerp;
     38     }
     39     return GrSamplerState::Filter::kMipMap;
     40 }
     41 
     42 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
     43 GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
     44                          const IDDesc& idDesc, GrMipMapsStatus mipMapsStatus)
     45     : GrSurface(gpu, desc)
     46     , INHERITED(gpu, desc, sampler_type(idDesc, desc.fConfig, gpu),
     47                 highest_filter_mode(idDesc, desc.fConfig), mipMapsStatus) {
     48     this->init(desc, idDesc);
     49     this->registerWithCache(budgeted);
     50 }
     51 
     52 GrGLTexture::GrGLTexture(GrGLGpu* gpu, Wrapped, const GrSurfaceDesc& desc,
     53                          GrMipMapsStatus mipMapsStatus, const IDDesc& idDesc)
     54     : GrSurface(gpu, desc)
     55     , INHERITED(gpu, desc, sampler_type(idDesc, desc.fConfig, gpu),
     56                 highest_filter_mode(idDesc, desc.fConfig), mipMapsStatus) {
     57     this->init(desc, idDesc);
     58     this->registerWithCacheWrapped();
     59 }
     60 
     61 GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
     62                          GrMipMapsStatus mipMapsStatus)
     63     : GrSurface(gpu, desc)
     64     , INHERITED(gpu, desc, sampler_type(idDesc, desc.fConfig, gpu),
     65                 highest_filter_mode(idDesc, desc.fConfig), mipMapsStatus) {
     66     this->init(desc, idDesc);
     67 }
     68 
     69 void GrGLTexture::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
     70     SkASSERT(0 != idDesc.fInfo.fID);
     71     SkASSERT(0 != idDesc.fInfo.fFormat);
     72     fTexParams.invalidate();
     73     fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
     74     fInfo = idDesc.fInfo;
     75     fTextureIDOwnership = idDesc.fOwnership;
     76 }
     77 
     78 void GrGLTexture::onRelease() {
     79     if (fInfo.fID) {
     80         if (GrBackendObjectOwnership::kBorrowed != fTextureIDOwnership) {
     81             GL_CALL(DeleteTextures(1, &fInfo.fID));
     82         }
     83         fInfo.fID = 0;
     84     }
     85     this->invokeReleaseProc();
     86     INHERITED::onRelease();
     87 }
     88 
     89 void GrGLTexture::onAbandon() {
     90     fInfo.fTarget = 0;
     91     fInfo.fID = 0;
     92     this->invokeReleaseProc();
     93     INHERITED::onAbandon();
     94 }
     95 
     96 GrBackendObject GrGLTexture::getTextureHandle() const {
     97     return reinterpret_cast<GrBackendObject>(&fInfo);
     98 }
     99 
    100 GrBackendTexture GrGLTexture::getBackendTexture() const {
    101     return GrBackendTexture(this->width(), this->height(), this->texturePriv().mipMapped(), fInfo);
    102 }
    103 
    104 sk_sp<GrGLTexture> GrGLTexture::MakeWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
    105                                             GrMipMapsStatus mipMapsStatus, const IDDesc& idDesc) {
    106     return sk_sp<GrGLTexture>(new GrGLTexture(gpu, kWrapped, desc, mipMapsStatus, idDesc));
    107 }
    108 
    109 bool GrGLTexture::onStealBackendTexture(GrBackendTexture* backendTexture,
    110                                         SkImage::BackendTextureReleaseProc* releaseProc) {
    111     *backendTexture = GrBackendTexture(width(), height(), config(), fInfo);
    112     // Set the release proc to a no-op function. GL doesn't require any special cleanup.
    113     *releaseProc = [](GrBackendTexture){};
    114 
    115     // It's important that we only abandon this texture's objects, not subclass objects such as
    116     // those held by GrGLTextureRenderTarget. Those objects are not being stolen and need to be
    117     // cleaned up by us.
    118     this->GrGLTexture::onAbandon();
    119     return true;
    120 }
    121 
    122 void GrGLTexture::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
    123     // Don't check this->fRefsWrappedObjects, as we might be the base of a GrGLTextureRenderTarget
    124     // which is multiply inherited from both ourselves and a texture. In these cases, one part
    125     // (texture, rt) may be wrapped, while the other is owned by Skia.
    126     bool refsWrappedTextureObjects =
    127             this->fTextureIDOwnership == GrBackendObjectOwnership::kBorrowed;
    128     if (refsWrappedTextureObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
    129         return;
    130     }
    131 
    132     // Dump as skia/gpu_resources/resource_#/texture, to avoid conflicts in the
    133     // GrGLTextureRenderTarget case, where multiple things may dump to the same resource. This
    134     // has no downside in the normal case.
    135     SkString resourceName = this->getResourceName();
    136     resourceName.append("/texture");
    137 
    138     // As we are only dumping our texture memory (not any additional memory tracked by classes
    139     // which may inherit from us), specifically call GrGLTexture::gpuMemorySize to avoid
    140     // hitting an override.
    141     this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "Texture",
    142                                    GrGLTexture::gpuMemorySize());
    143 
    144     SkString texture_id;
    145     texture_id.appendU32(this->textureID());
    146     traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_texture", texture_id.c_str());
    147 }
    148