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 "GrContext.h" 9#include "GrGLTexture.h" 10#include "GrGLGpu.h" 11#include "GrResourceProvider.h" 12#include "GrSemaphore.h" 13#include "GrShaderCaps.h" 14#include "SkMakeUnique.h" 15#include "SkTraceMemoryDump.h" 16 17#define GPUGL static_cast<GrGLGpu*>(this->getGpu()) 18#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X) 19 20static inline GrSLType sampler_type(const GrGLTexture::IDDesc& idDesc, GrPixelConfig config, 21 const GrGLGpu* gpu) { 22 if (idDesc.fInfo.fTarget == GR_GL_TEXTURE_EXTERNAL) { 23 SkASSERT(gpu->caps()->shaderCaps()->externalTextureSupport()); 24 SkASSERT(!GrPixelConfigIsSint(config)); 25 return kTextureExternalSampler_GrSLType; 26 } else if (idDesc.fInfo.fTarget == GR_GL_TEXTURE_RECTANGLE) { 27 SkASSERT(gpu->glCaps().rectangleTextureSupport()); 28 SkASSERT(!GrPixelConfigIsSint(config)); 29 return kTexture2DRectSampler_GrSLType; 30 } else if (GrPixelConfigIsSint(config)) { 31 return kITexture2DSampler_GrSLType; 32 } else { 33 SkASSERT(idDesc.fInfo.fTarget == GR_GL_TEXTURE_2D); 34 return kTexture2DSampler_GrSLType; 35 } 36} 37 38static inline GrSamplerParams::FilterMode highest_filter_mode(const GrGLTexture::IDDesc& idDesc, 39 GrPixelConfig config) { 40 if (GrPixelConfigIsSint(config)) { 41 // Integer textures in GL can use GL_NEAREST_MIPMAP_NEAREST. This is a mode we don't support 42 // and don't currently have a use for. 43 return GrSamplerParams::kNone_FilterMode; 44 } 45 if (idDesc.fInfo.fTarget == GR_GL_TEXTURE_RECTANGLE || 46 idDesc.fInfo.fTarget == GR_GL_TEXTURE_EXTERNAL) { 47 return GrSamplerParams::kBilerp_FilterMode; 48 } 49 return GrSamplerParams::kMipMap_FilterMode; 50} 51 52// Because this class is virtually derived from GrSurface we must explicitly call its constructor. 53GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc, 54 const IDDesc& idDesc) 55 : GrSurface(gpu, desc) 56 , INHERITED(gpu, desc, sampler_type(idDesc, desc.fConfig, gpu), 57 highest_filter_mode(idDesc, desc.fConfig), false) { 58 this->init(desc, idDesc); 59 this->registerWithCache(budgeted); 60} 61 62GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc, 63 const IDDesc& idDesc, 64 bool wasMipMapDataProvided) 65 : GrSurface(gpu, desc) 66 , INHERITED(gpu, desc, sampler_type(idDesc, desc.fConfig, gpu), 67 highest_filter_mode(idDesc, desc.fConfig), 68 wasMipMapDataProvided) { 69 this->init(desc, idDesc); 70 this->registerWithCache(budgeted); 71} 72 73GrGLTexture::GrGLTexture(GrGLGpu* gpu, Wrapped, const GrSurfaceDesc& desc, const IDDesc& idDesc) 74 : GrSurface(gpu, desc) 75 , INHERITED(gpu, desc, sampler_type(idDesc, desc.fConfig, gpu), 76 highest_filter_mode(idDesc, desc.fConfig), false) { 77 this->init(desc, idDesc); 78 this->registerWithCacheWrapped(); 79} 80 81GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc, 82 bool wasMipMapDataProvided) 83 : GrSurface(gpu, desc) 84 , INHERITED(gpu, desc, sampler_type(idDesc, desc.fConfig, gpu), 85 highest_filter_mode(idDesc, desc.fConfig), 86 wasMipMapDataProvided) { 87 this->init(desc, idDesc); 88} 89 90void GrGLTexture::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) { 91 SkASSERT(0 != idDesc.fInfo.fID); 92 fTexParams.invalidate(); 93 fTexParamsTimestamp = GrGpu::kExpiredTimestamp; 94 fInfo = idDesc.fInfo; 95 fTextureIDOwnership = idDesc.fOwnership; 96} 97 98void GrGLTexture::onRelease() { 99 if (fInfo.fID) { 100 if (GrBackendObjectOwnership::kBorrowed != fTextureIDOwnership) { 101 GL_CALL(DeleteTextures(1, &fInfo.fID)); 102 } 103 fInfo.fID = 0; 104 } 105 INHERITED::onRelease(); 106} 107 108void GrGLTexture::onAbandon() { 109 fInfo.fTarget = 0; 110 fInfo.fID = 0; 111 INHERITED::onAbandon(); 112} 113 114GrBackendObject GrGLTexture::getTextureHandle() const { 115 return reinterpret_cast<GrBackendObject>(&fInfo); 116} 117 118std::unique_ptr<GrExternalTextureData> GrGLTexture::detachBackendTexture() { 119 // Flush any pending writes to this texture 120 this->getContext()->prepareSurfaceForExternalIO(this); 121 122 // Set up a semaphore to be signaled once the data is ready, and flush GL 123 sk_sp<GrSemaphore> semaphore = this->getContext()->resourceProvider()->makeSemaphore(); 124 this->getGpu()->insertSemaphore(semaphore); 125 this->getGpu()->flush(); 126 127 // Make a copy of our GL-specific information 128 auto data = skstd::make_unique<GrGLExternalTextureData>(fInfo, std::move(semaphore), 129 this->getContext()); 130 131 // Ensure the cache can't reach this texture anymore 132 this->detachFromCache(); 133 134 // Detach from the GL object, so we don't use it (or try to delete it when we're freed) 135 fInfo.fTarget = 0; 136 fInfo.fID = 0; 137 138 return std::move(data); 139} 140 141void GrGLTexture::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, 142 const SkString& dumpName) const { 143 SkString texture_id; 144 texture_id.appendU32(this->textureID()); 145 traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture", 146 texture_id.c_str()); 147} 148 149sk_sp<GrGLTexture> GrGLTexture::MakeWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc, 150 const IDDesc& idDesc) { 151 return sk_sp<GrGLTexture>(new GrGLTexture(gpu, kWrapped, desc, idDesc)); 152} 153 154