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 SkASSERT(!GrPixelConfigIsSint(config));
23 return kTextureExternalSampler_GrSLType;
24 } else if (idDesc.fInfo.fTarget == GR_GL_TEXTURE_RECTANGLE) {
25 SkASSERT(gpu->glCaps().rectangleTextureSupport());
26 SkASSERT(!GrPixelConfigIsSint(config));
27 return kTexture2DRectSampler_GrSLType;
28 } else if (GrPixelConfigIsSint(config)) {
29 return kITexture2DSampler_GrSLType;
30 } else {
31 SkASSERT(idDesc.fInfo.fTarget == GR_GL_TEXTURE_2D);
32 return kTexture2DSampler_GrSLType;
33 }
34 }
35
36 // This method parallels GrTextureProxy::highestFilterMode
highest_filter_mode(const GrGLTexture::IDDesc & idDesc,GrPixelConfig config)37 static inline GrSamplerState::Filter highest_filter_mode(const GrGLTexture::IDDesc& idDesc,
38 GrPixelConfig config) {
39 if (GrPixelConfigIsSint(config)) {
40 // Integer textures in GL can use GL_NEAREST_MIPMAP_NEAREST. This is a mode we don't support
41 // and don't currently have a use for.
42 return GrSamplerState::Filter::kNearest;
43 }
44 if (idDesc.fInfo.fTarget == GR_GL_TEXTURE_RECTANGLE ||
45 idDesc.fInfo.fTarget == GR_GL_TEXTURE_EXTERNAL) {
46 return GrSamplerState::Filter::kBilerp;
47 }
48 return GrSamplerState::Filter::kMipMap;
49 }
50
51 // 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)52 GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
53 const IDDesc& idDesc, GrMipMapsStatus mipMapsStatus)
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->registerWithCache(budgeted);
59 }
60
GrGLTexture(GrGLGpu * gpu,Wrapped,const GrSurfaceDesc & desc,GrMipMapsStatus mipMapsStatus,const IDDesc & idDesc)61 GrGLTexture::GrGLTexture(GrGLGpu* gpu, Wrapped, const GrSurfaceDesc& desc,
62 GrMipMapsStatus mipMapsStatus, const IDDesc& idDesc)
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 this->registerWithCacheWrapped();
68 }
69
GrGLTexture(GrGLGpu * gpu,const GrSurfaceDesc & desc,const IDDesc & idDesc,GrMipMapsStatus mipMapsStatus)70 GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
71 GrMipMapsStatus mipMapsStatus)
72 : GrSurface(gpu, desc)
73 , INHERITED(gpu, desc, sampler_type(idDesc, desc.fConfig, gpu),
74 highest_filter_mode(idDesc, desc.fConfig), mipMapsStatus) {
75 this->init(desc, idDesc);
76 }
77
init(const GrSurfaceDesc & desc,const IDDesc & idDesc)78 void GrGLTexture::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
79 SkASSERT(0 != idDesc.fInfo.fID);
80 SkASSERT(0 != idDesc.fInfo.fFormat);
81 fTexParams.invalidate();
82 fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
83 fInfo = idDesc.fInfo;
84 fTextureIDOwnership = idDesc.fOwnership;
85 }
86
onRelease()87 void GrGLTexture::onRelease() {
88 if (fInfo.fID) {
89 if (GrBackendObjectOwnership::kBorrowed != fTextureIDOwnership) {
90 GL_CALL(DeleteTextures(1, &fInfo.fID));
91 }
92 fInfo.fID = 0;
93 }
94 this->invokeReleaseProc();
95 INHERITED::onRelease();
96 }
97
onAbandon()98 void GrGLTexture::onAbandon() {
99 fInfo.fTarget = 0;
100 fInfo.fID = 0;
101 this->invokeReleaseProc();
102 INHERITED::onAbandon();
103 }
104
getTextureHandle() const105 GrBackendObject GrGLTexture::getTextureHandle() const {
106 return reinterpret_cast<GrBackendObject>(&fInfo);
107 }
108
getBackendTexture() const109 GrBackendTexture GrGLTexture::getBackendTexture() const {
110 return GrBackendTexture(this->width(), this->height(), this->texturePriv().mipMapped(), fInfo);
111 }
112
setMemoryBacking(SkTraceMemoryDump * traceMemoryDump,const SkString & dumpName) const113 void GrGLTexture::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
114 const SkString& dumpName) const {
115 SkString texture_id;
116 texture_id.appendU32(this->textureID());
117 traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
118 texture_id.c_str());
119 }
120
MakeWrapped(GrGLGpu * gpu,const GrSurfaceDesc & desc,GrMipMapsStatus mipMapsStatus,const IDDesc & idDesc)121 sk_sp<GrGLTexture> GrGLTexture::MakeWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
122 GrMipMapsStatus mipMapsStatus, const IDDesc& idDesc) {
123 return sk_sp<GrGLTexture>(new GrGLTexture(gpu, kWrapped, desc, mipMapsStatus, idDesc));
124 }
125
onStealBackendTexture(GrBackendTexture * backendTexture,SkImage::BackendTextureReleaseProc * releaseProc)126 bool GrGLTexture::onStealBackendTexture(GrBackendTexture* backendTexture,
127 SkImage::BackendTextureReleaseProc* releaseProc) {
128 *backendTexture = GrBackendTexture(width(), height(), config(), fInfo);
129 // Set the release proc to a no-op function. GL doesn't require any special cleanup.
130 *releaseProc = [](GrBackendTexture){};
131
132 // It's important that we only abandon this texture's objects, not subclass objects such as
133 // those held by GrGLTextureRenderTarget. Those objects are not being stolen and need to be
134 // cleaned up by us.
135 this->GrGLTexture::onAbandon();
136 return true;
137 }
138