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