blob: 104b6e9c5d9f3c9fe9d74f85d7accf3479863c56 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkTraceMemoryDump.h"
9#include "include/gpu/GrContext.h"
10#include "src/gpu/GrContextPriv.h"
11#include "src/gpu/GrGpuResourcePriv.h"
12#include "src/gpu/GrRenderTargetPriv.h"
13#include "src/gpu/gl/GrGLGpu.h"
14#include "src/gpu/gl/GrGLRenderTarget.h"
15#include "src/gpu/gl/GrGLUtil.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,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040024 int sampleCount,
Greg Daniel4065d452018-11-16 15:43:41 -050025 GrGLenum format,
egdanielec00d942015-09-14 12:56:10 -070026 const IDDesc& idDesc,
27 GrGLStencilAttachment* stencil)
Brian Salomon27b4d8d2019-07-22 14:23:45 -040028 : GrSurface(gpu, desc, GrProtected::kNo)
29 , INHERITED(gpu, desc, sampleCount, GrProtected::kNo, stencil) {
Robert Phillipsfe0253f2018-03-16 16:47:25 -040030 this->setFlags(gpu->glCaps(), idDesc);
Greg Daniel4065d452018-11-16 15:43:41 -050031 this->init(desc, format, idDesc);
Brian Salomonaa6ca0a2019-01-24 16:03:07 -050032 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000033}
34
Brian Salomon27b4d8d2019-07-22 14:23:45 -040035GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, int sampleCount,
36 GrGLenum format, const IDDesc& idDesc)
37 : GrSurface(gpu, desc, GrProtected::kNo)
38 , INHERITED(gpu, desc, sampleCount, GrProtected::kNo) {
Robert Phillipsfe0253f2018-03-16 16:47:25 -040039 this->setFlags(gpu->glCaps(), idDesc);
Greg Daniel4065d452018-11-16 15:43:41 -050040 this->init(desc, format, idDesc);
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000041}
42
Robert Phillipsfe0253f2018-03-16 16:47:25 -040043inline void GrGLRenderTarget::setFlags(const GrGLCaps& glCaps, const IDDesc& idDesc) {
Greg Daniela070ed72018-04-26 16:31:38 -040044 if (!idDesc.fRTFBOID) {
45 this->setGLRTFBOIDIs0();
46 }
csmartdaltonf9635992016-08-10 11:09:07 -070047}
48
Greg Daniel4065d452018-11-16 15:43:41 -050049void GrGLRenderTarget::init(const GrSurfaceDesc& desc, GrGLenum format, const IDDesc& idDesc) {
cdaltond4727922015-11-10 12:49:06 -080050 fRTFBOID = idDesc.fRTFBOID;
51 fTexFBOID = idDesc.fTexFBOID;
52 fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID;
kkinnunen2e6055b2016-04-22 01:48:29 -070053 fRTFBOOwnership = idDesc.fRTFBOOwnership;
bsalomon37dd3312014-11-03 08:47:23 -080054
Greg Daniel4065d452018-11-16 15:43:41 -050055 fRTFormat = format;
56
Robert Phillips29e52f12016-11-03 10:19:14 -040057 fNumSamplesOwnedPerPixel = this->totalSamples();
senorblancod2981212015-04-30 12:06:10 -070058}
59
bungeman6bd52842016-10-27 09:30:08 -070060sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu,
61 const GrSurfaceDesc& desc,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040062 int sampleCount,
Greg Daniel4065d452018-11-16 15:43:41 -050063 GrGLenum format,
bungeman6bd52842016-10-27 09:30:08 -070064 const IDDesc& idDesc,
65 int stencilBits) {
egdanielec00d942015-09-14 12:56:10 -070066 GrGLStencilAttachment* sb = nullptr;
67 if (stencilBits) {
68 GrGLStencilAttachment::IDDesc sbDesc;
69 GrGLStencilAttachment::Format format;
70 format.fInternalFormat = GrGLStencilAttachment::kUnknownInternalFormat;
71 format.fPacked = false;
72 format.fStencilBits = stencilBits;
73 format.fTotalBits = stencilBits;
Robert Phillipscb2e2352017-08-30 16:44:40 -040074 // Ownership of sb is passed to the GrRenderTarget so doesn't need to be deleted
Brian Salomon27b4d8d2019-07-22 14:23:45 -040075 sb = new GrGLStencilAttachment(gpu, sbDesc, desc.fWidth, desc.fHeight, sampleCount, format);
egdanielec00d942015-09-14 12:56:10 -070076 }
Brian Salomon27b4d8d2019-07-22 14:23:45 -040077 return sk_sp<GrGLRenderTarget>(
78 new GrGLRenderTarget(gpu, desc, sampleCount, format, idDesc, sb));
egdanielec00d942015-09-14 12:56:10 -070079}
80
Greg Danielfaa095e2017-12-19 13:15:02 -050081GrBackendRenderTarget GrGLRenderTarget::getBackendRenderTarget() const {
82 GrGLFramebufferInfo fbi;
83 fbi.fFBOID = fRTFBOID;
84 fbi.fFormat = this->getGLGpu()->glCaps().configSizedInternalFormat(this->config());
Brian Salomon0c51eea2018-03-09 17:02:09 -050085 int numStencilBits = 0;
86 if (GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment()) {
87 numStencilBits = stencil->bits();
88 }
Greg Danielfaa095e2017-12-19 13:15:02 -050089
Chris Dalton6ce447a2019-06-23 18:07:38 -060090 return GrBackendRenderTarget(
91 this->width(), this->height(), this->numSamples(), numStencilBits, fbi);
Greg Danielfaa095e2017-12-19 13:15:02 -050092}
93
Greg Daniel4065d452018-11-16 15:43:41 -050094GrBackendFormat GrGLRenderTarget::backendFormat() const {
95 // We should never have a GrGLRenderTarget (even a textureable one with a target that is not
96 // texture 2D.
97 return GrBackendFormat::MakeGL(fRTFormat, GR_GL_TEXTURE_2D);
98}
99
senorblancod2981212015-04-30 12:06:10 -0700100size_t GrGLRenderTarget::onGpuMemorySize() const {
Brian Salomonbb5711a2017-05-17 13:49:59 -0400101 return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
Greg Daniele252f082017-10-23 16:05:23 -0400102 fNumSamplesOwnedPerPixel, GrMipMapped::kNo);
bsalomon@google.com5bfc2172011-07-29 20:29:05 +0000103}
104
egdanielec00d942015-09-14 12:56:10 -0700105bool GrGLRenderTarget::completeStencilAttachment() {
106 GrGLGpu* gpu = this->getGLGpu();
107 const GrGLInterface* interface = gpu->glInterface();
108 GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
109 if (nullptr == stencil) {
egdaniel79bd2ae2015-09-15 08:46:13 -0700110 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
111 GR_GL_STENCIL_ATTACHMENT,
112 GR_GL_RENDERBUFFER, 0));
113 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
114 GR_GL_DEPTH_ATTACHMENT,
115 GR_GL_RENDERBUFFER, 0));
egdanielec00d942015-09-14 12:56:10 -0700116#ifdef SK_DEBUG
robertphillipsfa7ff472016-04-21 11:27:43 -0700117 if (kChromium_GrGLDriver != gpu->glContext().driver()) {
118 // This check can cause problems in Chromium if the context has been asynchronously
119 // abandoned (see skbug.com/5200)
120 GrGLenum status;
121 GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
122 SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
123 }
egdanielec00d942015-09-14 12:56:10 -0700124#endif
egdanielec00d942015-09-14 12:56:10 -0700125 return true;
126 } else {
127 const GrGLStencilAttachment* glStencil = static_cast<const GrGLStencilAttachment*>(stencil);
128 GrGLuint rb = glStencil->renderbufferID();
129
130 gpu->invalidateBoundRenderTarget();
Adrienne Walker4ee88512018-05-17 11:37:14 -0700131 gpu->bindFramebuffer(GR_GL_FRAMEBUFFER, this->renderFBOID());
egdanielec00d942015-09-14 12:56:10 -0700132 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
133 GR_GL_STENCIL_ATTACHMENT,
134 GR_GL_RENDERBUFFER, rb));
135 if (glStencil->format().fPacked) {
136 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
137 GR_GL_DEPTH_ATTACHMENT,
138 GR_GL_RENDERBUFFER, rb));
139 } else {
140 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
141 GR_GL_DEPTH_ATTACHMENT,
142 GR_GL_RENDERBUFFER, 0));
143 }
144
Adrienne Walker3ed33992018-05-15 11:44:34 -0700145
egdanielec00d942015-09-14 12:56:10 -0700146#ifdef SK_DEBUG
robertphillipsfa7ff472016-04-21 11:27:43 -0700147 if (kChromium_GrGLDriver != gpu->glContext().driver()) {
148 // This check can cause problems in Chromium if the context has been asynchronously
149 // abandoned (see skbug.com/5200)
150 GrGLenum status;
151 GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
152 SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
153 }
egdanielec00d942015-09-14 12:56:10 -0700154#endif
155 return true;
156 }
157}
158
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000159void GrGLRenderTarget::onRelease() {
kkinnunen2e6055b2016-04-22 01:48:29 -0700160 if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) {
Adrienne Walker4ee88512018-05-17 11:37:14 -0700161 GrGLGpu* gpu = this->getGLGpu();
egdanield803f272015-03-18 13:01:52 -0700162 if (fTexFBOID) {
Adrienne Walker4ee88512018-05-17 11:37:14 -0700163 gpu->deleteFramebuffer(fTexFBOID);
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000164 }
egdanield803f272015-03-18 13:01:52 -0700165 if (fRTFBOID && fRTFBOID != fTexFBOID) {
Adrienne Walker4ee88512018-05-17 11:37:14 -0700166 gpu->deleteFramebuffer(fRTFBOID);
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000167 }
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000168 if (fMSColorRenderbufferID) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000169 GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000170 }
171 }
egdanield803f272015-03-18 13:01:52 -0700172 fRTFBOID = 0;
173 fTexFBOID = 0;
174 fMSColorRenderbufferID = 0;
robertphillips@google.comd6bbbf82012-09-05 15:46:34 +0000175 INHERITED::onRelease();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000176}
177
178void GrGLRenderTarget::onAbandon() {
egdanield803f272015-03-18 13:01:52 -0700179 fRTFBOID = 0;
180 fTexFBOID = 0;
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000181 fMSColorRenderbufferID = 0;
robertphillips@google.comd6bbbf82012-09-05 15:46:34 +0000182 INHERITED::onAbandon();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000183}
egdanielec00d942015-09-14 12:56:10 -0700184
185GrGLGpu* GrGLRenderTarget::getGLGpu() const {
186 SkASSERT(!this->wasDestroyed());
187 return static_cast<GrGLGpu*>(this->getGpu());
188}
189
kkinnunen2e6055b2016-04-22 01:48:29 -0700190bool GrGLRenderTarget::canAttemptStencilAttachment() const {
Robert Phillips9da87e02019-02-04 13:26:26 -0500191 if (this->getGpu()->getContext()->priv().caps()->avoidStencilBuffers()) {
Eric Karl5c779752017-05-08 12:02:07 -0700192 return false;
193 }
194
ericrkc4025182016-05-04 12:01:58 -0700195 // Only modify the FBO's attachments if we have created the FBO. Public APIs do not currently
196 // allow for borrowed FBO ownership, so we can safely assume that if an object is owned,
197 // Skia created it.
198 return this->fRTFBOOwnership == GrBackendObjectOwnership::kOwned;
kkinnunen2e6055b2016-04-22 01:48:29 -0700199}
200
ericrk0a5fa482015-09-15 14:16:10 -0700201void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
Eric Karlaf770022018-03-19 13:04:03 -0700202 // Don't check this->fRefsWrappedObjects, as we might be the base of a GrGLTextureRenderTarget
203 // which is multiply inherited from both ourselves and a texture. In these cases, one part
204 // (texture, rt) may be wrapped, while the other is owned by Skia.
205 bool refsWrappedRenderTargetObjects =
206 this->fRTFBOOwnership == GrBackendObjectOwnership::kBorrowed;
207 if (refsWrappedRenderTargetObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
208 return;
209 }
ericrk0a5fa482015-09-15 14:16:10 -0700210
Eric Karlaf770022018-03-19 13:04:03 -0700211 // Don't log the framebuffer, as the framebuffer itself doesn't contribute to meaningful
212 // memory usage. It is always a wrapper around either:
213 // - a texture, which is owned elsewhere, and will be dumped there
214 // - a renderbuffer, which will be dumped below.
215
216 // Log any renderbuffer's contribution to memory.
ericrk0a5fa482015-09-15 14:16:10 -0700217 if (fMSColorRenderbufferID) {
Brian Salomonbb5711a2017-05-17 13:49:59 -0400218 size_t size = GrSurface::ComputeSize(this->config(), this->width(), this->height(),
Greg Daniele252f082017-10-23 16:05:23 -0400219 this->msaaSamples(), GrMipMapped::kNo);
ericrk0a5fa482015-09-15 14:16:10 -0700220
221 // Due to this resource having both a texture and a renderbuffer component, dump as
222 // skia/gpu_resources/resource_#/renderbuffer
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400223 SkString resourceName = this->getResourceName();
224 resourceName.append("/renderbuffer");
ericrk0a5fa482015-09-15 14:16:10 -0700225
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400226 this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget", size);
ericrk0a5fa482015-09-15 14:16:10 -0700227
228 SkString renderbuffer_id;
229 renderbuffer_id.appendU32(fMSColorRenderbufferID);
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400230 traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_renderbuffer",
ericrk0a5fa482015-09-15 14:16:10 -0700231 renderbuffer_id.c_str());
232 }
233}
234
ericrk0a5fa482015-09-15 14:16:10 -0700235int GrGLRenderTarget::msaaSamples() const {
236 if (fTexFBOID == kUnresolvableFBOID || fTexFBOID != fRTFBOID) {
237 // If the render target's FBO is external (fTexFBOID == kUnresolvableFBOID), or if we own
238 // the render target's FBO (fTexFBOID == fRTFBOID) then we use the provided sample count.
Chris Dalton6ce447a2019-06-23 18:07:38 -0600239 return this->numSamples();
ericrk0a5fa482015-09-15 14:16:10 -0700240 }
241
242 // When fTexFBOID == fRTFBOID, we either are not using MSAA, or MSAA is auto resolving, so use
243 // 0 for the sample count.
244 return 0;
245}
246
247int GrGLRenderTarget::totalSamples() const {
248 int total_samples = this->msaaSamples();
249
250 if (fTexFBOID != kUnresolvableFBOID) {
251 // If we own the resolve buffer then that is one more sample per pixel.
252 total_samples += 1;
253 }
254
255 return total_samples;
256}