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 18static 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 33static 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. 43GrGLTexture::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 52GrGLTexture::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 61GrGLTexture::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 69void 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 78void 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 89void GrGLTexture::onAbandon() { 90 fInfo.fTarget = 0; 91 fInfo.fID = 0; 92 this->invokeReleaseProc(); 93 INHERITED::onAbandon(); 94} 95 96GrBackendObject GrGLTexture::getTextureHandle() const { 97 return reinterpret_cast<GrBackendObject>(&fInfo); 98} 99 100GrBackendTexture GrGLTexture::getBackendTexture() const { 101 return GrBackendTexture(this->width(), this->height(), this->texturePriv().mipMapped(), fInfo); 102} 103 104sk_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 109bool 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 122void 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