blob: 5e0a2fbd5fee729defb923ba0ef44bc71b6d440f [file] [log] [blame]
bsalomon@google.comaa5b6732011-07-29 15:13:20 +00001/*
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
bsalomon@google.comaa5b6732011-07-29 15:13:20 +00008#include "GrGLRenderTarget.h"
Eric Karl5c779752017-05-08 12:02:07 -07009#include "GrContext.h"
Brian Salomonc7fe0f72018-05-11 10:14:21 -040010#include "GrContextPriv.h"
jvanverth39edf762014-12-22 11:44:19 -080011#include "GrGLGpu.h"
egdanielec00d942015-09-14 12:56:10 -070012#include "GrGLUtil.h"
kkinnunen2e6055b2016-04-22 01:48:29 -070013#include "GrGpuResourcePriv.h"
14#include "GrRenderTargetPriv.h"
ericrk0a5fa482015-09-15 14:16:10 -070015#include "SkTraceMemoryDump.h"
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000016
egdanield803f272015-03-18 13:01:52 -070017#define GPUGL static_cast<GrGLGpu*>(this->getGpu())
18#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
bsalomon@google.com0b77d682011-08-19 13:28:54 +000019
bsalomon37dd3312014-11-03 08:47:23 -080020// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
kkinnunen2e6055b2016-04-22 01:48:29 -070021// Constructor for wrapped render targets.
egdanielec00d942015-09-14 12:56:10 -070022GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
23 const GrSurfaceDesc& desc,
Greg Daniel4065d452018-11-16 15:43:41 -050024 GrGLenum format,
egdanielec00d942015-09-14 12:56:10 -070025 const IDDesc& idDesc,
26 GrGLStencilAttachment* stencil)
kkinnunen2e6055b2016-04-22 01:48:29 -070027 : GrSurface(gpu, desc)
Robert Phillipsfe0253f2018-03-16 16:47:25 -040028 , INHERITED(gpu, desc, stencil) {
29 this->setFlags(gpu->glCaps(), idDesc);
Greg Daniel4065d452018-11-16 15:43:41 -050030 this->init(desc, format, idDesc);
kkinnunen2e6055b2016-04-22 01:48:29 -070031 this->registerWithCacheWrapped();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000032}
33
Greg Daniel4065d452018-11-16 15:43:41 -050034GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, GrGLenum format,
kkinnunen2e6055b2016-04-22 01:48:29 -070035 const IDDesc& idDesc)
36 : GrSurface(gpu, desc)
Robert Phillipsfe0253f2018-03-16 16:47:25 -040037 , INHERITED(gpu, desc) {
38 this->setFlags(gpu->glCaps(), idDesc);
Greg Daniel4065d452018-11-16 15:43:41 -050039 this->init(desc, format, idDesc);
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000040}
41
Robert Phillipsfe0253f2018-03-16 16:47:25 -040042inline void GrGLRenderTarget::setFlags(const GrGLCaps& glCaps, const IDDesc& idDesc) {
csmartdaltonf9635992016-08-10 11:09:07 -070043 if (idDesc.fIsMixedSampled) {
44 SkASSERT(glCaps.usesMixedSamples() && idDesc.fRTFBOID); // FBO 0 can't be mixed sampled.
Robert Phillipsfe0253f2018-03-16 16:47:25 -040045 this->setHasMixedSamples();
csmartdaltonf9635992016-08-10 11:09:07 -070046 }
Greg Daniela070ed72018-04-26 16:31:38 -040047 if (!idDesc.fRTFBOID) {
48 this->setGLRTFBOIDIs0();
49 }
csmartdaltonf9635992016-08-10 11:09:07 -070050}
51
Greg Daniel4065d452018-11-16 15:43:41 -050052void GrGLRenderTarget::init(const GrSurfaceDesc& desc, GrGLenum format, const IDDesc& idDesc) {
cdaltond4727922015-11-10 12:49:06 -080053 fRTFBOID = idDesc.fRTFBOID;
54 fTexFBOID = idDesc.fTexFBOID;
55 fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID;
kkinnunen2e6055b2016-04-22 01:48:29 -070056 fRTFBOOwnership = idDesc.fRTFBOOwnership;
bsalomon37dd3312014-11-03 08:47:23 -080057
Greg Daniel4065d452018-11-16 15:43:41 -050058 fRTFormat = format;
59
bsalomon37dd3312014-11-03 08:47:23 -080060 fViewport.fLeft = 0;
61 fViewport.fBottom = 0;
62 fViewport.fWidth = desc.fWidth;
63 fViewport.fHeight = desc.fHeight;
64
Robert Phillips29e52f12016-11-03 10:19:14 -040065 fNumSamplesOwnedPerPixel = this->totalSamples();
senorblancod2981212015-04-30 12:06:10 -070066}
67
bungeman6bd52842016-10-27 09:30:08 -070068sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu,
69 const GrSurfaceDesc& desc,
Greg Daniel4065d452018-11-16 15:43:41 -050070 GrGLenum format,
bungeman6bd52842016-10-27 09:30:08 -070071 const IDDesc& idDesc,
72 int stencilBits) {
egdanielec00d942015-09-14 12:56:10 -070073 GrGLStencilAttachment* sb = nullptr;
74 if (stencilBits) {
75 GrGLStencilAttachment::IDDesc sbDesc;
76 GrGLStencilAttachment::Format format;
77 format.fInternalFormat = GrGLStencilAttachment::kUnknownInternalFormat;
78 format.fPacked = false;
79 format.fStencilBits = stencilBits;
80 format.fTotalBits = stencilBits;
Robert Phillipscb2e2352017-08-30 16:44:40 -040081 // Ownership of sb is passed to the GrRenderTarget so doesn't need to be deleted
egdanielec00d942015-09-14 12:56:10 -070082 sb = new GrGLStencilAttachment(gpu, sbDesc, desc.fWidth, desc.fHeight,
83 desc.fSampleCnt, format);
84 }
Greg Daniel4065d452018-11-16 15:43:41 -050085 return sk_sp<GrGLRenderTarget>(new GrGLRenderTarget(gpu, desc, format, idDesc, sb));
egdanielec00d942015-09-14 12:56:10 -070086}
87
Greg Danielfaa095e2017-12-19 13:15:02 -050088GrBackendRenderTarget GrGLRenderTarget::getBackendRenderTarget() const {
89 GrGLFramebufferInfo fbi;
90 fbi.fFBOID = fRTFBOID;
91 fbi.fFormat = this->getGLGpu()->glCaps().configSizedInternalFormat(this->config());
Brian Salomon0c51eea2018-03-09 17:02:09 -050092 int numStencilBits = 0;
93 if (GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment()) {
94 numStencilBits = stencil->bits();
95 }
Greg Danielfaa095e2017-12-19 13:15:02 -050096
Greg Daniel8a3f55c2018-03-14 17:32:12 +000097 return GrBackendRenderTarget(this->width(), this->height(), this->numColorSamples(),
98 numStencilBits, fbi);
Greg Danielfaa095e2017-12-19 13:15:02 -050099}
100
Greg Daniel4065d452018-11-16 15:43:41 -0500101GrBackendFormat GrGLRenderTarget::backendFormat() const {
102 // We should never have a GrGLRenderTarget (even a textureable one with a target that is not
103 // texture 2D.
104 return GrBackendFormat::MakeGL(fRTFormat, GR_GL_TEXTURE_2D);
105}
106
senorblancod2981212015-04-30 12:06:10 -0700107size_t GrGLRenderTarget::onGpuMemorySize() const {
Brian Salomonbb5711a2017-05-17 13:49:59 -0400108 return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
Greg Daniele252f082017-10-23 16:05:23 -0400109 fNumSamplesOwnedPerPixel, GrMipMapped::kNo);
bsalomon@google.com5bfc2172011-07-29 20:29:05 +0000110}
111
egdanielec00d942015-09-14 12:56:10 -0700112bool GrGLRenderTarget::completeStencilAttachment() {
113 GrGLGpu* gpu = this->getGLGpu();
114 const GrGLInterface* interface = gpu->glInterface();
115 GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
116 if (nullptr == stencil) {
egdaniel79bd2ae2015-09-15 08:46:13 -0700117 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
118 GR_GL_STENCIL_ATTACHMENT,
119 GR_GL_RENDERBUFFER, 0));
120 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
121 GR_GL_DEPTH_ATTACHMENT,
122 GR_GL_RENDERBUFFER, 0));
egdanielec00d942015-09-14 12:56:10 -0700123#ifdef SK_DEBUG
robertphillipsfa7ff472016-04-21 11:27:43 -0700124 if (kChromium_GrGLDriver != gpu->glContext().driver()) {
125 // This check can cause problems in Chromium if the context has been asynchronously
126 // abandoned (see skbug.com/5200)
127 GrGLenum status;
128 GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
129 SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
130 }
egdanielec00d942015-09-14 12:56:10 -0700131#endif
egdanielec00d942015-09-14 12:56:10 -0700132 return true;
133 } else {
134 const GrGLStencilAttachment* glStencil = static_cast<const GrGLStencilAttachment*>(stencil);
135 GrGLuint rb = glStencil->renderbufferID();
136
137 gpu->invalidateBoundRenderTarget();
Adrienne Walker4ee88512018-05-17 11:37:14 -0700138 gpu->bindFramebuffer(GR_GL_FRAMEBUFFER, this->renderFBOID());
egdanielec00d942015-09-14 12:56:10 -0700139 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
140 GR_GL_STENCIL_ATTACHMENT,
141 GR_GL_RENDERBUFFER, rb));
142 if (glStencil->format().fPacked) {
143 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
144 GR_GL_DEPTH_ATTACHMENT,
145 GR_GL_RENDERBUFFER, rb));
146 } else {
147 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
148 GR_GL_DEPTH_ATTACHMENT,
149 GR_GL_RENDERBUFFER, 0));
150 }
151
Adrienne Walker3ed33992018-05-15 11:44:34 -0700152
egdanielec00d942015-09-14 12:56:10 -0700153#ifdef SK_DEBUG
robertphillipsfa7ff472016-04-21 11:27:43 -0700154 if (kChromium_GrGLDriver != gpu->glContext().driver()) {
155 // This check can cause problems in Chromium if the context has been asynchronously
156 // abandoned (see skbug.com/5200)
157 GrGLenum status;
158 GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
159 SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
160 }
egdanielec00d942015-09-14 12:56:10 -0700161#endif
162 return true;
163 }
164}
165
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000166void GrGLRenderTarget::onRelease() {
kkinnunen2e6055b2016-04-22 01:48:29 -0700167 if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) {
Adrienne Walker4ee88512018-05-17 11:37:14 -0700168 GrGLGpu* gpu = this->getGLGpu();
egdanield803f272015-03-18 13:01:52 -0700169 if (fTexFBOID) {
Adrienne Walker4ee88512018-05-17 11:37:14 -0700170 gpu->deleteFramebuffer(fTexFBOID);
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000171 }
egdanield803f272015-03-18 13:01:52 -0700172 if (fRTFBOID && fRTFBOID != fTexFBOID) {
Adrienne Walker4ee88512018-05-17 11:37:14 -0700173 gpu->deleteFramebuffer(fRTFBOID);
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000174 }
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000175 if (fMSColorRenderbufferID) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000176 GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000177 }
178 }
egdanield803f272015-03-18 13:01:52 -0700179 fRTFBOID = 0;
180 fTexFBOID = 0;
181 fMSColorRenderbufferID = 0;
robertphillips@google.comd6bbbf82012-09-05 15:46:34 +0000182 INHERITED::onRelease();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000183}
184
185void GrGLRenderTarget::onAbandon() {
egdanield803f272015-03-18 13:01:52 -0700186 fRTFBOID = 0;
187 fTexFBOID = 0;
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000188 fMSColorRenderbufferID = 0;
robertphillips@google.comd6bbbf82012-09-05 15:46:34 +0000189 INHERITED::onAbandon();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000190}
egdanielec00d942015-09-14 12:56:10 -0700191
192GrGLGpu* GrGLRenderTarget::getGLGpu() const {
193 SkASSERT(!this->wasDestroyed());
194 return static_cast<GrGLGpu*>(this->getGpu());
195}
196
kkinnunen2e6055b2016-04-22 01:48:29 -0700197bool GrGLRenderTarget::canAttemptStencilAttachment() const {
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400198 if (this->getGpu()->getContext()->contextPriv().caps()->avoidStencilBuffers()) {
Eric Karl5c779752017-05-08 12:02:07 -0700199 return false;
200 }
201
ericrkc4025182016-05-04 12:01:58 -0700202 // Only modify the FBO's attachments if we have created the FBO. Public APIs do not currently
203 // allow for borrowed FBO ownership, so we can safely assume that if an object is owned,
204 // Skia created it.
205 return this->fRTFBOOwnership == GrBackendObjectOwnership::kOwned;
kkinnunen2e6055b2016-04-22 01:48:29 -0700206}
207
ericrk0a5fa482015-09-15 14:16:10 -0700208void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
Eric Karlaf770022018-03-19 13:04:03 -0700209 // Don't check this->fRefsWrappedObjects, as we might be the base of a GrGLTextureRenderTarget
210 // which is multiply inherited from both ourselves and a texture. In these cases, one part
211 // (texture, rt) may be wrapped, while the other is owned by Skia.
212 bool refsWrappedRenderTargetObjects =
213 this->fRTFBOOwnership == GrBackendObjectOwnership::kBorrowed;
214 if (refsWrappedRenderTargetObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
215 return;
216 }
ericrk0a5fa482015-09-15 14:16:10 -0700217
Eric Karlaf770022018-03-19 13:04:03 -0700218 // Don't log the framebuffer, as the framebuffer itself doesn't contribute to meaningful
219 // memory usage. It is always a wrapper around either:
220 // - a texture, which is owned elsewhere, and will be dumped there
221 // - a renderbuffer, which will be dumped below.
222
223 // Log any renderbuffer's contribution to memory.
ericrk0a5fa482015-09-15 14:16:10 -0700224 if (fMSColorRenderbufferID) {
Brian Salomonbb5711a2017-05-17 13:49:59 -0400225 size_t size = GrSurface::ComputeSize(this->config(), this->width(), this->height(),
Greg Daniele252f082017-10-23 16:05:23 -0400226 this->msaaSamples(), GrMipMapped::kNo);
ericrk0a5fa482015-09-15 14:16:10 -0700227
228 // Due to this resource having both a texture and a renderbuffer component, dump as
229 // skia/gpu_resources/resource_#/renderbuffer
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400230 SkString resourceName = this->getResourceName();
231 resourceName.append("/renderbuffer");
ericrk0a5fa482015-09-15 14:16:10 -0700232
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400233 this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget", size);
ericrk0a5fa482015-09-15 14:16:10 -0700234
235 SkString renderbuffer_id;
236 renderbuffer_id.appendU32(fMSColorRenderbufferID);
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400237 traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_renderbuffer",
ericrk0a5fa482015-09-15 14:16:10 -0700238 renderbuffer_id.c_str());
239 }
240}
241
ericrk0a5fa482015-09-15 14:16:10 -0700242int GrGLRenderTarget::msaaSamples() const {
243 if (fTexFBOID == kUnresolvableFBOID || fTexFBOID != fRTFBOID) {
244 // If the render target's FBO is external (fTexFBOID == kUnresolvableFBOID), or if we own
245 // the render target's FBO (fTexFBOID == fRTFBOID) then we use the provided sample count.
Brian Salomonbdecacf2018-02-02 20:32:49 -0500246 return this->numStencilSamples();
ericrk0a5fa482015-09-15 14:16:10 -0700247 }
248
249 // When fTexFBOID == fRTFBOID, we either are not using MSAA, or MSAA is auto resolving, so use
250 // 0 for the sample count.
251 return 0;
252}
253
254int GrGLRenderTarget::totalSamples() const {
255 int total_samples = this->msaaSamples();
256
257 if (fTexFBOID != kUnresolvableFBOID) {
258 // If we own the resolve buffer then that is one more sample per pixel.
259 total_samples += 1;
260 }
261
262 return total_samples;
263}