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 "libGLESv2/utilities.h"
     15 #include "libGLESv2/Texture.h"
     16 #include "libGLESv2/Context.h"
     17 #include "libGLESv2/renderer/Renderer.h"
     18 #include "libGLESv2/Renderbuffer.h"
     19 
     20 namespace gl
     21 {
     22 
     23 Framebuffer::Framebuffer(rx::Renderer *renderer)
     24     : mRenderer(renderer)
     25 {
     26     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     27     {
     28         mColorbufferTypes[colorAttachment] = GL_NONE;
     29         mDrawBufferStates[colorAttachment] = GL_NONE;
     30     }
     31     mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
     32     mReadBufferState = GL_COLOR_ATTACHMENT0_EXT;
     33 
     34     mDepthbufferType = GL_NONE;
     35     mStencilbufferType = GL_NONE;
     36 }
     37 
     38 Framebuffer::~Framebuffer()
     39 {
     40     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     41     {
     42         mColorbufferPointers[colorAttachment].set(NULL);
     43     }
     44     mDepthbufferPointer.set(NULL);
     45     mStencilbufferPointer.set(NULL);
     46 }
     47 
     48 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
     49 {
     50     gl::Context *context = gl::getContext();
     51     Renderbuffer *buffer = NULL;
     52 
     53     if (type == GL_NONE)
     54     {
     55         buffer = NULL;
     56     }
     57     else if (type == GL_RENDERBUFFER)
     58     {
     59         buffer = context->getRenderbuffer(handle);
     60     }
     61     else if (IsInternalTextureTarget(type))
     62     {
     63         buffer = context->getTexture(handle)->getRenderbuffer(type);
     64     }
     65     else
     66     {
     67         UNREACHABLE();
     68     }
     69 
     70     return buffer;
     71 }
     72 
     73 void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer)
     74 {
     75     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
     76     mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE;
     77     mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer));
     78 }
     79 
     80 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
     81 {
     82     mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
     83     mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
     84 }
     85 
     86 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
     87 {
     88     mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
     89     mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
     90 }
     91 
     92 void Framebuffer::detachTexture(GLuint texture)
     93 {
     94     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
     95     {
     96         if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
     97         {
     98             mColorbufferTypes[colorAttachment] = GL_NONE;
     99             mColorbufferPointers[colorAttachment].set(NULL);
    100         }
    101     }
    102 
    103     if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
    104     {
    105         mDepthbufferType = GL_NONE;
    106         mDepthbufferPointer.set(NULL);
    107     }
    108 
    109     if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
    110     {
    111         mStencilbufferType = GL_NONE;
    112         mStencilbufferPointer.set(NULL);
    113     }
    114 }
    115 
    116 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
    117 {
    118     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    119     {
    120         if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
    121         {
    122             mColorbufferTypes[colorAttachment] = GL_NONE;
    123             mColorbufferPointers[colorAttachment].set(NULL);
    124         }
    125     }
    126 
    127     if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
    128     {
    129         mDepthbufferType = GL_NONE;
    130         mDepthbufferPointer.set(NULL);
    131     }
    132 
    133     if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
    134     {
    135         mStencilbufferType = GL_NONE;
    136         mStencilbufferPointer.set(NULL);
    137     }
    138 }
    139 
    140 unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const
    141 {
    142     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
    143 
    144     Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get();
    145 
    146     if (colorbuffer)
    147     {
    148         return colorbuffer->getSerial();
    149     }
    150 
    151     return 0;
    152 }
    153 
    154 unsigned int Framebuffer::getDepthbufferSerial() const
    155 {
    156     Renderbuffer *depthbuffer = mDepthbufferPointer.get();
    157 
    158     if (depthbuffer)
    159     {
    160         return depthbuffer->getSerial();
    161     }
    162 
    163     return 0;
    164 }
    165 
    166 unsigned int Framebuffer::getStencilbufferSerial() const
    167 {
    168     Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
    169 
    170     if (stencilbuffer)
    171     {
    172         return stencilbuffer->getSerial();
    173     }
    174 
    175     return 0;
    176 }
    177 
    178 Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
    179 {
    180     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
    181     return mColorbufferPointers[colorAttachment].get();
    182 }
    183 
    184 Renderbuffer *Framebuffer::getDepthbuffer() const
    185 {
    186     return mDepthbufferPointer.get();
    187 }
    188 
    189 Renderbuffer *Framebuffer::getStencilbuffer() const
    190 {
    191     return mStencilbufferPointer.get();
    192 }
    193 
    194 Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const
    195 {
    196     Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
    197 
    198     if (!depthstencilbuffer)
    199     {
    200         depthstencilbuffer = mStencilbufferPointer.get();
    201     }
    202 
    203     return depthstencilbuffer;
    204 }
    205 
    206 Renderbuffer *Framebuffer::getReadColorbuffer() const
    207 {
    208     // Will require more logic if glReadBuffers is supported
    209     return mColorbufferPointers[0].get();
    210 }
    211 
    212 GLenum Framebuffer::getReadColorbufferType() const
    213 {
    214     // Will require more logic if glReadBuffers is supported
    215     return mColorbufferTypes[0];
    216 }
    217 
    218 Renderbuffer *Framebuffer::getFirstColorbuffer() const
    219 {
    220     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    221     {
    222         if (mColorbufferTypes[colorAttachment] != GL_NONE)
    223         {
    224             return mColorbufferPointers[colorAttachment].get();
    225         }
    226     }
    227 
    228     return NULL;
    229 }
    230 
    231 GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
    232 {
    233     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
    234     return mColorbufferTypes[colorAttachment];
    235 }
    236 
    237 GLenum Framebuffer::getDepthbufferType() const
    238 {
    239     return mDepthbufferType;
    240 }
    241 
    242 GLenum Framebuffer::getStencilbufferType() const
    243 {
    244     return mStencilbufferType;
    245 }
    246 
    247 GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
    248 {
    249     ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
    250     return mColorbufferPointers[colorAttachment].id();
    251 }
    252 
    253 GLuint Framebuffer::getDepthbufferHandle() const
    254 {
    255     return mDepthbufferPointer.id();
    256 }
    257 
    258 GLuint Framebuffer::getStencilbufferHandle() const
    259 {
    260     return mStencilbufferPointer.id();
    261 }
    262 
    263 GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
    264 {
    265     return mDrawBufferStates[colorAttachment];
    266 }
    267 
    268 void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
    269 {
    270     mDrawBufferStates[colorAttachment] = drawBuffer;
    271 }
    272 
    273 bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
    274 {
    275     return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE);
    276 }
    277 
    278 bool Framebuffer::hasEnabledColorAttachment() const
    279 {
    280     for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    281     {
    282         if (isEnabledColorAttachment(colorAttachment))
    283         {
    284             return true;
    285         }
    286     }
    287 
    288     return false;
    289 }
    290 
    291 bool Framebuffer::hasStencil() const
    292 {
    293     if (mStencilbufferType != GL_NONE)
    294     {
    295         const Renderbuffer *stencilbufferObject = getStencilbuffer();
    296 
    297         if (stencilbufferObject)
    298         {
    299             return stencilbufferObject->getStencilSize() > 0;
    300         }
    301     }
    302 
    303     return false;
    304 }
    305 
    306 bool Framebuffer::usingExtendedDrawBuffers() const
    307 {
    308     for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    309     {
    310         if (isEnabledColorAttachment(colorAttachment))
    311         {
    312             return true;
    313         }
    314     }
    315 
    316     return false;
    317 }
    318 
    319 GLenum Framebuffer::completeness() const
    320 {
    321     int width = 0;
    322     int height = 0;
    323     int colorbufferSize = 0;
    324     int samples = -1;
    325     bool missingAttachment = true;
    326 
    327     for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    328     {
    329         if (mColorbufferTypes[colorAttachment] != GL_NONE)
    330         {
    331             const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment);
    332 
    333             if (!colorbuffer)
    334             {
    335                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    336             }
    337 
    338             if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
    339             {
    340                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    341             }
    342 
    343             if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
    344             {
    345                 if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
    346                 {
    347                     return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    348                 }
    349             }
    350             else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
    351             {
    352                 GLint internalformat = colorbuffer->getInternalFormat();
    353                 GLenum format = gl::ExtractFormat(internalformat);
    354 
    355                 if (IsCompressed(format) ||
    356                     format == GL_ALPHA ||
    357                     format == GL_LUMINANCE ||
    358                     format == GL_LUMINANCE_ALPHA)
    359                 {
    360                     return GL_FRAMEBUFFER_UNSUPPORTED;
    361                 }
    362 
    363                 bool filtering, renderable;
    364 
    365                 if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
    366                     (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
    367                 {
    368                     return GL_FRAMEBUFFER_UNSUPPORTED;
    369                 }
    370 
    371                 if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat))
    372                 {
    373                     return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    374                 }
    375             }
    376             else
    377             {
    378                 UNREACHABLE();
    379                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    380             }
    381 
    382             if (!missingAttachment)
    383             {
    384                 // all color attachments must have the same width and height
    385                 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
    386                 {
    387                     return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
    388                 }
    389 
    390                 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
    391                 // all color attachments have the same number of samples for the FBO to be complete.
    392                 if (colorbuffer->getSamples() != samples)
    393                 {
    394                     return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
    395                 }
    396 
    397                 // all color attachments attachments must have the same number of bitplanes
    398                 if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize)
    399                 {
    400                     return GL_FRAMEBUFFER_UNSUPPORTED;
    401                 }
    402 
    403                 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
    404                 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
    405                 {
    406                     if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get())
    407                     {
    408                         return GL_FRAMEBUFFER_UNSUPPORTED;
    409                     }
    410                 }
    411             }
    412             else
    413             {
    414                 width = colorbuffer->getWidth();
    415                 height = colorbuffer->getHeight();
    416                 samples = colorbuffer->getSamples();
    417                 colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat());
    418                 missingAttachment = false;
    419             }
    420         }
    421     }
    422 
    423     const Renderbuffer *depthbuffer = NULL;
    424     const Renderbuffer *stencilbuffer = NULL;
    425 
    426     if (mDepthbufferType != GL_NONE)
    427     {
    428         depthbuffer = getDepthbuffer();
    429 
    430         if (!depthbuffer)
    431         {
    432             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    433         }
    434 
    435         if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
    436         {
    437             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    438         }
    439 
    440         if (mDepthbufferType == GL_RENDERBUFFER)
    441         {
    442             if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
    443             {
    444                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    445             }
    446         }
    447         else if (IsInternalTextureTarget(mDepthbufferType))
    448         {
    449             GLint internalformat = depthbuffer->getInternalFormat();
    450 
    451             // depth texture attachments require OES/ANGLE_depth_texture
    452             if (!mRenderer->getDepthTextureSupport())
    453             {
    454                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    455             }
    456 
    457             if (!gl::IsDepthTexture(internalformat))
    458             {
    459                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    460             }
    461         }
    462         else
    463         {
    464             UNREACHABLE();
    465             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    466         }
    467 
    468         if (missingAttachment)
    469         {
    470             width = depthbuffer->getWidth();
    471             height = depthbuffer->getHeight();
    472             samples = depthbuffer->getSamples();
    473             missingAttachment = false;
    474         }
    475         else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
    476         {
    477             return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
    478         }
    479         else if (samples != depthbuffer->getSamples())
    480         {
    481             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
    482         }
    483     }
    484 
    485     if (mStencilbufferType != GL_NONE)
    486     {
    487         stencilbuffer = getStencilbuffer();
    488 
    489         if (!stencilbuffer)
    490         {
    491             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    492         }
    493 
    494         if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
    495         {
    496             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    497         }
    498 
    499         if (mStencilbufferType == GL_RENDERBUFFER)
    500         {
    501             if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
    502             {
    503                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    504             }
    505         }
    506         else if (IsInternalTextureTarget(mStencilbufferType))
    507         {
    508             GLint internalformat = stencilbuffer->getInternalFormat();
    509 
    510             // texture stencil attachments come along as part
    511             // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
    512             if (!mRenderer->getDepthTextureSupport())
    513             {
    514                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    515             }
    516 
    517             if (!gl::IsStencilTexture(internalformat))
    518             {
    519                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    520             }
    521         }
    522         else
    523         {
    524             UNREACHABLE();
    525             return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
    526         }
    527 
    528         if (missingAttachment)
    529         {
    530             width = stencilbuffer->getWidth();
    531             height = stencilbuffer->getHeight();
    532             samples = stencilbuffer->getSamples();
    533             missingAttachment = false;
    534         }
    535         else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
    536         {
    537             return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
    538         }
    539         else if (samples != stencilbuffer->getSamples())
    540         {
    541             return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
    542         }
    543     }
    544 
    545     // if we have both a depth and stencil buffer, they must refer to the same object
    546     // since we only support packed_depth_stencil and not separate depth and stencil
    547     if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
    548     {
    549         return GL_FRAMEBUFFER_UNSUPPORTED;
    550     }
    551 
    552     // we need to have at least one attachment to be complete
    553     if (missingAttachment)
    554     {
    555         return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
    556     }
    557 
    558     return GL_FRAMEBUFFER_COMPLETE;
    559 }
    560 
    561 DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
    562     : Framebuffer(renderer)
    563 {
    564     mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer));
    565 
    566     Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
    567     mDepthbufferPointer.set(depthStencilRenderbuffer);
    568     mStencilbufferPointer.set(depthStencilRenderbuffer);
    569 
    570     mColorbufferTypes[0] = GL_RENDERBUFFER;
    571     mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
    572     mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
    573 
    574     mDrawBufferStates[0] = GL_BACK;
    575     mReadBufferState = GL_BACK;
    576 }
    577 
    578 int Framebuffer::getSamples() const
    579 {
    580     if (completeness() == GL_FRAMEBUFFER_COMPLETE)
    581     {
    582         // for a complete framebuffer, all attachments must have the same sample count
    583         // in this case return the first nonzero sample size
    584         for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
    585         {
    586             if (mColorbufferTypes[colorAttachment] != GL_NONE)
    587             {
    588                 return getColorbuffer(colorAttachment)->getSamples();
    589             }
    590         }
    591     }
    592 
    593     return 0;
    594 }
    595 
    596 GLenum DefaultFramebuffer::completeness() const
    597 {
    598     // The default framebuffer *must* always be complete, though it may not be
    599     // subject to the same rules as application FBOs. ie, it could have 0x0 size.
    600     return GL_FRAMEBUFFER_COMPLETE;
    601 }
    602 
    603 }
    604