OSDN Git Service

Fix not returning GL_BGRA_EXT for incompatible format types.
[android-x86/external-swiftshader.git] / src / OpenGL / libGLESv2 / Framebuffer.cpp
index d59b715..6227577 100644 (file)
@@ -1,13 +1,16 @@
-// SwiftShader Software Renderer
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
 //
-// Copyright(c) 2005-2013 TransGaming Inc.
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
 //
-// All rights reserved. No part of this software may be copied, distributed, transmitted,
-// transcribed, stored in a retrieval system, translated into any human or computer
-// language by any means, or disclosed to third parties without the explicit written
-// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
-// or implied, including but not limited to any patent rights, are granted to you.
+//    http://www.apache.org/licenses/LICENSE-2.0
 //
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 // Framebuffer.cpp: Implements the Framebuffer class. Implements GL framebuffer
 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
 namespace es2
 {
 
+bool Framebuffer::IsRenderbuffer(GLenum type)
+{
+       return type == GL_RENDERBUFFER || type == GL_FRAMEBUFFER_DEFAULT;
+}
+
 Framebuffer::Framebuffer()
 {
-       mColorbufferType = GL_NONE;
+       for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
+       {
+               mColorbufferType[i] = GL_NONE;
+       }
        mDepthbufferType = GL_NONE;
        mStencilbufferType = GL_NONE;
+
+       readBuffer = GL_BACK;
+       drawBuffer[0] = GL_BACK;
+       for(int i = 1; i < MAX_COLOR_ATTACHMENTS; ++i)
+       {
+               drawBuffer[i] = GL_NONE;
+       }
 }
 
 Framebuffer::~Framebuffer()
 {
-       mColorbufferPointer = NULL;
-       mDepthbufferPointer = NULL;
-       mStencilbufferPointer = NULL;
+       for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
+       {
+               mColorbufferPointer[i] = nullptr;
+       }
+       mDepthbufferPointer = nullptr;
+       mStencilbufferPointer = nullptr;
 }
 
-Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
+Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const
 {
        Context *context = getContext();
-       Renderbuffer *buffer = NULL;
+       Renderbuffer *buffer = nullptr;
 
        if(type == GL_NONE)
        {
-               buffer = NULL;
+               buffer = nullptr;
        }
-       else if(type == GL_RENDERBUFFER)
+       else if(IsRenderbuffer(type))
        {
                buffer = context->getRenderbuffer(handle);
        }
        else if(IsTextureTarget(type))
        {
-               buffer = context->getTexture(handle)->getRenderbuffer(type);
-       }
-       else
-       {
-               UNREACHABLE();
+               buffer = context->getTexture(handle)->getRenderbuffer(type, level, layer);
        }
+       else UNREACHABLE(type);
 
        return buffer;
 }
 
-void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
+void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index, GLint level, GLint layer)
 {
-       mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
-       mColorbufferPointer = lookupRenderbuffer(type, colorbuffer);
+       mColorbufferType[index] = (colorbuffer != 0) ? type : GL_NONE;
+       mColorbufferPointer[index] = lookupRenderbuffer(type, colorbuffer, level, layer);
 }
 
-void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
+void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
 {
        mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
-       mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer);
+       mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer, level, layer);
 }
 
