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 
sampler_type(const GrGLTexture::IDDesc & idDesc,GrPixelConfig config,const GrGLGpu * gpu)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
highest_filter_mode(const GrGLTexture::IDDesc & idDesc,GrPixelConfig config)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.
GrGLTexture(GrGLGpu * gpu,SkBudgeted budgeted,const GrSurfaceDesc & desc,const IDDesc & idDesc,GrMipMapsStatus mipMapsStatus)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 
GrGLTexture(GrGLGpu * gpu,Wrapped,const GrSurfaceDesc & desc,GrMipMapsStatus mipMapsStatus,const IDDesc & idDesc)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 
GrGLTexture(GrGLGpu * gpu,const GrSurfaceDesc & desc,const IDDesc & idDesc,GrMipMapsStatus mipMapsStatus)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 
init(const GrSurfaceDesc & desc,const IDDesc & idDesc)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 
onRelease()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 
onAbandon()89 void GrGLTexture::onAbandon() {
90     fInfo.fTarget = 0;
91     fInfo.fID = 0;
92     this->invokeReleaseProc();
93     INHERITED::onAbandon();
94 }
95 
getTextureHandle() const96 GrBackendObject GrGLTexture::getTextureHandle() const {
97     return reinterpret_cast<GrBackendObject>(&fInfo);
98 }
99 
getBackendTexture() const100 GrBackendTexture GrGLTexture::getBackendTexture() const {
101     return GrBackendTexture(this->width(), this->height(), this->texturePriv().mipMapped(), fInfo);
102 }
103 
setMemoryBacking(SkTraceMemoryDump * traceMemoryDump,const SkString & dumpName) const104 void GrGLTexture::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
105                                    const SkString& dumpName) const {
106     SkString texture_id;
107     texture_id.appendU32(this->textureID());
108     traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
109                                       texture_id.c_str());
110 }
111 
MakeWrapped(GrGLGpu * gpu,const GrSurfaceDesc & desc,GrMipMapsStatus mipMapsStatus,const IDDesc & idDesc)112 sk_sp<GrGLTexture> GrGLTexture::MakeWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
113                                             GrMipMapsStatus mipMapsStatus, const IDDesc& idDesc) {
114     return sk_sp<GrGLTexture>(new GrGLTexture(gpu, kWrapped, desc, mipMapsStatus, idDesc));
115 }
116 
onStealBackendTexture(GrBackendTexture * backendTexture,SkImage::BackendTextureReleaseProc * releaseProc)117 bool GrGLTexture::onStealBackendTexture(GrBackendTexture* backendTexture,
118                                         SkImage::BackendTextureReleaseProc* releaseProc) {
119     *backendTexture = GrBackendTexture(width(), height(), config(), fInfo);
120     // Set the release proc to a no-op function. GL doesn't require any special cleanup.
121     *releaseProc = [](GrBackendTexture){};
122 
123     // It's important that we only abandon this texture's objects, not subclass objects such as
124     // those held by GrGLTextureRenderTarget. Those objects are not being stolen and need to be
125     // cleaned up by us.
126     this->GrGLTexture::onAbandon();
127     return true;
128 }
129