Home | History | Annotate | Download | only in libGLESv2
      1 //
      2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
      8 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
      9 
     10 #include "libGLESv2/Framebuffer.h"
     11 #include "libGLESv2/main.h"
     12 #include "libGLESv2/formatutils.h"
     13 #include "libGLESv2/Texture.h"
     14 #include "libGLESv2/Context.h"
     15 #include "libGLESv2/Renderbuffer.h"
     16 #include "libGLESv2/FramebufferAttachment.h"
     17 #include "libGLESv2/renderer/Renderer.h"
     18 #include "libGLESv2/renderer/RenderTarget.h"
     19 #include "libGLESv2/renderer/d3d/TextureD3D.h"
     20 
     21 #include "common/utilities.h"
     22 
     23 namespace rx
     24 {
     25 RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
     26 {
     27     if (attachment->isTexture())
     28     {
     29         gl::Texture *texture = attachment->getTexture();
     30         ASSERT(texture);
     31         TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
     32         const gl::ImageIndex *index = attachment->getTextureImageIndex();
     33         ASSERT(index);
     34         return textureD3D->getRenderTarget(*index);
     35     }
     36 
     37     gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
     38     ASSERT(renderbuffer);
     39 
     40     // TODO: cast to RenderbufferD3D
     41     return renderbuffer->getStorage()->getRenderTarget();
     42 }
     43 
     44 // Note: RenderTarget serials should ideally be in the RenderTargets themselves.
     45 unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
     46 {
     47     if (attachment->isTexture())
     48     {
     49         gl::Texture *texture = attachment->getTexture();
     50         ASSERT(texture);
     51         TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
     52         const gl::ImageIndex *index = attachment->getTextureImageIndex();
     53         ASSERT(index);
     54         return textureD3D->getRenderTargetSerial(*index);
     55     }
     56 
     57     gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
     58     ASSERT(renderbuffer);
     59 
     60     // TODO: cast to RenderbufferD3D
     61     return renderbuffer->getStorage()->getSerial();
     62 }
     63 
     64 }
     65 
     66 namespace gl
     67 {
     68 
     69 Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
     70     : mRenderer(renderer),
     71       mId(id),
     72       mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
     73       mDepthbuffer(NULL),
     74       mStencilbuffer(NULL)
     75 {
     76     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     77     {
     78         mColorbuffers[colorAttachment] = NULL;
     79         mDrawBufferStates[colorAttachment] = GL_NONE;
     80     }
     81     mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
     82 }
     83 
     84 Framebuffer::~Framebuffer()
     85 {
     86     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     87     {
     88         SafeDelete(mColorbuffers[colorAttachment]);
     89     }
     90     SafeDelete(mDepthbuffer);
     91     SafeDelete(mStencilbuffer);
     92 }
     93 
     94 FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
     95 {
     96     if (handle == 0)
     97     {
     98         return NULL;
     99     }
    100 
    101     gl::Context *context = gl::getContext();
    102 
    103     switch (type)
    104     {
    105       case GL_NONE:
    106         return NULL;
    107 
    108       case GL_RENDERBUFFER:
    109         return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
    110 
    111       case GL_TEXTURE_2D:
    112         {
    113             Texture *texture = context->getTexture(handle);
    114             if (texture && texture->getTarget() == GL_TEXTURE_2D)
    115             {
    116                 return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
    117             }
    118             else
    119             {
    120                 return NULL;
    121             }
    122         }
    123 
    124       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    125       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    126       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    127       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    128       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    129       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
    130         {
    131             Texture *texture = context->getTexture(handle);
    132             if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
    133             {
    134                 return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
    135             }
    136             else
    137             {
    138                 return NULL;
    139             }
    140         }
    141 
    142       case GL_TEXTURE_3D:
    143         {
    144             Texture *texture = context->getTexture(handle);
    145             if (texture && texture->getTarget() == GL_TEXTURE_3D)
    146             {
    147                 return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
    148             }
    149             else
    150             {
    151                 return NULL;
    152             }
    153         }
    154 
    155       case GL_TEXTURE_2D_ARRAY:
    156         {
    157             Texture *texture = context->getTexture(handle);
    158             if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
    159             {
    160                 return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
    161             }
    162             else
    163             {
    164                 return NULL;
    165             }
    166         }
    167 
    168       default:
    169         UNREACHABLE();
    170         return NULL;
    171     }
    172 }
    173 
    174 void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
    175 {
    176     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
    177     SafeDelete(mColorbuffers[colorAttachment]);
    178     GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
    179     mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
    180 }
    181 
    182 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
    183 {
    184     SafeDelete(mDepthbuffer);
    185     mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
    186 }
    187 
    188 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
    189 {
    190     SafeDelete(mStencilbuffer);
    191     mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
    192 }
    193 
    194 void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
    195 {
    196     FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
    197 
    198     SafeDelete(mDepthbuffer);
    199     SafeDelete(mStencilbuffer);
    200 
    201     // ensure this is a legitimate depth+stencil format
    202     if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
    203     {
    204         mDepthbuffer = attachment;
    205 
    206         // Make a new attachment object to ensure we do not double-delete
    207         // See angle issue 686
    208         mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
    209     }
    210 }
    211 
    212 void Framebuffer::detachTexture(GLuint textureId)
    213 {
    214     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    215     {
    216         FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
    217 
    218         if (attachment && attachment->isTextureWithId(textureId))
    219         {
    220             SafeDelete(mColorbuffers[colorAttachment]);
    221         }
    222     }
    223 
    224     if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
    225     {
    226         SafeDelete(mDepthbuffer);
    227     }
    228 
    229     if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
    230     {
    231         SafeDelete(mStencilbuffer);
    232     }
    233 }
    234 
    235 void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
    236 {
    237     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    238     {
    239         FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
    240 
    241         if (attachment && attachment->isRenderbufferWithId(renderbufferId))
    242         {
    243             SafeDelete(mColorbuffers[colorAttachment]);
    244         }
    245     }
    246 
    247     if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
    248     {
    249         SafeDelete(mDepthbuffer);
    250     }
    251 
    252     if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
    253     {
    254         SafeDelete(mStencilbuffer);
    255     }
    256 }
    257 
    258 FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
    259 {
    260     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
    261     return mColorbuffers[colorAttachment];
    262 }
    263 
    264 FramebufferAttachment *Framebuffer::getDepthbuffer() const
    265 {
    266     return mDepthbuffer;
    267 }
    268 
    269 FramebufferAttachment *Framebuffer::getStencilbuffer() const
    270 {
    271     return mStencilbuffer;
    272 }
    273 
    274 FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
    275 {
    276     return (hasValidDepthStencil() ? mDepthbuffer : NULL);
    277 }
    278 
    279 FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
    280 {
    281     FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
    282 
    283     if (!depthstencilbuffer)
    284     {
    285         depthstencilbuffer = mStencilbuffer;
    286     }
    287 
    288     return depthstencilbuffer;
    289 }
    290 
    291 FramebufferAttachment *Framebuffer::getReadColorbuffer() const
    292 {
    293     // Will require more logic if glReadBuffers is supported
    294     return mColorbuffers[0];
    295 }
    296 
    297 GLenum Framebuffer::getReadColorbufferType() const
    298 {
    299     // Will require more logic if glReadBuffers is supported
    300     return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
    301 }
    302 
    303 FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
    304 {
    305     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    306     {
    307         if (mColorbuffers[colorAttachment])
    308         {
    309             return mColorbuffers[colorAttachment];
    310         }
    311     }
    312 
    313     return NULL;
    314 }
    315 
    316 FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
    317 {
    318     if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
    319     {
    320         return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
    321     }
    322     else
    323     {
    324         switch (attachment)
    325         {
    326           case GL_DEPTH_ATTACHMENT:
    327             return getDepthbuffer();
    328           case GL_STENCIL_ATTACHMENT:
    329             return getStencilbuffer();
    330           case GL_DEPTH_STENCIL_ATTACHMENT:
    331             return getDepthStencilBuffer();
    332           default:
    333             UNREACHABLE();
    334             return NULL;
    335         }
    336     }
    337 }
    338 
    339 GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
    340 {
    341     return mDrawBufferStates[colorAttachment];
    342 }
    343 
    344 void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
    345 {
    346     mDrawBufferStates[colorAttachment] = drawBuffer;
    347 }
    348 
    349 bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
    350 {
    351     return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
    352 }
    353 
    354 bool Framebuffer::hasEnabledColorAttachment() const
    355 {
    356     for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    357     {
    358         if (isEnabledColorAttachment(colorAttachment))
    359         {
    360             return true;
    361         }
    362     }
    363 
    364     return false;
    365 }
    366 
    367 bool Framebuffer::hasStencil() const
    368 {
    369     return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
    370 }
    371 
    372 bool Framebuffer::usingExtendedDrawBuffers() const
    373 {
    374     for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    375     {
    376         if (isEnabledColorAttachment(colorAttachment))
    377         {
    378             return true;
    379         }
    380     }
    381 
    382     return false;
    383 }
    384 
    385 GLenum Framebuffer::completeness() const
    386 {
    387     int width = 0;
    388     int height = 0;
    389     unsigned int colorbufferSize = 0;
    390     int samples = -1;
    391     bool missingAttachment = true;
    392     GLuint clientVersion = mRenderer->getCurrentClientVersion();
    393 
    394     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    395     {
    396         const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
    397 
    398         if (colorbuffer)
    399         {
    400             if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
    401             {
    402                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    403             }
    404 
    405             GLenum internalformat = colorbuffer->getInternalFormat();
    406             // TODO(geofflang): use context's texture caps
    407             const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
    408             const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
    409             if (colorbuffer->isTexture())
    410             {
    411                 if (!formatCaps.renderable)
    412                 {
    413                     return GL_FRAMEBUFFER_UNSUPPORTED;
    414                 }
    415 
    416                 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
    417                 {
    418                     return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    419                 }
    420             }
    421             else
    422             {
    423                 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
    424                 {
    425                     return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    426                 }
    427             }
    428 
    429             if (!missingAttachment)
    430             {
    431                 // all color attachments must have the same width and height
    432                 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
    433                 {
    434                     return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
    435                 }
    436 
    437                 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
    438                 // all color attachments have the same number of samples for the FBO to be complete.
    439                 if (colorbuffer->getSamples() != samples)
    440                 {
    441                     return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
    442                 }
    443 
    444                 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
    445                 // in GLES 3.0, there is no such restriction
    446                 if (clientVersion < 3)
    447                 {
    448                     if (formatInfo.pixelBytes != colorbufferSize)
    449                     {
    450                         return GL_FRAMEBUFFER_UNSUPPORTED;
    451                     }
    452                 }
    453 
    454                 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
    455                 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
    456                 {
    457                     const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
    458 
    459                     if (previousAttachment &&
    460                         (colorbuffer->id() == previousAttachment->id() &&
    461                          colorbuffer->type() == previousAttachment->type()))
    462                     {
    463                         return GL_FRAMEBUFFER_UNSUPPORTED;
    464                     }
    465                 }
    466             }
    467             else
    468             {
    469                 width = colorbuffer->getWidth();
    470                 height = colorbuffer->getHeight();
    471                 samples = colorbuffer->getSamples();
    472                 colorbufferSize = formatInfo.pixelBytes;
    473                 missingAttachment = false;
    474             }
    475         }
    476     }
    477 
    478     if (mDepthbuffer)
    479     {
    480         if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
    481         {
    482             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    483         }
    484 
    485         GLenum internalformat = mDepthbuffer->getInternalFormat();
    486         // TODO(geofflang): use context's texture caps
    487         const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
    488         const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
    489         if (mDepthbuffer->isTexture())
    490         {
    491             // depth texture attachments require OES/ANGLE_depth_texture
    492             // TODO(geofflang): use context's extensions
    493             if (!mRenderer->getRendererExtensions().depthTextures)
    494             {
    495                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    496             }
    497 
    498             if (!formatCaps.renderable)
    499             {
    500                 return GL_FRAMEBUFFER_UNSUPPORTED;
    501             }
    502 
    503             if (formatInfo.depthBits == 0)
    504             {
    505                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    506             }
    507         }
    508         else
    509         {
    510             if (!formatCaps.renderable || formatInfo.depthBits == 0)
    511             {
    512                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    513             }
    514         }
    515 
    516         if (missingAttachment)
    517         {
    518             width = mDepthbuffer->getWidth();
    519             height = mDepthbuffer->getHeight();
    520             samples = mDepthbuffer->getSamples();
    521             missingAttachment = false;
    522         }
    523         else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
    524         {
    525             return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
    526         }
    527         else if (samples != mDepthbuffer->getSamples())
    528         {
    529             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
    530         }
    531     }
    532 
    533     if (mStencilbuffer)
    534     {
    535         if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
    536         {
    537             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    538         }
    539 
    540         GLenum internalformat = mStencilbuffer->getInternalFormat();
    541         // TODO(geofflang): use context's texture caps
    542         const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
    543         const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
    544         if (mStencilbuffer->isTexture())
    545         {
    546             // texture stencil attachments come along as part
    547             // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
    548             // TODO(geofflang): use context's extensions
    549             if (!mRenderer->getRendererExtensions().depthTextures)
    550             {
    551                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    552             }
    553 
    554             if (!formatCaps.renderable)
    555             {
    556                 return GL_FRAMEBUFFER_UNSUPPORTED;
    557             }
    558 
    559             if (formatInfo.stencilBits == 0)
    560             {
    561                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    562             }
    563         }
    564         else
    565         {
    566             if (!formatCaps.renderable || formatInfo.stencilBits == 0)
    567             {
    568                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    569             }
    570         }
    571 
    572         if (missingAttachment)
    573         {
    574             width = mStencilbuffer->getWidth();
    575             height = mStencilbuffer->getHeight();
    576             samples = mStencilbuffer->getSamples();
    577             missingAttachment = false;
    578         }
    579         else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
    580         {
    581             return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
    582         }
    583         else if (samples != mStencilbuffer->getSamples())
    584         {
    585             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
    586         }
    587     }
    588 
    589     // if we have both a depth and stencil buffer, they must refer to the same object
    590     // since we only support packed_depth_stencil and not separate depth and stencil
    591     if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
    592     {
    593         return GL_FRAMEBUFFER_UNSUPPORTED;
    594     }
    595 
    596     // we need to have at least one attachment to be complete
    597     if (missingAttachment)
    598     {
    599         return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
    600     }
    601 
    602     return GL_FRAMEBUFFER_COMPLETE;
    603 }
    604 
    605 void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
    606 {
    607     GLuint maxDimension = caps.maxRenderbufferSize;
    608     invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
    609 }
    610 
    611 void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
    612                                 GLint x, GLint y, GLsizei width, GLsizei height)
    613 {
    614     ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
    615     for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
    616     {
    617         GLenum attachmentTarget = attachments[attachIndex];
    618 
    619         gl::FramebufferAttachment *attachment =
    620             (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() :
    621                                                                 getAttachment(attachmentTarget);
    622 
    623         if (attachment)
    624         {
    625             rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
    626             if (renderTarget)
    627             {
    628                 renderTarget->invalidate(x, y, width, height);
    629             }
    630         }
    631     }
    632 }
    633 
    634 DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
    635     : Framebuffer(renderer, 0)
    636 {
    637     Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
    638     mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
    639 
    640     GLenum depthStencilActualFormat = depthStencil->getActualFormat();
    641     const gl::InternalFormat &depthStencilFormatInfo = GetInternalFormatInfo(depthStencilActualFormat);
    642 
    643     if (depthStencilFormatInfo.depthBits != 0 || depthStencilFormatInfo.stencilBits != 0)
    644     {
    645         Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
    646 
    647         // Make a new attachment objects to ensure we do not double-delete
    648         // See angle issue 686
    649         mDepthbuffer = (depthStencilFormatInfo.depthBits != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
    650         mStencilbuffer = (depthStencilFormatInfo.stencilBits != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
    651     }
    652     else
    653     {
    654         // This method transfers ownership, so delete the unused storage if we don't keep it.
    655         SafeDelete(depthStencil);
    656     }
    657 
    658     mDrawBufferStates[0] = GL_BACK;
    659     mReadBufferState = GL_BACK;
    660 }
    661 
    662 int Framebuffer::getSamples() const
    663 {
    664     if (completeness() == GL_FRAMEBUFFER_COMPLETE)
    665     {
    666         // for a complete framebuffer, all attachments must have the same sample count
    667         // in this case return the first nonzero sample size
    668         for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    669         {
    670             if (mColorbuffers[colorAttachment])
    671             {
    672                 return mColorbuffers[colorAttachment]->getSamples();
    673             }
    674         }
    675     }
    676 
    677     return 0;
    678 }
    679 
    680 bool Framebuffer::hasValidDepthStencil() const
    681 {
    682     // A valid depth-stencil attachment has the same resource bound to both the
    683     // depth and stencil attachment points.
    684     return (mDepthbuffer && mStencilbuffer &&
    685             mDepthbuffer->type() == mStencilbuffer->type() &&
    686             mDepthbuffer->id() == mStencilbuffer->id());
    687 }
    688 
    689 ColorbufferInfo Framebuffer::getColorbuffersForRender() const
    690 {
    691     ColorbufferInfo colorbuffersForRender;
    692 
    693     for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
    694     {
    695         GLenum drawBufferState = mDrawBufferStates[colorAttachment];
    696         FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
    697 
    698         if (colorbuffer != NULL && drawBufferState != GL_NONE)
    699         {
    700             ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
    701             colorbuffersForRender.push_back(colorbuffer);
    702         }
    703 #if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED)
    704         else
    705         {
    706             colorbuffersForRender.push_back(NULL);
    707         }
    708 #endif
    709     }
    710 
    711     return colorbuffersForRender;
    712 }
    713 
    714 GLenum DefaultFramebuffer::completeness() const
    715 {
    716     // The default framebuffer *must* always be complete, though it may not be
    717     // subject to the same rules as application FBOs. ie, it could have 0x0 size.
    718     return GL_FRAMEBUFFER_COMPLETE;
    719 }
    720 
    721 FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
    722 {
    723     switch (attachment)
    724     {
    725       case GL_COLOR:
    726       case GL_BACK:
    727         return getColorbuffer(0);
    728       case GL_DEPTH:
    729         return getDepthbuffer();
    730       case GL_STENCIL:
    731         return getStencilbuffer();
    732       case GL_DEPTH_STENCIL:
    733         return getDepthStencilBuffer();
    734       default:
    735         UNREACHABLE();
    736         return NULL;
    737     }
    738 }
    739 
    740 }
    741