GrGLRenderTarget.cpp revision 94c0468b2b4255e3beed81efdcfbf6d9d39e11e4
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 "GrGLRenderTarget.h" 9 10#include "GrContext.h" 11#include "GrGLGpu.h" 12#include "GrGLUtil.h" 13#include "GrGpuResourcePriv.h" 14#include "GrRenderTargetPriv.h" 15#include "SkTraceMemoryDump.h" 16 17#define GPUGL static_cast<GrGLGpu*>(this->getGpu()) 18#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X) 19 20// Because this class is virtually derived from GrSurface we must explicitly call its constructor. 21// Constructor for wrapped render targets. 22GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, 23 const GrSurfaceDesc& desc, 24 const IDDesc& idDesc, 25 GrGLStencilAttachment* stencil) 26 : GrSurface(gpu, desc) 27 , INHERITED(gpu, desc, ComputeFlags(gpu->glCaps(), idDesc), stencil) { 28 this->init(desc, idDesc); 29 this->registerWithCacheWrapped(); 30} 31 32GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, 33 const IDDesc& idDesc) 34 : GrSurface(gpu, desc) 35 , INHERITED(gpu, desc, ComputeFlags(gpu->glCaps(), idDesc)) { 36 this->init(desc, idDesc); 37} 38 39inline GrRenderTargetFlags GrGLRenderTarget::ComputeFlags(const GrGLCaps& glCaps, 40 const IDDesc& idDesc) { 41 GrRenderTargetFlags flags = GrRenderTargetFlags::kNone; 42 if (idDesc.fIsMixedSampled) { 43 SkASSERT(glCaps.usesMixedSamples() && idDesc.fRTFBOID); // FBO 0 can't be mixed sampled. 44 flags |= GrRenderTargetFlags::kMixedSampled; 45 } 46 if (GrCaps::WindowRectsSupport::kNone != glCaps.windowRectsSupport() && idDesc.fRTFBOID) { 47 flags |= GrRenderTargetFlags::kWindowRectsSupport; 48 } 49 return flags; 50} 51 52void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) { 53 fRTFBOID = idDesc.fRTFBOID; 54 fTexFBOID = idDesc.fTexFBOID; 55 fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID; 56 fRTFBOOwnership = idDesc.fRTFBOOwnership; 57 58 fViewport.fLeft = 0; 59 fViewport.fBottom = 0; 60 fViewport.fWidth = desc.fWidth; 61 fViewport.fHeight = desc.fHeight; 62 63 fNumSamplesOwnedPerPixel = this->totalSamples(); 64} 65 66sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu, 67 const GrSurfaceDesc& desc, 68 const IDDesc& idDesc, 69 int stencilBits) { 70 GrGLStencilAttachment* sb = nullptr; 71 if (stencilBits) { 72 GrGLStencilAttachment::IDDesc sbDesc; 73 GrGLStencilAttachment::Format format; 74 format.fInternalFormat = GrGLStencilAttachment::kUnknownInternalFormat; 75 format.fPacked = false; 76 format.fStencilBits = stencilBits; 77 format.fTotalBits = stencilBits; 78 // Ownership of sb is passed to the GrRenderTarget so doesn't need to be deleted 79 sb = new GrGLStencilAttachment(gpu, sbDesc, desc.fWidth, desc.fHeight, 80 desc.fSampleCnt, format); 81 } 82 return sk_sp<GrGLRenderTarget>(new GrGLRenderTarget(gpu, desc, idDesc, sb)); 83} 84 85size_t GrGLRenderTarget::onGpuMemorySize() const { 86 return GrSurface::ComputeSize(this->config(), this->width(), this->height(), 87 fNumSamplesOwnedPerPixel, GrMipMapped::kNo); 88} 89 90bool GrGLRenderTarget::completeStencilAttachment() { 91 GrGLGpu* gpu = this->getGLGpu(); 92 const GrGLInterface* interface = gpu->glInterface(); 93 GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); 94 if (nullptr == stencil) { 95 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 96 GR_GL_STENCIL_ATTACHMENT, 97 GR_GL_RENDERBUFFER, 0)); 98 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 99 GR_GL_DEPTH_ATTACHMENT, 100 GR_GL_RENDERBUFFER, 0)); 101#ifdef SK_DEBUG 102 if (kChromium_GrGLDriver != gpu->glContext().driver()) { 103 // This check can cause problems in Chromium if the context has been asynchronously 104 // abandoned (see skbug.com/5200) 105 GrGLenum status; 106 GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 107 SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status); 108 } 109#endif 110 return true; 111 } else { 112 const GrGLStencilAttachment* glStencil = static_cast<const GrGLStencilAttachment*>(stencil); 113 GrGLuint rb = glStencil->renderbufferID(); 114 115 gpu->invalidateBoundRenderTarget(); 116 gpu->stats()->incRenderTargetBinds(); 117 GR_GL_CALL(interface, BindFramebuffer(GR_GL_FRAMEBUFFER, this->renderFBOID())); 118 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 119 GR_GL_STENCIL_ATTACHMENT, 120 GR_GL_RENDERBUFFER, rb)); 121 if (glStencil->format().fPacked) { 122 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 123 GR_GL_DEPTH_ATTACHMENT, 124 GR_GL_RENDERBUFFER, rb)); 125 } else { 126 GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, 127 GR_GL_DEPTH_ATTACHMENT, 128 GR_GL_RENDERBUFFER, 0)); 129 } 130 131#ifdef SK_DEBUG 132 if (kChromium_GrGLDriver != gpu->glContext().driver()) { 133 // This check can cause problems in Chromium if the context has been asynchronously 134 // abandoned (see skbug.com/5200) 135 GrGLenum status; 136 GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); 137 SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status); 138 } 139#endif 140 return true; 141 } 142} 143 144void GrGLRenderTarget::onRelease() { 145 if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) { 146 if (fTexFBOID) { 147 GL_CALL(DeleteFramebuffers(1, &fTexFBOID)); 148 } 149 if (fRTFBOID && fRTFBOID != fTexFBOID) { 150 GL_CALL(DeleteFramebuffers(1, &fRTFBOID)); 151 } 152 if (fMSColorRenderbufferID) { 153 GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID)); 154 } 155 } 156 fRTFBOID = 0; 157 fTexFBOID = 0; 158 fMSColorRenderbufferID = 0; 159 INHERITED::onRelease(); 160} 161 162void GrGLRenderTarget::onAbandon() { 163 fRTFBOID = 0; 164 fTexFBOID = 0; 165 fMSColorRenderbufferID = 0; 166 INHERITED::onAbandon(); 167} 168 169GrGLGpu* GrGLRenderTarget::getGLGpu() const { 170 SkASSERT(!this->wasDestroyed()); 171 return static_cast<GrGLGpu*>(this->getGpu()); 172} 173 174bool GrGLRenderTarget::canAttemptStencilAttachment() const { 175 if (this->getGpu()->getContext()->caps()->avoidStencilBuffers()) { 176 return false; 177 } 178 179 // Only modify the FBO's attachments if we have created the FBO. Public APIs do not currently 180 // allow for borrowed FBO ownership, so we can safely assume that if an object is owned, 181 // Skia created it. 182 return this->fRTFBOOwnership == GrBackendObjectOwnership::kOwned; 183} 184 185void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { 186 // Don't log the backing texture's contribution to the memory size. This will be handled by the 187 // texture object. 188 189 // Log any renderbuffer's contribution to memory. We only do this if we own the renderbuffer 190 // (have a fMSColorRenderbufferID). 191 if (fMSColorRenderbufferID) { 192 size_t size = GrSurface::ComputeSize(this->config(), this->width(), this->height(), 193 this->msaaSamples(), GrMipMapped::kNo); 194 195 // Due to this resource having both a texture and a renderbuffer component, dump as 196 // skia/gpu_resources/resource_#/renderbuffer 197 SkString dumpName("skia/gpu_resources/resource_"); 198 dumpName.appendU32(this->uniqueID().asUInt()); 199 dumpName.append("/renderbuffer"); 200 201 traceMemoryDump->dumpNumericValue(dumpName.c_str(), "size", "bytes", size); 202 203 if (this->isPurgeable()) { 204 traceMemoryDump->dumpNumericValue(dumpName.c_str(), "purgeable_size", "bytes", size); 205 } 206 207 SkString renderbuffer_id; 208 renderbuffer_id.appendU32(fMSColorRenderbufferID); 209 traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_renderbuffer", 210 renderbuffer_id.c_str()); 211 } 212} 213 214int GrGLRenderTarget::msaaSamples() const { 215 if (fTexFBOID == kUnresolvableFBOID || fTexFBOID != fRTFBOID) { 216 // If the render target's FBO is external (fTexFBOID == kUnresolvableFBOID), or if we own 217 // the render target's FBO (fTexFBOID == fRTFBOID) then we use the provided sample count. 218 return SkTMax(1, this->numStencilSamples()); 219 } 220 221 // When fTexFBOID == fRTFBOID, we either are not using MSAA, or MSAA is auto resolving, so use 222 // 0 for the sample count. 223 return 0; 224} 225 226int GrGLRenderTarget::totalSamples() const { 227 int total_samples = this->msaaSamples(); 228 229 if (fTexFBOID != kUnresolvableFBOID) { 230 // If we own the resolve buffer then that is one more sample per pixel. 231 total_samples += 1; 232 } 233 234 return total_samples; 235} 236