-// 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()
return mStencilbufferType;
}
-GLuint Framebuffer::getColorbufferName()
+GLuint Framebuffer::getColorbufferName(GLuint index)
{
- return mColorbufferPointer.name();
+ return mColorbufferPointer[index].name();
}
GLuint Framebuffer::getDepthbufferName()
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)
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)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if(mDepthbufferType == GL_RENDERBUFFER)
+ if(IsRenderbuffer(mDepthbufferType))
{
if(!es2::IsDepthRenderable(depthbuffer->getFormat()))
{
}
else
{
- UNREACHABLE();
+ UNREACHABLE(mDepthbufferType);
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if(mStencilbufferType == GL_RENDERBUFFER)
+ if(IsRenderbuffer(mStencilbufferType))
{
if(!es2::IsStencilRenderable(stencilbuffer->getFormat()))
{
}
else
{
- UNREACHABLE();
+ UNREACHABLE(mStencilbufferType);
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
}
- // 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;
}
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;
}
}