blob: 693bc12faee0ba3bcf307d26e10ee386524ee271 [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,
24 const IDDesc& idDesc,
25 GrGLStencilAttachment* stencil)
kkinnunen2e6055b2016-04-22 01:48:29 -070026 : GrSurface(gpu, desc)
Robert Phillipsfe0253f2018-03-16 16:47:25 -040027 , INHERITED(gpu, desc, stencil) {
28 this->setFlags(gpu->glCaps(), idDesc);
bsalomon37dd3312014-11-03 08:47:23 -080029 this->init(desc, idDesc);
kkinnunen2e6055b2016-04-22 01:48:29 -070030 this->registerWithCacheWrapped();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000031}
32
kkinnunen2e6055b2016-04-22 01:48:29 -070033GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc,
34 const IDDesc& idDesc)
35 : GrSurface(gpu, desc)
Robert Phillipsfe0253f2018-03-16 16:47:25 -040036 , INHERITED(gpu, desc) {
37 this->setFlags(gpu->glCaps(), idDesc);
bsalomon37dd3312014-11-03 08:47:23 -080038 this->init(desc, idDesc);
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000039}
40
Robert Phillipsfe0253f2018-03-16 16:47:25 -040041inline void GrGLRenderTarget::setFlags(const GrGLCaps& glCaps, const IDDesc& idDesc) {
csmartdaltonf9635992016-08-10 11:09:07 -070042 if (idDesc.fIsMixedSampled) {
43 SkASSERT(glCaps.usesMixedSamples() && idDesc.fRTFBOID); // FBO 0 can't be mixed sampled.
Robert Phillipsfe0253f2018-03-16 16:47:25 -040044 this->setHasMixedSamples();
csmartdaltonf9635992016-08-10 11:09:07 -070045 }
Jim Van Verth6a40abc2017-11-02 16:56:09 +000046 if (glCaps.maxWindowRectangles() > 0 && idDesc.fRTFBOID) {
Robert Phillipsfe0253f2018-03-16 16:47:25 -040047 this->setSupportsWindowRects();
csmartdaltonf9635992016-08-10 11:09:07 -070048 }
Greg Daniela070ed72018-04-26 16:31:38 -040049 if (!idDesc.fRTFBOID) {
50 this->setGLRTFBOIDIs0();
51 }
csmartdaltonf9635992016-08-10 11:09:07 -070052}
53
bsalomon37dd3312014-11-03 08:47:23 -080054void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
cdaltond4727922015-11-10 12:49:06 -080055 fRTFBOID = idDesc.fRTFBOID;
56 fTexFBOID = idDesc.fTexFBOID;
57 fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID;
kkinnunen2e6055b2016-04-22 01:48:29 -070058 fRTFBOOwnership = idDesc.fRTFBOOwnership;
bsalomon37dd3312014-11-03 08:47:23 -080059
60 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,
70 const IDDesc& idDesc,
71 int stencilBits) {
egdanielec00d942015-09-14 12:56:10 -070072 GrGLStencilAttachment* sb = nullptr;
73 if (stencilBits) {
74 GrGLStencilAttachment::IDDesc sbDesc;
75 GrGLStencilAttachment::Format format;
76 format.fInternalFormat = GrGLStencilAttachment::kUnknownInternalFormat;
77 format.fPacked = false;
78 format.fStencilBits = stencilBits;
79 format.fTotalBits = stencilBits;
Robert Phillipscb2e2352017-08-30 16:44:40 -040080 // Ownership of sb is passed to the GrRenderTarget so doesn't need to be deleted
egdanielec00d942015-09-14 12:56:10 -070081 sb = new GrGLStencilAttachment(gpu, sbDesc, desc.fWidth, desc.fHeight,
82 desc.fSampleCnt, format);
83 }
bungeman6bd52842016-10-27 09:30:08 -070084 return sk_sp<GrGLRenderTarget>(new GrGLRenderTarget(gpu, desc, idDesc, sb));
egdanielec00d942015-09-14 12:56:10 -070085}
86
Greg Danielfaa095e2017-12-19 13:15:02 -050087GrBackendRenderTarget GrGLRenderTarget::getBackendRenderTarget() const {
88 GrGLFramebufferInfo fbi;
89 fbi.fFBOID = fRTFBOID;
90 fbi.fFormat = this->getGLGpu()->glCaps().configSizedInternalFormat(this->config());
Brian Salomon0c51eea2018-03-09 17:02:09 -050091 int numStencilBits = 0;
92 if (GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment()) {
93 numStencilBits = stencil->bits();
94 }
Greg Danielfaa095e2017-12-19 13:15:02 -050095
Greg Daniel8a3f55c2018-03-14 17:32:12 +000096 return GrBackendRenderTarget(this->width(), this->height(), this->numColorSamples(),
97 numStencilBits, fbi);
Greg Danielfaa095e2017-12-19 13:15:02 -050098}
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();
131 gpu->stats()->incRenderTargetBinds();
132 GR_GL_CALL(interface, BindFramebuffer(GR_GL_FRAMEBUFFER, this->renderFBOID()));
133 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
134 GR_GL_STENCIL_ATTACHMENT,
135 GR_GL_RENDERBUFFER, rb));
136 if (glStencil->format().fPacked) {
137 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
138 GR_GL_DEPTH_ATTACHMENT,
139 GR_GL_RENDERBUFFER, rb));
140 } else {
141 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
142 GR_GL_DEPTH_ATTACHMENT,
143 GR_GL_RENDERBUFFER, 0));
144 }
145
Adrienne Walker3ed33992018-05-15 11:44:34 -0700146 gpu->didBindFramebuffer();
147
egdanielec00d942015-09-14 12:56:10 -0700148#ifdef SK_DEBUG
robertphillipsfa7ff472016-04-21 11:27:43 -0700149 if (kChromium_GrGLDriver != gpu->glContext().driver()) {
150 // This check can cause problems in Chromium if the context has been asynchronously
151 // abandoned (see skbug.com/5200)
152 GrGLenum status;
153 GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
154 SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
155 }
egdanielec00d942015-09-14 12:56:10 -0700156#endif
157 return true;
158 }
159}
160
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000161void GrGLRenderTarget::onRelease() {
kkinnunen2e6055b2016-04-22 01:48:29 -0700162 if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) {
egdanield803f272015-03-18 13:01:52 -0700163 if (fTexFBOID) {
164 GL_CALL(DeleteFramebuffers(1, &fTexFBOID));
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000165 }
egdanield803f272015-03-18 13:01:52 -0700166 if (fRTFBOID && fRTFBOID != fTexFBOID) {
167 GL_CALL(DeleteFramebuffers(1, &fRTFBOID));
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000168 }
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000169 if (fMSColorRenderbufferID) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000170 GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000171 }
172 }
egdanield803f272015-03-18 13:01:52 -0700173 fRTFBOID = 0;
174 fTexFBOID = 0;
175 fMSColorRenderbufferID = 0;
robertphillips@google.comd6bbbf82012-09-05 15:46:34 +0000176 INHERITED::onRelease();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000177}
178
179void GrGLRenderTarget::onAbandon() {
egdanield803f272015-03-18 13:01:52 -0700180 fRTFBOID = 0;
181 fTexFBOID = 0;
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000182 fMSColorRenderbufferID = 0;
robertphillips@google.comd6bbbf82012-09-05 15:46:34 +0000183 INHERITED::onAbandon();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000184}
egdanielec00d942015-09-14 12:56:10 -0700185
186GrGLGpu* GrGLRenderTarget::getGLGpu() const {
187 SkASSERT(!this->wasDestroyed());
188 return static_cast<GrGLGpu*>(this->getGpu());
189}
190
kkinnunen2e6055b2016-04-22 01:48:29 -0700191bool GrGLRenderTarget::canAttemptStencilAttachment() const {
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400192 if (this->getGpu()->getContext()->contextPriv().caps()->avoidStencilBuffers()) {
Eric Karl5c779752017-05-08 12:02:07 -0700193 return false;
194 }
195
ericrkc4025182016-05-04 12:01:58 -0700196 // Only modify the FBO's attachments if we have created the FBO. Public APIs do not currently
197 // allow for borrowed FBO ownership, so we can safely assume that if an object is owned,
198 // Skia created it.
199 return this->fRTFBOOwnership == GrBackendObjectOwnership::kOwned;
kkinnunen2e6055b2016-04-22 01:48:29 -0700200}
201
ericrk0a5fa482015-09-15 14:16:10 -0700202void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
Eric Karlaf770022018-03-19 13:04:03 -0700203 // Don't check this->fRefsWrappedObjects, as we might be the base of a GrGLTextureRenderTarget
204 // which is multiply inherited from both ourselves and a texture. In these cases, one part
205 // (texture, rt) may be wrapped, while the other is owned by Skia.
206 bool refsWrappedRenderTargetObjects =
207 this->fRTFBOOwnership == GrBackendObjectOwnership::kBorrowed;
208 if (refsWrappedRenderTargetObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
209 return;
210 }
ericrk0a5fa482015-09-15 14:16:10 -0700211
Eric Karlaf770022018-03-19 13:04:03 -0700212 // Don't log the framebuffer, as the framebuffer itself doesn't contribute to meaningful
213 // memory usage. It is always a wrapper around either:
214 // - a texture, which is owned elsewhere, and will be dumped there
215 // - a renderbuffer, which will be dumped below.
216
217 // Log any renderbuffer's contribution to memory.
ericrk0a5fa482015-09-15 14:16:10 -0700218 if (fMSColorRenderbufferID) {
Brian Salomonbb5711a2017-05-17 13:49:59 -0400219 size_t size = GrSurface::ComputeSize(this->config(), this->width(), this->height(),
Greg Daniele252f082017-10-23 16:05:23 -0400220 this->msaaSamples(), GrMipMapped::kNo);
ericrk0a5fa482015-09-15 14:16:10 -0700221
222 // Due to this resource having both a texture and a renderbuffer component, dump as
223 // skia/gpu_resources/resource_#/renderbuffer
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400224 SkString resourceName = this->getResourceName();
225 resourceName.append("/renderbuffer");
ericrk0a5fa482015-09-15 14:16:10 -0700226
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400227 this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget", size);
ericrk0a5fa482015-09-15 14:16:10 -0700228
229 SkString renderbuffer_id;
230 renderbuffer_id.appendU32(fMSColorRenderbufferID);
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400231 traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_renderbuffer",
ericrk0a5fa482015-09-15 14:16:10 -0700232 renderbuffer_id.c_str());
233 }
234}
235
ericrk0a5fa482015-09-15 14:16:10 -0700236int GrGLRenderTarget::msaaSamples() const {
237 if (fTexFBOID == kUnresolvableFBOID || fTexFBOID != fRTFBOID) {
238 // If the render target's FBO is external (fTexFBOID == kUnresolvableFBOID), or if we own
239 // the render target's FBO (fTexFBOID == fRTFBOID) then we use the provided sample count.
Brian Salomonbdecacf2018-02-02 20:32:49 -0500240 return this->numStencilSamples();
ericrk0a5fa482015-09-15 14:16:10 -0700241 }
242
243 // When fTexFBOID == fRTFBOID, we either are not using MSAA, or MSAA is auto resolving, so use
244 // 0 for the sample count.
245 return 0;
246}
247
248int GrGLRenderTarget::totalSamples() const {
249 int total_samples = this->msaaSamples();
250
251 if (fTexFBOID != kUnresolvableFBOID) {
252 // If we own the resolve buffer then that is one more sample per pixel.
253 total_samples += 1;
254 }
255
256 return total_samples;
257}