-void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
+void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
 {
        mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
-       mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer);
+       mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level, layer);
+}
+
+void Framebuffer::setReadBuffer(GLenum buf)
+{
+       readBuffer = buf;
+}
+
+void Framebuffer::setDrawBuffer(GLuint index, GLenum buf)
+{
+       drawBuffer[index] = buf;
+}
+
+GLenum Framebuffer::getReadBuffer() const
+{
+       return readBuffer;
+}
+
+GLenum Framebuffer::getDrawBuffer(GLuint index) const
+{
+       return drawBuffer[index];
 }
 
 void Framebuffer::detachTexture(GLuint texture)
 {
-       if(mColorbufferPointer.name() == texture && IsTextureTarget(mColorbufferType))
+       for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
        {
-               mColorbufferType = GL_NONE;
-               mColorbufferPointer = NULL;
+               if(mColorbufferPointer[i].name() == texture && IsTextureTarget(mColorbufferType[i]))
+               {
+                       mColorbufferType[i] = GL_NONE;
+                       mColorbufferPointer[i] = nullptr;
+               }
        }
 
        if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType))
        {
                mDepthbufferType = GL_NONE;
-               mDepthbufferPointer = NULL;
+               mDepthbufferPointer = nullptr;
        }
 
        if(mStencilbufferPointer.name() == texture && IsTextureTarget(mStencilbufferType))
        {
                mStencilbufferType = GL_NONE;
-               mStencilbufferPointer = NULL;
+               mStencilbufferPointer = nullptr;
        }
 }
 
 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
 {
-       if(mColorbufferPointer.name() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
+       for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
        {
-               mColorbufferType = GL_NONE;
-               mColorbufferPointer = NULL;
+               if(mColorbufferPointer[i].name() == renderbuffer && IsRenderbuffer(mColorbufferType[i]))
+               {
+                       mColorbufferType[i] = GL_NONE;
+                       mColorbufferPointer[i] = nullptr;
+               }
        }
 
-       if(mDepthbufferPointer.name() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
+       if(mDepthbufferPointer.name() == renderbuffer && IsRenderbuffer(mDepthbufferType))
        {
                mDepthbufferType = GL_NONE;
-               mDepthbufferPointer = NULL;
+               mDepthbufferPointer = nullptr;
        }
 
-       if(mStencilbufferPointer.name() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
+       if(mStencilbufferPointer.name() == renderbuffer && IsRenderbuffer(mStencilbufferType))
        {
                mStencilbufferType = GL_NONE;
-               mStencilbufferPointer = NULL;
+               mStencilbufferPointer = nullptr;
        }
 }
 
 // Increments refcount on surface.
 // caller must Release() the returned surface
-egl::Image *Framebuffer::getRenderTarget()
+egl::Image *Framebuffer::getRenderTarget(GLuint index)
 {
-       Renderbuffer *colorbuffer = mColorbufferPointer;
+       Renderbuffer *colorbuffer = mColorbufferPointer[index];
 
        if(colorbuffer)
        {
                return colorbuffer->getRenderTarget();
        }
 
-       return NULL;
+       return nullptr;
+}
+
+egl::Image *Framebuffer::getReadRenderTarget()
+{
+       Context *context = getContext();
+       return getRenderTarget(context->getReadFramebufferColorIndex());
 }
 
 // Increments refcount on surface.
 // caller must Release() the returned surface
-egl::Image *Framebuffer::getDepthStencil()
+egl::Image *Framebuffer::getDepthBuffer()
 {
-       Renderbuffer *depthstencilbuffer = mDepthbufferPointer;
-       
-       if(!depthstencilbuffer)
+       Renderbuffer *depthbuffer = mDepthbufferPointer;
+
+       if(depthbuffer)
        {
-               depthstencilbuffer = mStencilbufferPointer;
+               return depthbuffer->getRenderTarget();
        }
 
-       if(depthstencilbuffer)
+       return nullptr;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+egl::Image *Framebuffer::getStencilBuffer()
+{
+       Renderbuffer *stencilbuffer = mStencilbufferPointer;
+
+       if(stencilbuffer)
        {
-               return depthstencilbuffer->getRenderTarget();
+               return stencilbuffer->getRenderTarget();
        }
 
-       return NULL;
+       return nullptr;
+}
+
+Renderbuffer *Framebuffer::getColorbuffer(GLuint index) const
+{
+       return (index < MAX_COLOR_ATTACHMENTS) ? mColorbufferPointer[index] : (Renderbuffer*)nullptr;
 }
 
-Renderbuffer *Framebuffer::getColorbuffer()
+Renderbuffer *Framebuffer::getReadColorbuffer() const
 {
-       return mColorbufferPointer;
+       Context *context = getContext();
+       return getColorbuffer(context->getReadFramebufferColorIndex());
 }
 
-Renderbuffer *Framebuffer::getDepthbuffer()
+Renderbuffer *Framebuffer::getDepthbuffer() const
 {
        return mDepthbufferPointer;
 }
 
-Renderbuffer *Framebuffer::getStencilbuffer()
+Renderbuffer *Framebuffer::getStencilbuffer() const
 {
        return mStencilbufferPointer;
 }
 
-GLenum Framebuffer::getColorbufferType()
+GLenum Framebuffer::getColorbufferType(GLuint index)
 {
-       return mColorbufferType;
+       return mColorbufferType[index];
 }
 
 GLenum Framebuffer::getDepthbufferType()
@@ -184,9 +249,9 @@ GLenum Framebuffer::getStencilbufferType()
        return mStencilbufferType;
 }
 
-GLuint Framebuffer::getColorbufferName()
+GLuint Framebuffer::getColorbufferName(GLuint index)
 {
-       return mColorbufferPointer.name();
+       return mColorbufferPointer[index].name();
 }
 
 GLuint Framebuffer::getDepthbufferName()
@@ -199,6 +264,22 @@ GLuint Framebuffer::getStencilbufferName()
        return mStencilbufferPointer.name();
 }
 
+GLint Framebuffer::getColorbufferLayer(GLuint index)
+{
+       Renderbuffer *colorbuffer = mColorbufferPointer[index];
+       return colorbuffer ? colorbuffer->getLayer() : 0;
+}
+
+GLint Framebuffer::getDepthbufferLayer()
+{
+       return mDepthbufferPointer ? mDepthbufferPointer->getLayer() : 0;
+}
+
+GLint Framebuffer::getStencilbufferLayer()
+{
+       return mStencilbufferPointer ? mStencilbufferPointer->getLayer() : 0;
+}
+
 bool Framebuffer::hasStencil()
 {
        if(mStencilbufferType != GL_NONE)
@@ -229,57 +310,65 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
        height = -1;
        samples = -1;
 
-       if(mColorbufferType != GL_NONE)
+       for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
        {
-               Renderbuffer *colorbuffer = getColorbuffer();
-
-               if(!colorbuffer)
+               if(mColorbufferType[i] != GL_NONE)
                {
-                       return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-               }
+                       Renderbuffer *colorbuffer = getColorbuffer(i);
 
-               if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
-               {
-                       return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-               }
+                       if(!colorbuffer)
+                       {
+                               return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+                       }
 
-               if(mColorbufferType == GL_RENDERBUFFER)
-               {
-                       if(!es2::IsColorRenderable(colorbuffer->getFormat()))
+                       if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0 || (colorbuffer->getDepth() <= colorbuffer->getLayer()))
                        {
                                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
                        }
-               }
-               else if(IsTextureTarget(mColorbufferType))
-               {
-                       GLenum format = colorbuffer->getFormat();
 
-                       if(IsCompressed(format) ||
-                          format == GL_ALPHA ||
-                          format == GL_LUMINANCE ||
-                          format == GL_LUMINANCE_ALPHA)
+                       if(IsRenderbuffer(mColorbufferType[i]))
                        {
-                               return GL_FRAMEBUFFER_UNSUPPORTED;
+                               if(!IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion()))
+                               {
+                                       return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+                               }
                        }
+                       else if(IsTextureTarget(mColorbufferType[i]))
+                       {
+                               GLenum format = colorbuffer->getFormat();
+
+                               if(!IsColorRenderable(format, egl::getClientVersion()))
+                               {
+                                       return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+                               }
 
-                       if(es2::IsDepthTexture(format) || es2::IsStencilTexture(format))
+                               if(IsDepthTexture(format) || IsStencilTexture(format))
+                               {
+                                       return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+                               }
+                       }
+                       else
                        {
+                               UNREACHABLE(mColorbufferType[i]);
                                return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
                        }
-               }
-               else
-               {
-                       UNREACHABLE();
-                       return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
-               }
 
-               width = colorbuffer->getWidth();
-               height = colorbuffer->getHeight();
-               samples = colorbuffer->getSamples();
+                       width = colorbuffer->getWidth();
+                       height = colorbuffer->getHeight();
+
+                       if(samples == -1)
+                       {
+                               samples = colorbuffer->getSamples();
+                       }
+                       else if(samples != colorbuffer->getSamples())
+                       {
+                               return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+                       }
+               }
        }
 
