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