summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp')
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp535
1 files changed, 283 insertions, 252 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
index b0abba0ac4..f808175250 100644
--- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
@@ -1,6 +1,6 @@
#include "precompiled.h"
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -11,253 +11,288 @@
#include "libGLESv2/Framebuffer.h"
#include "libGLESv2/main.h"
-#include "libGLESv2/utilities.h"
+#include "common/utilities.h"
+#include "libGLESv2/formatutils.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/Context.h"
#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/FramebufferAttachment.h"
namespace gl
{
-Framebuffer::Framebuffer(rx::Renderer *renderer)
- : mRenderer(renderer)
+Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
+ : mRenderer(renderer),
+ mId(id),
+ mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
+ mDepthbuffer(NULL),
+ mStencilbuffer(NULL)
{
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- mColorbufferTypes[colorAttachment] = GL_NONE;
+ mColorbuffers[colorAttachment] = NULL;
mDrawBufferStates[colorAttachment] = GL_NONE;
}
mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
- mReadBufferState = GL_COLOR_ATTACHMENT0_EXT;
-
- mDepthbufferType = GL_NONE;
- mStencilbufferType = GL_NONE;
}
Framebuffer::~Framebuffer()
{
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- mColorbufferPointers[colorAttachment].set(NULL);
+ SafeDelete(mColorbuffers[colorAttachment]);
}
- mDepthbufferPointer.set(NULL);
- mStencilbufferPointer.set(NULL);
+ SafeDelete(mDepthbuffer);
+ SafeDelete(mStencilbuffer);
}
-Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
+FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const
{
- gl::Context *context = gl::getContext();
- Renderbuffer *buffer = NULL;
-
- if (type == GL_NONE)
+ if (handle == 0)
{
- buffer = NULL;
+ return NULL;
}
- else if (type == GL_RENDERBUFFER)
- {
- buffer = context->getRenderbuffer(handle);
- }
- else if (IsInternalTextureTarget(type))
- {
- buffer = context->getTexture(handle)->getRenderbuffer(type);
- }
- else
+
+ gl::Context *context = gl::getContext();
+
+ switch (type)
{
+ case GL_NONE:
+ return NULL;
+
+ case GL_RENDERBUFFER:
+ return new RenderbufferAttachment(context->getRenderbuffer(handle));
+
+ case GL_TEXTURE_2D:
+ {
+ Texture *texture = context->getTexture(handle);
+ if (texture && texture->getTarget() == GL_TEXTURE_2D)
+ {
+ Texture2D *tex2D = static_cast<Texture2D*>(texture);
+ return new Texture2DAttachment(tex2D, level);
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ {
+ Texture *texture = context->getTexture(handle);
+ if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
+ {
+ TextureCubeMap *texCube = static_cast<TextureCubeMap*>(texture);
+ return new TextureCubeMapAttachment(texCube, type, level);
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ case GL_TEXTURE_3D:
+ {
+ Texture *texture = context->getTexture(handle);
+ if (texture && texture->getTarget() == GL_TEXTURE_3D)
+ {
+ Texture3D *tex3D = static_cast<Texture3D*>(texture);
+ return new Texture3DAttachment(tex3D, level, layer);
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ Texture *texture = context->getTexture(handle);
+ if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
+ {
+ Texture2DArray *tex2DArray = static_cast<Texture2DArray*>(texture);
+ return new Texture2DArrayAttachment(tex2DArray, level, layer);
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ default:
UNREACHABLE();
+ return NULL;
}
-
- return buffer;
}
-void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer)
+void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
{
ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
- mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE;
- mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer));
+ SafeDelete(mColorbuffers[colorAttachment]);
+ mColorbuffers[colorAttachment] = createAttachment(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.set(lookupRenderbuffer(type, depthbuffer));
+ SafeDelete(mDepthbuffer);
+ mDepthbuffer = createAttachment(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.set(lookupRenderbuffer(type, stencilbuffer));
+ SafeDelete(mStencilbuffer);
+ mStencilbuffer = createAttachment(type, stencilbuffer, level, layer);
}
-void Framebuffer::detachTexture(GLuint texture)
+void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
{
- for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
- {
- mColorbufferTypes[colorAttachment] = GL_NONE;
- mColorbufferPointers[colorAttachment].set(NULL);
- }
- }
+ FramebufferAttachment *attachment = createAttachment(type, depthStencilBuffer, level, layer);
- if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType))
- {
- mDepthbufferType = GL_NONE;
- mDepthbufferPointer.set(NULL);
- }
+ SafeDelete(mDepthbuffer);
+ SafeDelete(mStencilbuffer);
- if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType))
+ // ensure this is a legitimate depth+stencil format
+ if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
{
- mStencilbufferType = GL_NONE;
- mStencilbufferPointer.set(NULL);
+ mDepthbuffer = attachment;
+
+ // Make a new attachment object to ensure we do not double-delete
+ // See angle issue 686
+ mStencilbuffer = createAttachment(type, depthStencilBuffer, level, layer);
}
}
-void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
+void Framebuffer::detachTexture(GLuint textureId)
{
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
+ FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
+
+ if (attachment && attachment->isTextureWithId(textureId))
{
- mColorbufferTypes[colorAttachment] = GL_NONE;
- mColorbufferPointers[colorAttachment].set(NULL);
+ SafeDelete(mColorbuffers[colorAttachment]);
}
}
- if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
+ if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
{
- mDepthbufferType = GL_NONE;
- mDepthbufferPointer.set(NULL);
+ SafeDelete(mDepthbuffer);
}
- if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
+ if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
{
- mStencilbufferType = GL_NONE;
- mStencilbufferPointer.set(NULL);
+ SafeDelete(mStencilbuffer);
}
}
-unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const
+void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
{
- ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
+ for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
- Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get();
+ if (attachment && attachment->isRenderbufferWithId(renderbufferId))
+ {
+ SafeDelete(mColorbuffers[colorAttachment]);
+ }
+ }
- if (colorbuffer)
+ if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
{
- return colorbuffer->getSerial();
+ SafeDelete(mDepthbuffer);
}
- return 0;
-}
-
-unsigned int Framebuffer::getDepthbufferSerial() const
-{
- Renderbuffer *depthbuffer = mDepthbufferPointer.get();
-
- if (depthbuffer)
+ if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
{
- return depthbuffer->getSerial();
+ SafeDelete(mStencilbuffer);
}
-
- return 0;
}
-unsigned int Framebuffer::getStencilbufferSerial() const
+FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
{
- Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
-
- if (stencilbuffer)
- {
- return stencilbuffer->getSerial();
- }
-
- return 0;
+ ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
+ return mColorbuffers[colorAttachment];
}
-Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
+FramebufferAttachment *Framebuffer::getDepthbuffer() const
{
- ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
- return mColorbufferPointers[colorAttachment].get();
+ return mDepthbuffer;
}
-Renderbuffer *Framebuffer::getDepthbuffer() const
+FramebufferAttachment *Framebuffer::getStencilbuffer() const
{
- return mDepthbufferPointer.get();
+ return mStencilbuffer;
}
-Renderbuffer *Framebuffer::getStencilbuffer() const
+FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
{
- return mStencilbufferPointer.get();
+ return (hasValidDepthStencil() ? mDepthbuffer : NULL);
}
-Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const
+FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
{
- Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
+ FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
if (!depthstencilbuffer)
{
- depthstencilbuffer = mStencilbufferPointer.get();
+ depthstencilbuffer = mStencilbuffer;
}
return depthstencilbuffer;
}
-Renderbuffer *Framebuffer::getReadColorbuffer() const
+FramebufferAttachment *Framebuffer::getReadColorbuffer() const
{
// Will require more logic if glReadBuffers is supported
- return mColorbufferPointers[0].get();
+ return mColorbuffers[0];
}
GLenum Framebuffer::getReadColorbufferType() const
{
// Will require more logic if glReadBuffers is supported
- return mColorbufferTypes[0];
+ return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
}
-Renderbuffer *Framebuffer::getFirstColorbuffer() const
+FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
{
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- if (mColorbufferTypes[colorAttachment] != GL_NONE)
+ if (mColorbuffers[colorAttachment])
{
- return mColorbufferPointers[colorAttachment].get();
+ return mColorbuffers[colorAttachment];
}
}
return NULL;
}
-GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const
+FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
{
- ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
- return mColorbufferTypes[colorAttachment];
-}
-
-GLenum Framebuffer::getDepthbufferType() const
-{
- return mDepthbufferType;
-}
-
-GLenum Framebuffer::getStencilbufferType() const
-{
- return mStencilbufferType;
-}
-
-GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const
-{
- ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
- return mColorbufferPointers[colorAttachment].id();
-}
-
-GLuint Framebuffer::getDepthbufferHandle() const
-{
- return mDepthbufferPointer.id();
-}
-
-GLuint Framebuffer::getStencilbufferHandle() const
-{
- return mStencilbufferPointer.id();
+ if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
+ {
+ return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
+ }
+ else
+ {
+ switch (attachment)
+ {
+ case GL_DEPTH_ATTACHMENT:
+ return getDepthbuffer();
+ case GL_STENCIL_ATTACHMENT:
+ return getStencilbuffer();
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ return getDepthStencilBuffer();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ }
}
GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
@@ -272,7 +307,7 @@ void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBu
bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
{
- return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE);
+ return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
}
bool Framebuffer::hasEnabledColorAttachment() const
@@ -290,17 +325,7 @@ bool Framebuffer::hasEnabledColorAttachment() const
bool Framebuffer::hasStencil() const
{
- if (mStencilbufferType != GL_NONE)
- {
- const Renderbuffer *stencilbufferObject = getStencilbuffer();
-
- if (stencilbufferObject)
- {
- return stencilbufferObject->getStencilSize() > 0;
- }
- }
-
- return false;
+ return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
}
bool Framebuffer::usingExtendedDrawBuffers() const
@@ -320,63 +345,43 @@ GLenum Framebuffer::completeness() const
{
int width = 0;
int height = 0;
- int colorbufferSize = 0;
+ unsigned int colorbufferSize = 0;
int samples = -1;
bool missingAttachment = true;
+ GLuint clientVersion = mRenderer->getCurrentClientVersion();
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- if (mColorbufferTypes[colorAttachment] != GL_NONE)
- {
- const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment);
-
- if (!colorbuffer)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
+ if (colorbuffer)
+ {
if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER)
+ GLenum internalformat = colorbuffer->getInternalFormat();
+ // TODO(geofflang): use context's texture caps
+ const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
+ if (colorbuffer->isTexture())
{
- if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
- }
- else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment]))
- {
- GLint internalformat = colorbuffer->getInternalFormat();
- GLenum format = gl::ExtractFormat(internalformat);
-
- if (IsCompressed(format) ||
- format == GL_ALPHA ||
- format == GL_LUMINANCE ||
- format == GL_LUMINANCE_ALPHA)
+ if (!formatCaps.renderable)
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
- bool filtering, renderable;
-
- if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) ||
- (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable)))
- {
- return GL_FRAMEBUFFER_UNSUPPORTED;
- }
-
- if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat))
+ if (gl::GetDepthBits(internalformat) > 0 || gl::GetStencilBits(internalformat) > 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
else
{
- UNREACHABLE();
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!formatCaps.renderable || gl::GetDepthBits(internalformat) > 0 || gl::GetStencilBits(internalformat) > 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
}
if (!missingAttachment)
@@ -394,16 +399,24 @@ GLenum Framebuffer::completeness() const
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
}
- // all color attachments attachments must have the same number of bitplanes
- if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize)
+ // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
+ // in GLES 3.0, there is no such restriction
+ if (clientVersion < 3)
{
- return GL_FRAMEBUFFER_UNSUPPORTED;
+ if (gl::GetPixelBytes(colorbuffer->getInternalFormat()) != colorbufferSize)
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
}
// D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
{
- if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get())
+ const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
+
+ if (previousAttachment &&
+ (colorbuffer->id() == previousAttachment->id() &&
+ colorbuffer->type() == previousAttachment->type()))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
@@ -414,129 +427,120 @@ GLenum Framebuffer::completeness() const
width = colorbuffer->getWidth();
height = colorbuffer->getHeight();
samples = colorbuffer->getSamples();
- colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat());
+ colorbufferSize = gl::GetPixelBytes(colorbuffer->getInternalFormat());
missingAttachment = false;
}
}
}
- const Renderbuffer *depthbuffer = NULL;
- const Renderbuffer *stencilbuffer = NULL;
-
- if (mDepthbufferType != GL_NONE)
+ if (mDepthbuffer)
{
- depthbuffer = getDepthbuffer();
-
- if (!depthbuffer)
+ if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
+ GLenum internalformat = mDepthbuffer->getInternalFormat();
+ // TODO(geofflang): use context's texture caps
+ const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
+ if (mDepthbuffer->isTexture())
{
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ GLenum internalformat = mDepthbuffer->getInternalFormat();
- if (mDepthbufferType == GL_RENDERBUFFER)
- {
- if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat()))
+ // depth texture attachments require OES/ANGLE_depth_texture
+ // TODO(geofflang): use context's extensions
+ if (!mRenderer->getRendererExtensions().depthTextures)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- }
- else if (IsInternalTextureTarget(mDepthbufferType))
- {
- GLint internalformat = depthbuffer->getInternalFormat();
- // depth texture attachments require OES/ANGLE_depth_texture
- if (!mRenderer->getDepthTextureSupport())
+ if (!formatCaps.renderable)
{
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ return GL_FRAMEBUFFER_UNSUPPORTED;
}
- if (!gl::IsDepthTexture(internalformat))
+ if (gl::GetDepthBits(internalformat) == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
else
{
- UNREACHABLE();
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!formatCaps.renderable || gl::GetDepthBits(internalformat) == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
}
if (missingAttachment)
{
- width = depthbuffer->getWidth();
- height = depthbuffer->getHeight();
- samples = depthbuffer->getSamples();
+ width = mDepthbuffer->getWidth();
+ height = mDepthbuffer->getHeight();
+ samples = mDepthbuffer->getSamples();
missingAttachment = false;
}
- else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
+ else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
{
return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
}
- else if (samples != depthbuffer->getSamples())
+ else if (samples != mDepthbuffer->getSamples())
{
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
}
}
- if (mStencilbufferType != GL_NONE)
+ if (mStencilbuffer)
{
- stencilbuffer = getStencilbuffer();
-
- if (!stencilbuffer)
+ if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
+ GLenum internalformat = mStencilbuffer->getInternalFormat();
+ // TODO(geofflang): use context's texture caps
+ const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
+ if (mStencilbuffer->isTexture())
{
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ GLenum internalformat = mStencilbuffer->getInternalFormat();
- if (mStencilbufferType == GL_RENDERBUFFER)
- {
- if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat()))
+ // texture stencil attachments come along as part
+ // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
+ // TODO(geofflang): use context's extensions
+ if (!mRenderer->getRendererExtensions().depthTextures)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- }
- else if (IsInternalTextureTarget(mStencilbufferType))
- {
- GLint internalformat = stencilbuffer->getInternalFormat();
- // texture stencil attachments come along as part
- // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
- if (!mRenderer->getDepthTextureSupport())
+ if (!formatCaps.renderable)
{
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ return GL_FRAMEBUFFER_UNSUPPORTED;
}
- if (!gl::IsStencilTexture(internalformat))
+ if (gl::GetStencilBits(internalformat) == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
else
{
- UNREACHABLE();
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ if (!formatCaps.renderable || gl::GetStencilBits(internalformat) == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
}
if (missingAttachment)
{
- width = stencilbuffer->getWidth();
- height = stencilbuffer->getHeight();
- samples = stencilbuffer->getSamples();
+ width = mStencilbuffer->getWidth();
+ height = mStencilbuffer->getHeight();
+ samples = mStencilbuffer->getSamples();
missingAttachment = false;
}
- else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
+ else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
{
return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
}
- else if (samples != stencilbuffer->getSamples())
+ else if (samples != mStencilbuffer->getSamples())
{
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
}
@@ -544,7 +548,7 @@ GLenum Framebuffer::completeness() const
// 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 (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
@@ -559,17 +563,17 @@ GLenum Framebuffer::completeness() const
}
DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
- : Framebuffer(renderer)
+ : Framebuffer(renderer, 0)
{
- mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer));
+ Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
+ mColorbuffers[0] = new RenderbufferAttachment(colorRenderbuffer);
- Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil);
- mDepthbufferPointer.set(depthStencilRenderbuffer);
- mStencilbufferPointer.set(depthStencilRenderbuffer);
+ Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
- mColorbufferTypes[0] = GL_RENDERBUFFER;
- mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
- mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
+ // Make a new attachment objects to ensure we do not double-delete
+ // See angle issue 686
+ mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL);
+ mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL);
mDrawBufferStates[0] = GL_BACK;
mReadBufferState = GL_BACK;
@@ -583,9 +587,9 @@ int Framebuffer::getSamples() const
// in this case return the first nonzero sample size
for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
{
- if (mColorbufferTypes[colorAttachment] != GL_NONE)
+ if (mColorbuffers[colorAttachment])
{
- return getColorbuffer(colorAttachment)->getSamples();
+ return mColorbuffers[colorAttachment]->getSamples();
}
}
}
@@ -593,6 +597,15 @@ int Framebuffer::getSamples() const
return 0;
}
+bool Framebuffer::hasValidDepthStencil() const
+{
+ // A valid depth-stencil attachment has the same resource bound to both the
+ // depth and stencil attachment points.
+ return (mDepthbuffer && mStencilbuffer &&
+ mDepthbuffer->type() == mStencilbuffer->type() &&
+ mDepthbuffer->id() == mStencilbuffer->id());
+}
+
GLenum DefaultFramebuffer::completeness() const
{
// The default framebuffer *must* always be complete, though it may not be
@@ -600,4 +613,22 @@ GLenum DefaultFramebuffer::completeness() const
return GL_FRAMEBUFFER_COMPLETE;
}
+FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
+{
+ switch (attachment)
+ {
+ case GL_BACK:
+ return getColorbuffer(0);
+ case GL_DEPTH:
+ return getDepthbuffer();
+ case GL_STENCIL:
+ return getStencilbuffer();
+ case GL_DEPTH_STENCIL:
+ return getDepthStencilBuffer();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
}