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