-       Renderbuffer *depthbuffer = NULL;
-       Renderbuffer *stencilbuffer = NULL;
+       Renderbuffer *depthbuffer = nullptr;
+       Renderbuffer *stencilbuffer = nullptr;
 
        if(mDepthbufferType != GL_NONE)
        {
@@ -295,7 +384,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
                        return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
                }
 
-               if(mDepthbufferType == GL_RENDERBUFFER)
+               if(IsRenderbuffer(mDepthbufferType))
                {
                        if(!es2::IsDepthRenderable(depthbuffer->getFormat()))
                        {
@@ -311,7 +400,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
                }
                else
                {
-                       UNREACHABLE();
+                       UNREACHABLE(mDepthbufferType);
                        return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
                }
 
@@ -345,7 +434,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
                        return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
                }
 
-               if(mStencilbufferType == GL_RENDERBUFFER)
+               if(IsRenderbuffer(mStencilbufferType))
                {
                        if(!es2::IsStencilRenderable(stencilbuffer->getFormat()))
                        {
@@ -363,7 +452,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
                }
                else
                {
-                       UNREACHABLE();
+                       UNREACHABLE(mStencilbufferType);
                        return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
                }
 
@@ -383,10 +472,13 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
                }
        }
 
-       // If we have both a depth and stencil buffer, they must refer to the same object
-       // since we only support packed_depth_stencil and not separate depth and stencil
-       if(depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
+       if((egl::getClientVersion() >= 3) && depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
        {
+               // In the GLES 3.0 spec, section 4.4.4, Framebuffer Completeness:
+               // "The framebuffer object target is said to be framebuffer complete if all the following conditions are true:
+               //  [...]
+               //  Depth and stencil attachments, if present, are the same image.
+               //  { FRAMEBUFFER_UNSUPPORTED }"
                return GL_FRAMEBUFFER_UNSUPPORTED;
        }
 
@@ -399,74 +491,190 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
        return GL_FRAMEBUFFER_COMPLETE;
 }
 
-GLenum Framebuffer::getImplementationColorReadFormat()
+GLenum Framebuffer::getImplementationColorReadFormat() const
 {
-       Renderbuffer *colorbuffer = mColorbufferPointer;
-       
+       Renderbuffer *colorbuffer = getReadColorbuffer();
+
        if(colorbuffer)
        {
-               // Don't return GL_RGBA since that's always supported. Provide a second option here.
                switch(colorbuffer->getInternalFormat())
                {
-               case sw::FORMAT_A16B16G16R16F: return GL_BGRA_EXT;
-               case sw::FORMAT_A32B32G32R32F: return GL_BGRA_EXT;
-               case sw::FORMAT_A8R8G8B8:      return GL_BGRA_EXT;
-               case sw::FORMAT_A8B8G8R8:      return GL_BGRA_EXT;
-               case sw::FORMAT_X8R8G8B8:      return 0x80E0;   // GL_BGR_EXT
-               case sw::FORMAT_X8B8G8R8:      return 0x80E0;   // GL_BGR_EXT
-               case sw::FORMAT_A1R5G5B5:      return GL_BGRA_EXT;
-               case sw::FORMAT_R5G6B5:        return 0x80E0;   // GL_BGR_EXT
+               case sw::FORMAT_A8B8G8R8I:       return GL_RGBA_INTEGER;
+               case sw::FORMAT_A8B8G8R8UI:      return GL_RGBA_INTEGER;
+               case sw::FORMAT_A16B16G16R16I:   return GL_RGBA_INTEGER;
+               case sw::FORMAT_A16B16G16R16UI:  return GL_RGBA_INTEGER;
+               case sw::FORMAT_A32B32G32R32I:   return GL_RGBA_INTEGER;
+               case sw::FORMAT_A32B32G32R32UI:  return GL_RGBA_INTEGER;
+               case sw::FORMAT_A2B10G10R10:     return GL_RGB10_A2;
+               case sw::FORMAT_A8B8G8R8I_SNORM: return GL_RGBA;
+               case sw::FORMAT_A8B8G8R8:        return GL_RGBA;
+               case sw::FORMAT_SRGB8_A8:        return GL_RGBA;
+               case sw::FORMAT_A8R8G8B8:        return GL_BGRA_EXT;
+               case sw::FORMAT_A1R5G5B5:        return GL_BGRA_EXT;
+               case sw::FORMAT_X8B8G8R8I:       return GL_RGBA_INTEGER;
+               case sw::FORMAT_X8B8G8R8UI:      return GL_RGBA_INTEGER;
+               case sw::FORMAT_X16B16G16R16I:   return GL_RGBA_INTEGER;
+               case sw::FORMAT_X16B16G16R16UI:  return GL_RGBA_INTEGER;
+               case sw::FORMAT_X32B32G32R32I:   return GL_RGBA_INTEGER;
+               case sw::FORMAT_X32B32G32R32UI:  return GL_RGBA_INTEGER;
+               case sw::FORMAT_X8B8G8R8I_SNORM: return GL_RGBA;
+               case sw::FORMAT_SRGB8_X8:        return GL_RGBA;
+               case sw::FORMAT_X8B8G8R8:        return GL_RGBA;
+               case sw::FORMAT_X8R8G8B8:        return GL_BGRA_EXT;
+               case sw::FORMAT_R5G6B5:          return GL_RGB;
+               case sw::FORMAT_G8R8I:           return GL_RG_INTEGER;
+               case sw::FORMAT_G8R8UI:          return GL_RG_INTEGER;
+               case sw::FORMAT_G16R16I:         return GL_RG_INTEGER;
+               case sw::FORMAT_G16R16UI:        return GL_RG_INTEGER;
+               case sw::FORMAT_G32R32I:         return GL_RG_INTEGER;
+               case sw::FORMAT_G32R32UI:        return GL_RG_INTEGER;
+               case sw::FORMAT_R8I:             return GL_RED_INTEGER;
+               case sw::FORMAT_R8UI:            return GL_RED_INTEGER;
+               case sw::FORMAT_R16I:            return GL_RED_INTEGER;
+               case sw::FORMAT_R16UI:           return GL_RED_INTEGER;
+               case sw::FORMAT_R32I:            return GL_RED_INTEGER;
+               case sw::FORMAT_R32UI:           return GL_RED_INTEGER;
+               case sw::FORMAT_R8:              return GL_RED;
+               case sw::FORMAT_R8I_SNORM:       return GL_RED;
+               case sw::FORMAT_R16F:            return GL_RED;
+               case sw::FORMAT_R32F:            return GL_RED;
+               case sw::FORMAT_G8R8:            return GL_RG;
+               case sw::FORMAT_G8R8I_SNORM:     return GL_RG;
+               case sw::FORMAT_G16R16F:         return GL_RG;
+               case sw::FORMAT_G32R32F:         return GL_RG;
+               case sw::FORMAT_B16G16R16F:      return GL_RGB;
+               case sw::FORMAT_X32B32G32R32F:   return GL_RGBA;
+               case sw::FORMAT_A16B16G16R16F:   return GL_RGBA;
+               case sw::FORMAT_A32B32G32R32F:   return GL_RGBA;
                default:
-                       UNREACHABLE();
+                       UNREACHABLE(colorbuffer->getInternalFormat());
                }
        }
 
        return GL_RGBA;
 }
 
-GLenum Framebuffer::getImplementationColorReadType()
+GLenum Framebuffer::getImplementationColorReadType() const
 {
-       Renderbuffer *colorbuffer = mColorbufferPointer;
-       
+       Renderbuffer *colorbuffer = getReadColorbuffer();
+
        if(colorbuffer)
        {
                switch(colorbuffer->getInternalFormat())
                {
-               case sw::FORMAT_A16B16G16R16F: return GL_HALF_FLOAT_OES;
-               case sw::FORMAT_A32B32G32R32F: return GL_FLOAT;
-               case sw::FORMAT_A8R8G8B8:      return GL_UNSIGNED_BYTE;
-               case sw::FORMAT_A8B8G8R8:      return GL_UNSIGNED_BYTE;
-               case sw::FORMAT_X8R8G8B8:      return GL_UNSIGNED_BYTE;
-               case sw::FORMAT_X8B8G8R8:      return GL_UNSIGNED_BYTE;
-               case sw::FORMAT_A1R5G5B5:      return GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
-               case sw::FORMAT_R5G6B5:        return GL_UNSIGNED_SHORT_5_6_5;
+               case sw::FORMAT_R16F:            return GL_FLOAT;
+               case sw::FORMAT_G16R16F:         return GL_FLOAT;
+               case sw::FORMAT_B16G16R16F:      return GL_FLOAT;
+               case sw::FORMAT_A16B16G16R16F:   return GL_FLOAT;
+               case sw::FORMAT_R32F:            return GL_FLOAT;
+               case sw::FORMAT_G32R32F:         return GL_FLOAT;
+               case sw::FORMAT_B32G32R32F:      return GL_FLOAT;
+               case sw::FORMAT_X32B32G32R32F:   return GL_FLOAT;
+               case sw::FORMAT_A32B32G32R32F:   return GL_FLOAT;
+               case sw::FORMAT_R8I_SNORM:       return GL_BYTE;
+               case sw::FORMAT_G8R8I_SNORM:     return GL_BYTE;
+               case sw::FORMAT_X8B8G8R8I_SNORM: return GL_BYTE;
+               case sw::FORMAT_A8B8G8R8I_SNORM: return GL_BYTE;
+               case sw::FORMAT_R8:              return GL_UNSIGNED_BYTE;
+               case sw::FORMAT_G8R8:            return GL_UNSIGNED_BYTE;
+               case sw::FORMAT_SRGB8_X8:        return GL_UNSIGNED_BYTE;
+               case sw::FORMAT_SRGB8_A8:        return GL_UNSIGNED_BYTE;
+               case sw::FORMAT_A8R8G8B8:        return GL_UNSIGNED_BYTE;
+               case sw::FORMAT_A8B8G8R8:        return GL_UNSIGNED_BYTE;
+               case sw::FORMAT_X8R8G8B8:        return GL_UNSIGNED_BYTE;
+               case sw::FORMAT_X8B8G8R8:        return GL_UNSIGNED_BYTE;
+               case sw::FORMAT_R8I:             return GL_INT;
+               case sw::FORMAT_G8R8I:           return GL_INT;
+               case sw::FORMAT_X8B8G8R8I:       return GL_INT;
+               case sw::FORMAT_A8B8G8R8I:       return GL_INT;
+               case sw::FORMAT_R16I:            return GL_INT;
+               case sw::FORMAT_G16R16I:         return GL_INT;
+               case sw::FORMAT_X16B16G16R16I:   return GL_INT;
+               case sw::FORMAT_A16B16G16R16I:   return GL_INT;
+               case sw::FORMAT_R32I:            return GL_INT;
+               case sw::FORMAT_G32R32I:         return GL_INT;
+               case sw::FORMAT_X32B32G32R32I:   return GL_INT;
+               case sw::FORMAT_A32B32G32R32I:   return GL_INT;
+               case sw::FORMAT_R8UI:            return GL_UNSIGNED_INT;
+               case sw::FORMAT_G8R8UI:          return GL_UNSIGNED_INT;
+               case sw::FORMAT_X8B8G8R8UI:      return GL_UNSIGNED_INT;
+               case sw::FORMAT_A8B8G8R8UI:      return GL_UNSIGNED_INT;
+               case sw::FORMAT_R16UI:           return GL_UNSIGNED_INT;
+               case sw::FORMAT_G16R16UI:        return GL_UNSIGNED_INT;
+               case sw::FORMAT_X16B16G16R16UI:  return GL_UNSIGNED_INT;
+               case sw::FORMAT_A16B16G16R16UI:  return GL_UNSIGNED_INT;
+               case sw::FORMAT_R32UI:           return GL_UNSIGNED_INT;
+               case sw::FORMAT_G32R32UI:        return GL_UNSIGNED_INT;
+               case sw::FORMAT_X32B32G32R32UI:  return GL_UNSIGNED_INT;
+               case sw::FORMAT_A32B32G32R32UI:  return GL_UNSIGNED_INT;
+               case sw::FORMAT_A2B10G10R10:     return GL_UNSIGNED_INT_10_10_10_2_OES;
+               case sw::FORMAT_A1R5G5B5:        return GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
+               case sw::FORMAT_R5G6B5:          return GL_UNSIGNED_SHORT_5_6_5;
                default:
-                       UNREACHABLE();
+                       UNREACHABLE(colorbuffer->getInternalFormat());
                }
        }
 
        return GL_UNSIGNED_BYTE;
 }
 
-DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
+GLenum Framebuffer::getDepthReadFormat() const
 {
-       mColorbufferPointer = new Renderbuffer(0, colorbuffer);
+       Renderbuffer *depthbuffer = getDepthbuffer();
 
-       Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
-       mDepthbufferPointer = depthStencilRenderbuffer;
-       mStencilbufferPointer = depthStencilRenderbuffer;
+       if(depthbuffer)
+       {
+               // There is only one depth read format.
+               return GL_DEPTH_COMPONENT;
+       }
 
-       mColorbufferType = GL_RENDERBUFFER;
-       mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
-       mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
+       // If there is no depth buffer, GL_INVALID_OPERATION occurs.
+       return GL_NONE;
 }
 
-GLenum DefaultFramebuffer::completeness()
+GLenum Framebuffer::getDepthReadType() const
 {
-       // The default framebuffer should always be complete
-       ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
+       Renderbuffer *depthbuffer = getDepthbuffer();
 
-       return GL_FRAMEBUFFER_COMPLETE;
+       if(depthbuffer)
+       {
+               switch(depthbuffer->getInternalFormat())
+               {
+               case sw::FORMAT_D16:                return GL_UNSIGNED_SHORT;
+               case sw::FORMAT_D24S8:              return GL_UNSIGNED_INT_24_8_OES;
+               case sw::FORMAT_D32:                return GL_UNSIGNED_INT;
+               case sw::FORMAT_D32F:
+               case sw::FORMAT_D32F_COMPLEMENTARY:
+               case sw::FORMAT_D32F_LOCKABLE:
+               case sw::FORMAT_D32FS8_TEXTURE:
+               case sw::FORMAT_D32FS8_SHADOW:      return GL_FLOAT;
+               default:
+                       UNREACHABLE(depthbuffer->getInternalFormat());
+               }
+       }
+
+       // If there is no depth buffer, GL_INVALID_OPERATION occurs.
+       return GL_NONE;
+}
+
+DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
+{
+       GLenum defaultRenderbufferType = egl::getClientVersion() < 3 ? GL_RENDERBUFFER : GL_FRAMEBUFFER_DEFAULT;
+       mColorbufferPointer[0] = new Renderbuffer(0, colorbuffer);
+       mColorbufferType[0] = defaultRenderbufferType;
+
+       for(int i = 1; i < MAX_COLOR_ATTACHMENTS; i++)
+       {
+               mColorbufferPointer[i] = nullptr;
+               mColorbufferType[i] = GL_NONE;
+       }
+
+       Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
+       mDepthbufferPointer = depthStencilRenderbuffer;
+       mStencilbufferPointer = depthStencilRenderbuffer;
+
+       mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? defaultRenderbufferType : GL_NONE;
+       mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? defaultRenderbufferType : GL_NONE;
 }
 
 }