blob: bda8529b8714ab2456fe0af18c8ce43b79036e54 [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
Brian Salomonf7f54332020-07-28 09:23:35 -04008#include "src/gpu/gl/GrGLRenderTarget.h"
9
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkTraceMemoryDump.h"
Adlai Holler3d0359a2020-07-09 15:35:55 -040011#include "include/gpu/GrDirectContext.h"
Greg Daniel8ade5e82020-10-07 13:09:48 -040012#include "src/gpu/GrBackendUtils.h"
Adlai Hollera0693042020-10-14 11:23:11 -040013#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/GrGpuResourcePriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/gl/GrGLGpu.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/gl/GrGLUtil.h"
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000017
egdanield803f272015-03-18 13:01:52 -070018#define GPUGL static_cast<GrGLGpu*>(this->getGpu())
19#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
bsalomon@google.com0b77d682011-08-19 13:28:54 +000020
bsalomon37dd3312014-11-03 08:47:23 -080021// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
kkinnunen2e6055b2016-04-22 01:48:29 -070022// Constructor for wrapped render targets.
egdanielec00d942015-09-14 12:56:10 -070023GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
Brian Salomon9f2b86c2019-10-22 10:37:46 -040024 const SkISize& dimensions,
Brian Salomonea4ad302019-08-07 13:04:55 -040025 GrGLFormat format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040026 int sampleCount,
Brian Salomonea4ad302019-08-07 13:04:55 -040027 const IDs& ids,
Greg Danielc0d69152020-10-08 14:59:00 -040028 GrGLAttachment* stencil)
Greg Danield51fa2f2020-01-22 16:53:38 -050029 : GrSurface(gpu, dimensions, GrProtected::kNo)
30 , INHERITED(gpu, dimensions, sampleCount, GrProtected::kNo, stencil) {
Brian Salomonea4ad302019-08-07 13:04:55 -040031 this->setFlags(gpu->glCaps(), ids);
32 this->init(format, ids);
Brian Salomonaa6ca0a2019-01-24 16:03:07 -050033 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000034}
35
Brian Salomonea4ad302019-08-07 13:04:55 -040036GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
Brian Salomon9f2b86c2019-10-22 10:37:46 -040037 const SkISize& dimensions,
Brian Salomonea4ad302019-08-07 13:04:55 -040038 GrGLFormat format,
Brian Salomonea4ad302019-08-07 13:04:55 -040039 int sampleCount,
40 const IDs& ids)
Greg Danield51fa2f2020-01-22 16:53:38 -050041 : GrSurface(gpu, dimensions, GrProtected::kNo)
42 , INHERITED(gpu, dimensions, sampleCount, GrProtected::kNo) {
Brian Salomonea4ad302019-08-07 13:04:55 -040043 this->setFlags(gpu->glCaps(), ids);
44 this->init(format, ids);
bsalomon@google.com5bfc2172011-07-29 20:29:05 +000045}
46
Brian Salomonea4ad302019-08-07 13:04:55 -040047inline void GrGLRenderTarget::setFlags(const GrGLCaps& glCaps, const IDs& idDesc) {
Greg Daniela070ed72018-04-26 16:31:38 -040048 if (!idDesc.fRTFBOID) {
Jim Van Verth5fab9092019-11-25 21:23:53 +000049 this->setGLRTFBOIDIs0();
Greg Daniela070ed72018-04-26 16:31:38 -040050 }
csmartdaltonf9635992016-08-10 11:09:07 -070051}
52
Brian Salomonea4ad302019-08-07 13:04:55 -040053void GrGLRenderTarget::init(GrGLFormat format, const IDs& idDesc) {
54 fRTFBOID = idDesc.fRTFBOID;
55 fTexFBOID = idDesc.fTexFBOID;
56 fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID;
57 fRTFBOOwnership = idDesc.fRTFBOOwnership;
58 fRTFormat = format;
Robert Phillips29e52f12016-11-03 10:19:14 -040059 fNumSamplesOwnedPerPixel = this->totalSamples();
senorblancod2981212015-04-30 12:06:10 -070060}
61
Greg Daniel8ade5e82020-10-07 13:09:48 -040062GrGLFormat stencil_bits_to_format(int stencilBits) {
63 SkASSERT(stencilBits);
64 switch (stencilBits) {
65 case 8:
66 // We pick the packed format here so when we query total size we are at least not
67 // underestimating the total size of the stencil buffer. However, in reality this
68 // rarely matters since we usually don't care about the size of wrapped objects.
69 return GrGLFormat::kDEPTH24_STENCIL8;
70 case 16:
71 return GrGLFormat::kSTENCIL_INDEX16;
72 default:
73 SkASSERT(false);
74 return GrGLFormat::kUnknown;
75 }
76}
77
bungeman6bd52842016-10-27 09:30:08 -070078sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu,
Brian Salomon9f2b86c2019-10-22 10:37:46 -040079 const SkISize& dimensions,
Brian Salomonea4ad302019-08-07 13:04:55 -040080 GrGLFormat format,
Brian Salomon27b4d8d2019-07-22 14:23:45 -040081 int sampleCount,
Brian Salomonea4ad302019-08-07 13:04:55 -040082 const IDs& idDesc,
bungeman6bd52842016-10-27 09:30:08 -070083 int stencilBits) {
Greg Danielc0d69152020-10-08 14:59:00 -040084 GrGLAttachment* sb = nullptr;
egdanielec00d942015-09-14 12:56:10 -070085 if (stencilBits) {
Greg Danielc0d69152020-10-08 14:59:00 -040086 GrGLAttachment::IDDesc sbDesc;
Greg Daniel8ade5e82020-10-07 13:09:48 -040087 // We pick a "fake" actual format that matches the number of stencil bits. When wrapping
88 // an FBO with some number of stencil bits all we care about in the future is that we have
89 // a format with the same number of stencil bits. We don't even directly use the format or
90 // any other properties. Thus it is fine for us to just assign an arbitrary format that
91 // matches the stencil bit count.
92 GrGLFormat sFmt = stencil_bits_to_format(stencilBits);
93
Robert Phillipscb2e2352017-08-30 16:44:40 -040094 // Ownership of sb is passed to the GrRenderTarget so doesn't need to be deleted
Greg Daniel25ebd952020-11-03 11:17:05 -050095 sb = new GrGLAttachment(gpu, sbDesc, dimensions,
96 GrAttachment::UsageFlags::kStencilAttachment, sampleCount, sFmt);
egdanielec00d942015-09-14 12:56:10 -070097 }
Brian Salomon27b4d8d2019-07-22 14:23:45 -040098 return sk_sp<GrGLRenderTarget>(
Greg Danield51fa2f2020-01-22 16:53:38 -050099 new GrGLRenderTarget(gpu, dimensions, format, sampleCount, idDesc, sb));
egdanielec00d942015-09-14 12:56:10 -0700100}
101
Greg Danielfaa095e2017-12-19 13:15:02 -0500102GrBackendRenderTarget GrGLRenderTarget::getBackendRenderTarget() const {
103 GrGLFramebufferInfo fbi;
104 fbi.fFBOID = fRTFBOID;
Brian Salomon1c53a9f2019-08-12 14:10:12 -0400105 fbi.fFormat = GrGLFormatToEnum(this->format());
Brian Salomon0c51eea2018-03-09 17:02:09 -0500106 int numStencilBits = 0;
Greg Danielc0d69152020-10-08 14:59:00 -0400107 if (GrAttachment* stencil = this->getStencilAttachment()) {
Greg Daniel8ade5e82020-10-07 13:09:48 -0400108 numStencilBits = GrBackendFormatStencilBits(stencil->backendFormat());
Brian Salomon0c51eea2018-03-09 17:02:09 -0500109 }
Greg Danielfaa095e2017-12-19 13:15:02 -0500110
Chris Dalton6ce447a2019-06-23 18:07:38 -0600111 return GrBackendRenderTarget(
112 this->width(), this->height(), this->numSamples(), numStencilBits, fbi);
Greg Danielfaa095e2017-12-19 13:15:02 -0500113}
114
Greg Daniel4065d452018-11-16 15:43:41 -0500115GrBackendFormat GrGLRenderTarget::backendFormat() const {
116 // We should never have a GrGLRenderTarget (even a textureable one with a target that is not
117 // texture 2D.
Brian Salomonea4ad302019-08-07 13:04:55 -0400118 return GrBackendFormat::MakeGL(GrGLFormatToEnum(fRTFormat), GR_GL_TEXTURE_2D);
Greg Daniel4065d452018-11-16 15:43:41 -0500119}
120
senorblancod2981212015-04-30 12:06:10 -0700121size_t GrGLRenderTarget::onGpuMemorySize() const {
Greg Daniel0eca74c2020-10-01 13:46:00 -0400122 return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
Brian Salomon7e67dca2020-07-21 09:27:25 -0400123 fNumSamplesOwnedPerPixel, GrMipmapped::kNo);
bsalomon@google.com5bfc2172011-07-29 20:29:05 +0000124}
125
egdanielec00d942015-09-14 12:56:10 -0700126bool GrGLRenderTarget::completeStencilAttachment() {
127 GrGLGpu* gpu = this->getGLGpu();
128 const GrGLInterface* interface = gpu->glInterface();
Greg Danielc0d69152020-10-08 14:59:00 -0400129 GrAttachment* stencil = this->getStencilAttachment();
egdanielec00d942015-09-14 12:56:10 -0700130 if (nullptr == stencil) {
egdaniel79bd2ae2015-09-15 08:46:13 -0700131 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
132 GR_GL_STENCIL_ATTACHMENT,
133 GR_GL_RENDERBUFFER, 0));
134 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
135 GR_GL_DEPTH_ATTACHMENT,
136 GR_GL_RENDERBUFFER, 0));
egdanielec00d942015-09-14 12:56:10 -0700137#ifdef SK_DEBUG
Brian Salomond8575452020-02-25 12:13:29 -0500138 if (!gpu->glCaps().skipErrorChecks()) {
robertphillipsfa7ff472016-04-21 11:27:43 -0700139 // This check can cause problems in Chromium if the context has been asynchronously
140 // abandoned (see skbug.com/5200)
141 GrGLenum status;
142 GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
143 SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
144 }
egdanielec00d942015-09-14 12:56:10 -0700145#endif
egdanielec00d942015-09-14 12:56:10 -0700146 return true;
147 } else {
Greg Danielc0d69152020-10-08 14:59:00 -0400148 const GrGLAttachment* glStencil = static_cast<const GrGLAttachment*>(stencil);
egdanielec00d942015-09-14 12:56:10 -0700149 GrGLuint rb = glStencil->renderbufferID();
150
151 gpu->invalidateBoundRenderTarget();
Adrienne Walker4ee88512018-05-17 11:37:14 -0700152 gpu->bindFramebuffer(GR_GL_FRAMEBUFFER, this->renderFBOID());
egdanielec00d942015-09-14 12:56:10 -0700153 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
154 GR_GL_STENCIL_ATTACHMENT,
155 GR_GL_RENDERBUFFER, rb));
Greg Daniel8ade5e82020-10-07 13:09:48 -0400156 if (GrGLFormatIsPackedDepthStencil(glStencil->format())) {
egdanielec00d942015-09-14 12:56:10 -0700157 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
158 GR_GL_DEPTH_ATTACHMENT,
159 GR_GL_RENDERBUFFER, rb));
160 } else {
161 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
162 GR_GL_DEPTH_ATTACHMENT,
163 GR_GL_RENDERBUFFER, 0));
164 }
165
Adrienne Walker3ed33992018-05-15 11:44:34 -0700166
egdanielec00d942015-09-14 12:56:10 -0700167#ifdef SK_DEBUG
Brian Salomond8575452020-02-25 12:13:29 -0500168 if (!gpu->glCaps().skipErrorChecks()) {
robertphillipsfa7ff472016-04-21 11:27:43 -0700169 // This check can cause problems in Chromium if the context has been asynchronously
170 // abandoned (see skbug.com/5200)
171 GrGLenum status;
172 GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
173 SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
174 }
egdanielec00d942015-09-14 12:56:10 -0700175#endif
176 return true;
177 }
178}
179
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000180void GrGLRenderTarget::onRelease() {
kkinnunen2e6055b2016-04-22 01:48:29 -0700181 if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) {
Adrienne Walker4ee88512018-05-17 11:37:14 -0700182 GrGLGpu* gpu = this->getGLGpu();
egdanield803f272015-03-18 13:01:52 -0700183 if (fTexFBOID) {
Adrienne Walker4ee88512018-05-17 11:37:14 -0700184 gpu->deleteFramebuffer(fTexFBOID);
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000185 }
egdanield803f272015-03-18 13:01:52 -0700186 if (fRTFBOID && fRTFBOID != fTexFBOID) {
Adrienne Walker4ee88512018-05-17 11:37:14 -0700187 gpu->deleteFramebuffer(fRTFBOID);
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000188 }
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000189 if (fMSColorRenderbufferID) {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000190 GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000191 }
192 }
egdanield803f272015-03-18 13:01:52 -0700193 fRTFBOID = 0;
194 fTexFBOID = 0;
195 fMSColorRenderbufferID = 0;
robertphillips@google.comd6bbbf82012-09-05 15:46:34 +0000196 INHERITED::onRelease();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000197}
198
199void GrGLRenderTarget::onAbandon() {
egdanield803f272015-03-18 13:01:52 -0700200 fRTFBOID = 0;
201 fTexFBOID = 0;
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000202 fMSColorRenderbufferID = 0;
robertphillips@google.comd6bbbf82012-09-05 15:46:34 +0000203 INHERITED::onAbandon();
bsalomon@google.comaa5b6732011-07-29 15:13:20 +0000204}
egdanielec00d942015-09-14 12:56:10 -0700205
206GrGLGpu* GrGLRenderTarget::getGLGpu() const {
207 SkASSERT(!this->wasDestroyed());
208 return static_cast<GrGLGpu*>(this->getGpu());
209}
210
kkinnunen2e6055b2016-04-22 01:48:29 -0700211bool GrGLRenderTarget::canAttemptStencilAttachment() const {
Robert Phillips9da87e02019-02-04 13:26:26 -0500212 if (this->getGpu()->getContext()->priv().caps()->avoidStencilBuffers()) {
Eric Karl5c779752017-05-08 12:02:07 -0700213 return false;
214 }
215
ericrkc4025182016-05-04 12:01:58 -0700216 // Only modify the FBO's attachments if we have created the FBO. Public APIs do not currently
217 // allow for borrowed FBO ownership, so we can safely assume that if an object is owned,
218 // Skia created it.
219 return this->fRTFBOOwnership == GrBackendObjectOwnership::kOwned;
kkinnunen2e6055b2016-04-22 01:48:29 -0700220}
221
ericrk0a5fa482015-09-15 14:16:10 -0700222void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
Eric Karlaf770022018-03-19 13:04:03 -0700223 // Don't check this->fRefsWrappedObjects, as we might be the base of a GrGLTextureRenderTarget
224 // which is multiply inherited from both ourselves and a texture. In these cases, one part
225 // (texture, rt) may be wrapped, while the other is owned by Skia.
226 bool refsWrappedRenderTargetObjects =
227 this->fRTFBOOwnership == GrBackendObjectOwnership::kBorrowed;
228 if (refsWrappedRenderTargetObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
229 return;
230 }
ericrk0a5fa482015-09-15 14:16:10 -0700231
Eric Karlaf770022018-03-19 13:04:03 -0700232 // Don't log the framebuffer, as the framebuffer itself doesn't contribute to meaningful
233 // memory usage. It is always a wrapper around either:
234 // - a texture, which is owned elsewhere, and will be dumped there
235 // - a renderbuffer, which will be dumped below.
236
237 // Log any renderbuffer's contribution to memory.
ericrk0a5fa482015-09-15 14:16:10 -0700238 if (fMSColorRenderbufferID) {
Greg Daniel0eca74c2020-10-01 13:46:00 -0400239 size_t size = GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
Brian Salomon7e67dca2020-07-21 09:27:25 -0400240 this->msaaSamples(), GrMipmapped::kNo);
ericrk0a5fa482015-09-15 14:16:10 -0700241
242 // Due to this resource having both a texture and a renderbuffer component, dump as
243 // skia/gpu_resources/resource_#/renderbuffer
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400244 SkString resourceName = this->getResourceName();
245 resourceName.append("/renderbuffer");
ericrk0a5fa482015-09-15 14:16:10 -0700246
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400247 this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget", size);
ericrk0a5fa482015-09-15 14:16:10 -0700248
249 SkString renderbuffer_id;
250 renderbuffer_id.appendU32(fMSColorRenderbufferID);
Derek Sollenbergercf6da8c2018-03-29 13:40:02 -0400251 traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_renderbuffer",
ericrk0a5fa482015-09-15 14:16:10 -0700252 renderbuffer_id.c_str());
253 }
254}
255
ericrk0a5fa482015-09-15 14:16:10 -0700256int GrGLRenderTarget::msaaSamples() const {
257 if (fTexFBOID == kUnresolvableFBOID || fTexFBOID != fRTFBOID) {
258 // If the render target's FBO is external (fTexFBOID == kUnresolvableFBOID), or if we own
259 // the render target's FBO (fTexFBOID == fRTFBOID) then we use the provided sample count.
Chris Dalton6ce447a2019-06-23 18:07:38 -0600260 return this->numSamples();
ericrk0a5fa482015-09-15 14:16:10 -0700261 }
262
263 // When fTexFBOID == fRTFBOID, we either are not using MSAA, or MSAA is auto resolving, so use
264 // 0 for the sample count.
265 return 0;
266}
267
268int GrGLRenderTarget::totalSamples() const {
269 int total_samples = this->msaaSamples();
270
271 if (fTexFBOID != kUnresolvableFBOID) {
272 // If we own the resolve buffer then that is one more sample per pixel.
273 total_samples += 1;
274 }
275
276 return total_samples;
277}