Home | History | Annotate | Download | only in gl
      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 "GrRenderTargetPriv.h"
     11 #include "GrGLGpu.h"
     12 #include "GrGLUtil.h"
     13 #include "SkTraceMemoryDump.h"
     14 
     15 #define GPUGL static_cast<GrGLGpu*>(this->getGpu())
     16 #define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
     17 
     18 // Because this class is virtually derived from GrSurface we must explicitly call its constructor.
     19 GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
     20                                    const GrSurfaceDesc& desc,
     21                                    const IDDesc& idDesc,
     22                                    GrGLStencilAttachment* stencil)
     23     : GrSurface(gpu, idDesc.fLifeCycle, desc)
     24     , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig, stencil) {
     25     this->init(desc, idDesc);
     26     this->registerWithCache();
     27 }
     28 
     29 GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
     30                                    Derived)
     31     : GrSurface(gpu, idDesc.fLifeCycle, desc)
     32     , INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig) {
     33     this->init(desc, idDesc);
     34 }
     35 
     36 void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
     37     fRTFBOID                = idDesc.fRTFBOID;
     38     fTexFBOID               = idDesc.fTexFBOID;
     39     fMSColorRenderbufferID  = idDesc.fMSColorRenderbufferID;
     40     fRTLifecycle            = idDesc.fLifeCycle;
     41 
     42     fViewport.fLeft   = 0;
     43     fViewport.fBottom = 0;
     44     fViewport.fWidth  = desc.fWidth;
     45     fViewport.fHeight = desc.fHeight;
     46 
     47     fGpuMemorySize = this->totalSamples() * this->totalBytesPerSample();
     48 
     49     SkASSERT(fGpuMemorySize <= WorseCaseSize(desc));
     50 }
     51 
     52 GrGLRenderTarget* GrGLRenderTarget::CreateWrapped(GrGLGpu* gpu,
     53                                                   const GrSurfaceDesc& desc,
     54                                                   const IDDesc& idDesc,
     55                                                   int stencilBits) {
     56     GrGLStencilAttachment* sb = nullptr;
     57     if (stencilBits) {
     58         GrGLStencilAttachment::IDDesc sbDesc;
     59         GrGLStencilAttachment::Format format;
     60         format.fInternalFormat = GrGLStencilAttachment::kUnknownInternalFormat;
     61         format.fPacked = false;
     62         format.fStencilBits = stencilBits;
     63         format.fTotalBits = stencilBits;
     64         // Owndership of sb is passed to the GrRenderTarget so doesn't need to be deleted
     65         sb = new GrGLStencilAttachment(gpu, sbDesc, desc.fWidth, desc.fHeight,
     66                                        desc.fSampleCnt, format);
     67     }
     68     return (new GrGLRenderTarget(gpu, desc, idDesc, sb));
     69 }
     70 
     71 size_t GrGLRenderTarget::onGpuMemorySize() const {
     72     return fGpuMemorySize;
     73 }
     74 
     75 bool GrGLRenderTarget::completeStencilAttachment() {
     76     GrGLGpu* gpu = this->getGLGpu();
     77     const GrGLInterface* interface = gpu->glInterface();
     78     GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
     79     if (nullptr == stencil) {
     80         GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
     81                                                       GR_GL_STENCIL_ATTACHMENT,
     82                                                       GR_GL_RENDERBUFFER, 0));
     83         GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
     84                                                       GR_GL_DEPTH_ATTACHMENT,
     85                                                       GR_GL_RENDERBUFFER, 0));
     86 #ifdef SK_DEBUG
     87         GrGLenum status;
     88         GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
     89         SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
     90 #endif
     91         return true;
     92     } else {
     93         const GrGLStencilAttachment* glStencil = static_cast<const GrGLStencilAttachment*>(stencil);
     94         GrGLuint rb = glStencil->renderbufferID();
     95 
     96         gpu->invalidateBoundRenderTarget();
     97         gpu->stats()->incRenderTargetBinds();
     98         GR_GL_CALL(interface, BindFramebuffer(GR_GL_FRAMEBUFFER, this->renderFBOID()));
     99         GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    100                                                       GR_GL_STENCIL_ATTACHMENT,
    101                                                       GR_GL_RENDERBUFFER, rb));
    102         if (glStencil->format().fPacked) {
    103             GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    104                                                           GR_GL_DEPTH_ATTACHMENT,
    105                                                           GR_GL_RENDERBUFFER, rb));
    106         } else {
    107             GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
    108                                                           GR_GL_DEPTH_ATTACHMENT,
    109                                                           GR_GL_RENDERBUFFER, 0));
    110         }
    111 
    112 #ifdef SK_DEBUG
    113         GrGLenum status;
    114         GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
    115         SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status);
    116 #endif
    117         return true;
    118     }
    119 }
    120 
    121 void GrGLRenderTarget::onRelease() {
    122     if (kBorrowed_LifeCycle != fRTLifecycle) {
    123         if (fTexFBOID) {
    124             GL_CALL(DeleteFramebuffers(1, &fTexFBOID));
    125         }
    126         if (fRTFBOID && fRTFBOID != fTexFBOID) {
    127             GL_CALL(DeleteFramebuffers(1, &fRTFBOID));
    128         }
    129         if (fMSColorRenderbufferID) {
    130             GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
    131         }
    132     }
    133     fRTFBOID                = 0;
    134     fTexFBOID               = 0;
    135     fMSColorRenderbufferID  = 0;
    136     INHERITED::onRelease();
    137 }
    138 
    139 void GrGLRenderTarget::onAbandon() {
    140     fRTFBOID                = 0;
    141     fTexFBOID               = 0;
    142     fMSColorRenderbufferID  = 0;
    143     INHERITED::onAbandon();
    144 }
    145 
    146 GrGLGpu* GrGLRenderTarget::getGLGpu() const {
    147     SkASSERT(!this->wasDestroyed());
    148     return static_cast<GrGLGpu*>(this->getGpu());
    149 }
    150 
    151 void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
    152     // Don't log the backing texture's contribution to the memory size. This will be handled by the
    153     // texture object.
    154 
    155     // Log any renderbuffer's contribution to memory. We only do this if we own the renderbuffer
    156     // (have a fMSColorRenderbufferID).
    157     if (fMSColorRenderbufferID) {
    158         size_t size = this->msaaSamples() * this->totalBytesPerSample();
    159 
    160         // Due to this resource having both a texture and a renderbuffer component, dump as
    161         // skia/gpu_resources/resource_#/renderbuffer
    162         SkString dumpName("skia/gpu_resources/resource_");
    163         dumpName.appendS32(this->getUniqueID());
    164         dumpName.append("/renderbuffer");
    165 
    166         traceMemoryDump->dumpNumericValue(dumpName.c_str(), "size", "bytes", size);
    167 
    168         if (this->isPurgeable()) {
    169             traceMemoryDump->dumpNumericValue(dumpName.c_str(), "purgeable_size", "bytes", size);
    170         }
    171 
    172         SkString renderbuffer_id;
    173         renderbuffer_id.appendU32(fMSColorRenderbufferID);
    174         traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_renderbuffer",
    175                                           renderbuffer_id.c_str());
    176     }
    177 }
    178 
    179 size_t GrGLRenderTarget::totalBytesPerSample() const {
    180     SkASSERT(kUnknown_GrPixelConfig != fDesc.fConfig);
    181     SkASSERT(!GrPixelConfigIsCompressed(fDesc.fConfig));
    182     size_t colorBytes = GrBytesPerPixel(fDesc.fConfig);
    183     SkASSERT(colorBytes > 0);
    184 
    185     return fDesc.fWidth * fDesc.fHeight * colorBytes;
    186 }
    187 
    188 int GrGLRenderTarget::msaaSamples() const {
    189     if (fTexFBOID == kUnresolvableFBOID || fTexFBOID != fRTFBOID) {
    190         // If the render target's FBO is external (fTexFBOID == kUnresolvableFBOID), or if we own
    191         // the render target's FBO (fTexFBOID == fRTFBOID) then we use the provided sample count.
    192         return SkTMax(1, fDesc.fSampleCnt);
    193     }
    194 
    195     // When fTexFBOID == fRTFBOID, we either are not using MSAA, or MSAA is auto resolving, so use
    196     // 0 for the sample count.
    197     return 0;
    198 }
    199 
    200 int GrGLRenderTarget::totalSamples() const {
    201   int total_samples = this->msaaSamples();
    202 
    203   if (fTexFBOID != kUnresolvableFBOID) {
    204       // If we own the resolve buffer then that is one more sample per pixel.
    205       total_samples += 1;
    206   }
    207 
    208   return total_samples;
    209 }
    210