Multiple color attachments Adding multiple color attachments to Framebuffer objects. This cl allows setting multiple draw buffers, but there is currently no code exercising that path. These will connected properly to a shader's multiple outputs later. Change-Id: I41d4eadc4518d0b9c1468802c32e622df591e860 Reviewed-on: https://swiftshader-review.googlesource.com/2881 Tested-by: Alexis Hétu <sugoi@google.com> Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/Main/Config.hpp b/src/Main/Config.hpp index f94e447..6a0134b 100644 --- a/src/Main/Config.hpp +++ b/src/Main/Config.hpp
@@ -68,6 +68,7 @@ { OUTLINE_RESOLUTION = 4096, // Maximum vertical resolution of the render target MIPMAP_LEVELS = 14, + MAX_COLOR_ATTACHMENTS = 8, TEXTURE_IMAGE_UNITS = 16, VERTEX_TEXTURE_IMAGE_UNITS = 4, TOTAL_IMAGE_UNITS = TEXTURE_IMAGE_UNITS + VERTEX_TEXTURE_IMAGE_UNITS,
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp index c22386a..f62f583 100644 --- a/src/OpenGL/libGLESv2/Context.cpp +++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -152,6 +152,12 @@ bindRenderbuffer(0); bindTransformFeedback(0); + mState.readFramebufferColorIndex = 0; + for(int i = 0; i < MAX_COLOR_ATTACHMENTS; ++i) + { + mState.drawFramebufferColorIndices[i] = GL_NONE; + } + mState.currentProgram = 0; mState.packAlignment = 4; @@ -716,6 +722,24 @@ return mState.renderbuffer.name(); } +void Context::setReadFramebufferColorIndex(GLuint index) +{ + mState.readFramebufferColorIndex = index; +} + +void Context::setDrawFramebufferColorIndices(GLsizei n, const GLenum *bufs) +{ + for(int i = 0; i < n; ++i) + { + mState.drawFramebufferColorIndices[i] = ((bufs[i] == GL_BACK) || (bufs[i] == GL_NONE)) ? bufs[i] : i; + } +} + +GLuint Context::getReadFramebufferColorIndex() const +{ + return mState.readFramebufferColorIndex; +} + GLuint Context::getArrayBufferName() const { return mState.arrayBuffer.name(); @@ -1829,7 +1853,7 @@ case GL_ALPHA_BITS: { Framebuffer *framebuffer = getDrawFramebuffer(); - Renderbuffer *colorbuffer = framebuffer->getColorbuffer(); + Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); if(colorbuffer) { @@ -2467,7 +2491,7 @@ return error(GL_INVALID_FRAMEBUFFER_OPERATION, false); } - egl::Image *renderTarget = framebuffer->getRenderTarget(); + egl::Image *renderTarget = framebuffer->getRenderTarget(0); device->setRenderTarget(renderTarget); if(renderTarget) renderTarget->release(); @@ -2997,7 +3021,7 @@ } } - egl::Image *renderTarget = framebuffer->getRenderTarget(); + egl::Image *renderTarget = framebuffer->getRenderTarget(0); if(!renderTarget) { @@ -3849,10 +3873,10 @@ if(mask & GL_COLOR_BUFFER_BIT) { - const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D || - readFramebuffer->getColorbufferType() == GL_RENDERBUFFER; - const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D || - drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER; + const bool validReadType = readFramebuffer->getColorbufferType(getReadFramebufferColorIndex()) == GL_TEXTURE_2D || + readFramebuffer->getColorbufferType(getReadFramebufferColorIndex()) == GL_RENDERBUFFER; + const bool validDrawType = drawFramebuffer->getColorbufferType(0) == GL_TEXTURE_2D || + drawFramebuffer->getColorbufferType(0) == GL_RENDERBUFFER; if(!validReadType || !validDrawType) { return error(GL_INVALID_OPERATION); @@ -3921,8 +3945,8 @@ { if(blitRenderTarget) { - egl::Image *readRenderTarget = readFramebuffer->getRenderTarget(); - egl::Image *drawRenderTarget = drawFramebuffer->getRenderTarget(); + egl::Image *readRenderTarget = readFramebuffer->getReadRenderTarget(); + egl::Image *drawRenderTarget = drawFramebuffer->getRenderTarget(0); if(flipX) {
diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h index 575c99c..9b3a30d 100644 --- a/src/OpenGL/libGLESv2/Context.h +++ b/src/OpenGL/libGLESv2/Context.h
@@ -334,6 +334,8 @@ GLuint readFramebuffer; GLuint drawFramebuffer; + GLuint readFramebufferColorIndex; + GLuint drawFramebufferColorIndices[MAX_COLOR_ATTACHMENTS]; gl::BindingPointer<Renderbuffer> renderbuffer; GLuint currentProgram; GLuint vertexArray; @@ -427,6 +429,10 @@ GLuint getDrawFramebufferName() const; GLuint getRenderbufferName() const; + void setReadFramebufferColorIndex(GLuint index); + void setDrawFramebufferColorIndices(GLsizei n, const GLenum *bufs); + GLuint getReadFramebufferColorIndex() const; + GLuint getActiveQuery(GLenum target) const; GLuint getArrayBufferName() const;
diff --git a/src/OpenGL/libGLESv2/Framebuffer.cpp b/src/OpenGL/libGLESv2/Framebuffer.cpp index d59b715..e2cc168 100644 --- a/src/OpenGL/libGLESv2/Framebuffer.cpp +++ b/src/OpenGL/libGLESv2/Framebuffer.cpp
@@ -24,14 +24,20 @@ Framebuffer::Framebuffer() { - mColorbufferType = GL_NONE; + for(int i = 0; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i) + { + mColorbufferType[i] = GL_NONE; + } mDepthbufferType = GL_NONE; mStencilbufferType = GL_NONE; } Framebuffer::~Framebuffer() { - mColorbufferPointer = NULL; + for(int i = 0; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i) + { + mColorbufferPointer[i] = NULL; + } mDepthbufferPointer = NULL; mStencilbufferPointer = NULL; } @@ -61,10 +67,10 @@ return buffer; } -void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer) +void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index) { - mColorbufferType = (colorbuffer != 0) ? type : GL_NONE; - mColorbufferPointer = lookupRenderbuffer(type, colorbuffer); + mColorbufferType[index] = (colorbuffer != 0) ? type : GL_NONE; + mColorbufferPointer[index] = lookupRenderbuffer(type, colorbuffer); } void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer) @@ -81,10 +87,13 @@ void Framebuffer::detachTexture(GLuint texture) { - if(mColorbufferPointer.name() == texture && IsTextureTarget(mColorbufferType)) + for(int i = 0; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i) { - mColorbufferType = GL_NONE; - mColorbufferPointer = NULL; + if(mColorbufferPointer[i].name() == texture && IsTextureTarget(mColorbufferType[i])) + { + mColorbufferType[i] = GL_NONE; + mColorbufferPointer[i] = NULL; + } } if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType)) @@ -102,10 +111,13 @@ void Framebuffer::detachRenderbuffer(GLuint renderbuffer) { - if(mColorbufferPointer.name() == renderbuffer && mColorbufferType == GL_RENDERBUFFER) + for(int i = 0; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i) { - mColorbufferType = GL_NONE; - mColorbufferPointer = NULL; + if(mColorbufferPointer[i].name() == renderbuffer && mColorbufferType[i] == GL_RENDERBUFFER) + { + mColorbufferType[i] = GL_NONE; + mColorbufferPointer[i] = NULL; + } } if(mDepthbufferPointer.name() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER) @@ -123,9 +135,9 @@ // 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) { @@ -135,6 +147,12 @@ return NULL; } +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() @@ -154,9 +172,15 @@ return NULL; } -Renderbuffer *Framebuffer::getColorbuffer() +Renderbuffer *Framebuffer::getColorbuffer(GLuint index) { - return mColorbufferPointer; + return (index < MAX_COLOR_ATTACHMENTS) ? mColorbufferPointer[index] : (Renderbuffer*)NULL; +} + +Renderbuffer *Framebuffer::getReadColorbuffer() +{ + Context *context = getContext(); + return getColorbuffer(context->getReadFramebufferColorIndex()); } Renderbuffer *Framebuffer::getDepthbuffer() @@ -169,9 +193,9 @@ return mStencilbufferPointer; } -GLenum Framebuffer::getColorbufferType() +GLenum Framebuffer::getColorbufferType(GLuint index) { - return mColorbufferType; + return mColorbufferType[index]; } GLenum Framebuffer::getDepthbufferType() @@ -184,9 +208,9 @@ return mStencilbufferType; } -GLuint Framebuffer::getColorbufferName() +GLuint Framebuffer::getColorbufferName(GLuint index) { - return mColorbufferPointer.name(); + return mColorbufferPointer[index].name(); } GLuint Framebuffer::getDepthbufferName() @@ -229,53 +253,56 @@ height = -1; samples = -1; - if(mColorbufferType != GL_NONE) + for(int i = 0; i < IMPLEMENTATION_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(mColorbufferType == GL_RENDERBUFFER) - { - if(!es2::IsColorRenderable(colorbuffer->getFormat())) + if(!colorbuffer) { 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) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if(es2::IsDepthTexture(format) || es2::IsStencilTexture(format)) + if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - } - else - { - UNREACHABLE(); - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - width = colorbuffer->getWidth(); - height = colorbuffer->getHeight(); - samples = colorbuffer->getSamples(); + if(mColorbufferType[i] == GL_RENDERBUFFER) + { + if(!es2::IsColorRenderable(colorbuffer->getFormat())) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if(IsTextureTarget(mColorbufferType[i])) + { + GLenum format = colorbuffer->getFormat(); + + if(IsCompressed(format) || + format == GL_ALPHA || + format == GL_LUMINANCE || + format == GL_LUMINANCE_ALPHA) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if(es2::IsDepthTexture(format) || es2::IsStencilTexture(format)) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else + { + UNREACHABLE(); + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + width = colorbuffer->getWidth(); + height = colorbuffer->getHeight(); + samples = colorbuffer->getSamples(); + } } Renderbuffer *depthbuffer = NULL; @@ -401,7 +428,7 @@ GLenum Framebuffer::getImplementationColorReadFormat() { - Renderbuffer *colorbuffer = mColorbufferPointer; + Renderbuffer *colorbuffer = getReadColorbuffer(); if(colorbuffer) { @@ -426,7 +453,7 @@ GLenum Framebuffer::getImplementationColorReadType() { - Renderbuffer *colorbuffer = mColorbufferPointer; + Renderbuffer *colorbuffer = getReadColorbuffer(); if(colorbuffer) { @@ -450,13 +477,19 @@ DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) { - mColorbufferPointer = new Renderbuffer(0, colorbuffer); + mColorbufferPointer[0] = new Renderbuffer(0, colorbuffer); + mColorbufferType[0] = GL_RENDERBUFFER; + + for(int i = 1; i < IMPLEMENTATION_MAX_COLOR_ATTACHMENTS; ++i) + { + mColorbufferPointer[i] = nullptr; + mColorbufferType[i] = GL_NONE; + } Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil); mDepthbufferPointer = depthStencilRenderbuffer; mStencilbufferPointer = depthStencilRenderbuffer; - mColorbufferType = GL_RENDERBUFFER; mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE; mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE; }
diff --git a/src/OpenGL/libGLESv2/Framebuffer.h b/src/OpenGL/libGLESv2/Framebuffer.h index d581c79..b423e63 100644 --- a/src/OpenGL/libGLESv2/Framebuffer.h +++ b/src/OpenGL/libGLESv2/Framebuffer.h
@@ -35,25 +35,27 @@ virtual ~Framebuffer(); - void setColorbuffer(GLenum type, GLuint colorbuffer); + void setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index); void setDepthbuffer(GLenum type, GLuint depthbuffer); void setStencilbuffer(GLenum type, GLuint stencilbuffer); void detachTexture(GLuint texture); void detachRenderbuffer(GLuint renderbuffer); - egl::Image *getRenderTarget(); + egl::Image *getRenderTarget(GLuint index); + egl::Image *getReadRenderTarget(); egl::Image *getDepthStencil(); - Renderbuffer *getColorbuffer(); + Renderbuffer *getColorbuffer(GLuint index); + Renderbuffer *getReadColorbuffer(); Renderbuffer *getDepthbuffer(); Renderbuffer *getStencilbuffer(); - GLenum getColorbufferType(); + GLenum getColorbufferType(GLuint index); GLenum getDepthbufferType(); GLenum getStencilbufferType(); - GLuint getColorbufferName(); + GLuint getColorbufferName(GLuint index); GLuint getDepthbufferName(); GLuint getStencilbufferName(); @@ -66,8 +68,8 @@ GLenum getImplementationColorReadType(); protected: - GLenum mColorbufferType; - gl::BindingPointer<Renderbuffer> mColorbufferPointer; + GLenum mColorbufferType[MAX_COLOR_ATTACHMENTS]; + gl::BindingPointer<Renderbuffer> mColorbufferPointer[MAX_COLOR_ATTACHMENTS]; GLenum mDepthbufferType; gl::BindingPointer<Renderbuffer> mDepthbufferPointer;
diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp index d84fb86..2d909e6 100644 --- a/src/OpenGL/libGLESv2/Texture.cpp +++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -700,7 +700,7 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - egl::Image *renderTarget = source->getRenderTarget(); + egl::Image *renderTarget = source->getRenderTarget(0); if(!renderTarget) { @@ -722,8 +722,16 @@ if(width != 0 && height != 0) { + Renderbuffer* renderbuffer = source->getReadColorbuffer(); + + if(!renderbuffer) + { + ERR("Failed to retrieve the source colorbuffer."); + return; + } + sw::SliceRect sourceRect(x, y, x + width, y + height, 0); - sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); + sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); copy(renderTarget, sourceRect, format, 0, 0, 0, image[level]); } @@ -743,7 +751,7 @@ return error(GL_INVALID_VALUE); } - egl::Image *renderTarget = source->getRenderTarget(); + egl::Image *renderTarget = source->getRenderTarget(0); if(!renderTarget) { @@ -751,8 +759,16 @@ return error(GL_OUT_OF_MEMORY); } + Renderbuffer* renderbuffer = source->getReadColorbuffer(); + + if(!renderbuffer) + { + ERR("Failed to retrieve the source colorbuffer."); + return; + } + sw::SliceRect sourceRect(x, y, x + width, y + height, 0); - sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); + sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]); @@ -1211,7 +1227,7 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - egl::Image *renderTarget = source->getRenderTarget(); + egl::Image *renderTarget = source->getRenderTarget(0); if(!renderTarget) { @@ -1235,8 +1251,16 @@ if(width != 0 && height != 0) { + Renderbuffer* renderbuffer = source->getReadColorbuffer(); + + if(!renderbuffer) + { + ERR("Failed to retrieve the source colorbuffer."); + return; + } + sw::SliceRect sourceRect(x, y, x + width, y + height, 0); - sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); + sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); copy(renderTarget, sourceRect, format, 0, 0, 0, image[face][level]); } @@ -1270,7 +1294,7 @@ return error(GL_INVALID_VALUE); } - egl::Image *renderTarget = source->getRenderTarget(); + egl::Image *renderTarget = source->getRenderTarget(0); if(!renderTarget) { @@ -1278,8 +1302,16 @@ return error(GL_OUT_OF_MEMORY); } + Renderbuffer* renderbuffer = source->getReadColorbuffer(); + + if(!renderbuffer) + { + ERR("Failed to retrieve the source colorbuffer."); + return; + } + sw::SliceRect sourceRect(x, y, x + width, y + height, 0); - sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); + sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); copy(renderTarget, sourceRect, image[face][level]->getFormat(), xoffset, yoffset, zoffset, image[face][level]); @@ -1565,7 +1597,7 @@ void Texture3D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLint z, GLsizei width, GLsizei height, GLsizei depth, Framebuffer *source) { - egl::Image *renderTarget = source->getRenderTarget(); + egl::Image *renderTarget = source->getRenderTarget(0); if(!renderTarget) { @@ -1587,8 +1619,16 @@ if(width != 0 && height != 0 && depth != 0) { + Renderbuffer* renderbuffer = source->getReadColorbuffer(); + + if(!renderbuffer) + { + ERR("Failed to retrieve the source colorbuffer."); + return; + } + sw::SliceRect sourceRect(x, y, x + width, y + height, z); - sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); + sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); for(GLint sliceZ = 0; sliceZ < depth; ++sliceZ, ++sourceRect.slice) { copy(renderTarget, sourceRect, format, 0, 0, sliceZ, image[level]); @@ -1610,7 +1650,7 @@ return error(GL_INVALID_VALUE); } - egl::Image *renderTarget = source->getRenderTarget(); + egl::Image *renderTarget = source->getRenderTarget(0); if(!renderTarget) { @@ -1618,8 +1658,16 @@ return error(GL_OUT_OF_MEMORY); } + Renderbuffer* renderbuffer = source->getReadColorbuffer(); + + if(!renderbuffer) + { + ERR("Failed to retrieve the source colorbuffer."); + return; + } + sw::SliceRect sourceRect = {x, y, x + width, y + height, 0}; - sourceRect.clip(0, 0, source->getColorbuffer()->getWidth(), source->getColorbuffer()->getHeight()); + sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
diff --git a/src/OpenGL/libGLESv2/Texture.h b/src/OpenGL/libGLESv2/Texture.h index 3a4dd1d..81fdf92 100644 --- a/src/OpenGL/libGLESv2/Texture.h +++ b/src/OpenGL/libGLESv2/Texture.h
@@ -43,7 +43,7 @@ IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 1 << (MIPMAP_LEVELS - 1), IMPLEMENTATION_MAX_RENDERBUFFER_SIZE = OUTLINE_RESOLUTION, IMPLEMENTATION_MAX_SAMPLES = 4, - IMPLEMENTATION_MAX_COLOR_ATTACHMENTS = 8, + IMPLEMENTATION_MAX_COLOR_ATTACHMENTS = MAX_COLOR_ATTACHMENTS, IMPLEMENTATION_MAX_DRAW_BUFFERS = 8, IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS = 36,
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp index 8dfd4b4..61c82eb 100644 --- a/src/OpenGL/libGLESv2/libGLESv2.cpp +++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -1247,12 +1247,13 @@ return error(GL_INVALID_FRAMEBUFFER_OPERATION); } - if(context->getReadFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1) + es2::Renderbuffer *source = framebuffer->getReadColorbuffer(); + + if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1)) { return error(GL_INVALID_OPERATION); } - es2::Renderbuffer *source = framebuffer->getColorbuffer(); GLenum colorbufferFormat = source->getFormat(); if(!validateColorBufferFormat(internalformat, colorbufferFormat)) @@ -1328,12 +1329,13 @@ return error(GL_INVALID_FRAMEBUFFER_OPERATION); } - if(context->getReadFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1) + es2::Renderbuffer *source = framebuffer->getReadColorbuffer(); + + if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1)) { return error(GL_INVALID_OPERATION); } - es2::Renderbuffer *source = framebuffer->getColorbuffer(); GLenum colorbufferFormat = source->getFormat(); es2::Texture *texture = NULL; @@ -2188,10 +2190,36 @@ return error(GL_INVALID_OPERATION); } + egl::GLint clientVersion = context->getClientVersion(); + switch(attachment) { + case GL_COLOR_ATTACHMENT1: + case GL_COLOR_ATTACHMENT2: + case GL_COLOR_ATTACHMENT3: + case GL_COLOR_ATTACHMENT4: + case GL_COLOR_ATTACHMENT5: + case GL_COLOR_ATTACHMENT6: + case GL_COLOR_ATTACHMENT7: + case GL_COLOR_ATTACHMENT8: + case GL_COLOR_ATTACHMENT9: + case GL_COLOR_ATTACHMENT10: + case GL_COLOR_ATTACHMENT11: + case GL_COLOR_ATTACHMENT12: + case GL_COLOR_ATTACHMENT13: + case GL_COLOR_ATTACHMENT14: + case GL_COLOR_ATTACHMENT15: + if(clientVersion < 3) + { + return error(GL_INVALID_ENUM); + } + // fall through case GL_COLOR_ATTACHMENT0: - framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer); + if((attachment - GL_COLOR_ATTACHMENT0) >= es2::IMPLEMENTATION_MAX_COLOR_ATTACHMENTS) + { + return error(GL_INVALID_ENUM); + } + framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0); break; case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer); @@ -2294,9 +2322,37 @@ return error(GL_INVALID_OPERATION); } + egl::GLint clientVersion = context->getClientVersion(); + switch(attachment) { - case GL_COLOR_ATTACHMENT0: framebuffer->setColorbuffer(textarget, texture); break; + case GL_COLOR_ATTACHMENT1: + case GL_COLOR_ATTACHMENT2: + case GL_COLOR_ATTACHMENT3: + case GL_COLOR_ATTACHMENT4: + case GL_COLOR_ATTACHMENT5: + case GL_COLOR_ATTACHMENT6: + case GL_COLOR_ATTACHMENT7: + case GL_COLOR_ATTACHMENT8: + case GL_COLOR_ATTACHMENT9: + case GL_COLOR_ATTACHMENT10: + case GL_COLOR_ATTACHMENT11: + case GL_COLOR_ATTACHMENT12: + case GL_COLOR_ATTACHMENT13: + case GL_COLOR_ATTACHMENT14: + case GL_COLOR_ATTACHMENT15: + if(clientVersion < 3) + { + return error(GL_INVALID_ENUM); + } + // fall through + case GL_COLOR_ATTACHMENT0: + if((attachment - GL_COLOR_ATTACHMENT0) >= es2::IMPLEMENTATION_MAX_COLOR_ATTACHMENTS) + { + return error(GL_INVALID_ENUM); + } + framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0); + break; case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; } @@ -2874,13 +2930,39 @@ framebuffer = context->getDrawFramebuffer(); } + egl::GLint clientVersion = context->getClientVersion(); + GLenum attachmentType; GLuint attachmentHandle; switch(attachment) { + case GL_COLOR_ATTACHMENT1: + case GL_COLOR_ATTACHMENT2: + case GL_COLOR_ATTACHMENT3: + case GL_COLOR_ATTACHMENT4: + case GL_COLOR_ATTACHMENT5: + case GL_COLOR_ATTACHMENT6: + case GL_COLOR_ATTACHMENT7: + case GL_COLOR_ATTACHMENT8: + case GL_COLOR_ATTACHMENT9: + case GL_COLOR_ATTACHMENT10: + case GL_COLOR_ATTACHMENT11: + case GL_COLOR_ATTACHMENT12: + case GL_COLOR_ATTACHMENT13: + case GL_COLOR_ATTACHMENT14: + case GL_COLOR_ATTACHMENT15: + if(clientVersion < 3) + { + return error(GL_INVALID_ENUM); + } + // fall through case GL_COLOR_ATTACHMENT0: - attachmentType = framebuffer->getColorbufferType(); - attachmentHandle = framebuffer->getColorbufferName(); + if((attachment - GL_COLOR_ATTACHMENT0) >= es2::IMPLEMENTATION_MAX_COLOR_ATTACHMENTS) + { + return error(GL_INVALID_ENUM); + } + attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0); + attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0); break; case GL_DEPTH_ATTACHMENT: attachmentType = framebuffer->getDepthbufferType(); @@ -6681,12 +6763,13 @@ return error(GL_INVALID_FRAMEBUFFER_OPERATION); } - if(context->getReadFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1) + es2::Renderbuffer *source = framebuffer->getReadColorbuffer(); + + if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1)) { return error(GL_INVALID_OPERATION); } - es2::Renderbuffer *source = framebuffer->getColorbuffer(); GLenum colorbufferFormat = source->getFormat(); es2::Texture3D *texture = context->getTexture3D(); @@ -6909,9 +6992,37 @@ return error(GL_INVALID_OPERATION); } + egl::GLint clientVersion = context->getClientVersion(); + switch(attachment) { - case GL_COLOR_ATTACHMENT0: framebuffer->setColorbuffer(textarget, texture); break; + case GL_COLOR_ATTACHMENT1: + case GL_COLOR_ATTACHMENT2: + case GL_COLOR_ATTACHMENT3: + case GL_COLOR_ATTACHMENT4: + case GL_COLOR_ATTACHMENT5: + case GL_COLOR_ATTACHMENT6: + case GL_COLOR_ATTACHMENT7: + case GL_COLOR_ATTACHMENT8: + case GL_COLOR_ATTACHMENT9: + case GL_COLOR_ATTACHMENT10: + case GL_COLOR_ATTACHMENT11: + case GL_COLOR_ATTACHMENT12: + case GL_COLOR_ATTACHMENT13: + case GL_COLOR_ATTACHMENT14: + case GL_COLOR_ATTACHMENT15: + if(clientVersion < 3) + { + return error(GL_INVALID_ENUM); + } + // fall through + case GL_COLOR_ATTACHMENT0: + if((attachment - GL_COLOR_ATTACHMENT0) >= es2::IMPLEMENTATION_MAX_COLOR_ATTACHMENTS) + { + return error(GL_INVALID_ENUM); + } + framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0); + break; case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; }
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp index 11804eb..3381e2d 100644 --- a/src/OpenGL/libGLESv2/libGLESv3.cpp +++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -458,37 +458,55 @@ es2::Context *context = es2::getContext(); - switch(src) + if(context) { - case GL_BACK: - case GL_NONE: - break; - case GL_COLOR_ATTACHMENT0: - case GL_COLOR_ATTACHMENT1: - case GL_COLOR_ATTACHMENT2: - case GL_COLOR_ATTACHMENT3: - case GL_COLOR_ATTACHMENT4: - case GL_COLOR_ATTACHMENT5: - case GL_COLOR_ATTACHMENT6: - case GL_COLOR_ATTACHMENT7: - case GL_COLOR_ATTACHMENT8: - case GL_COLOR_ATTACHMENT9: - case GL_COLOR_ATTACHMENT10: - case GL_COLOR_ATTACHMENT11: - case GL_COLOR_ATTACHMENT12: - case GL_COLOR_ATTACHMENT13: - case GL_COLOR_ATTACHMENT14: - case GL_COLOR_ATTACHMENT15: - if((src - GL_COLOR_ATTACHMENT0) >= es2::IMPLEMENTATION_MAX_COLOR_ATTACHMENTS) - { - return error(GL_INVALID_ENUM); - } - break; - default: - error(GL_INVALID_ENUM); - } + GLuint readFramebufferName = context->getReadFramebufferName(); - UNIMPLEMENTED(); + switch(src) + { + case GL_BACK: + if(readFramebufferName != 0) + { + return error(GL_INVALID_OPERATION); + } + context->setReadFramebufferColorIndex(0); + break; + case GL_NONE: + context->setReadFramebufferColorIndex(GL_INVALID_INDEX); + break; + case GL_COLOR_ATTACHMENT0: + case GL_COLOR_ATTACHMENT1: + case GL_COLOR_ATTACHMENT2: + case GL_COLOR_ATTACHMENT3: + case GL_COLOR_ATTACHMENT4: + case GL_COLOR_ATTACHMENT5: + case GL_COLOR_ATTACHMENT6: + case GL_COLOR_ATTACHMENT7: + case GL_COLOR_ATTACHMENT8: + case GL_COLOR_ATTACHMENT9: + case GL_COLOR_ATTACHMENT10: + case GL_COLOR_ATTACHMENT11: + case GL_COLOR_ATTACHMENT12: + case GL_COLOR_ATTACHMENT13: + case GL_COLOR_ATTACHMENT14: + case GL_COLOR_ATTACHMENT15: + { + GLuint index = (src - GL_COLOR_ATTACHMENT0); + if(index >= es2::IMPLEMENTATION_MAX_COLOR_ATTACHMENTS) + { + return error(GL_INVALID_ENUM); + } + if(readFramebufferName == 0) + { + return error(GL_INVALID_OPERATION); + } + context->setReadFramebufferColorIndex(index); + } + break; + default: + error(GL_INVALID_ENUM); + } + } } GL_APICALL void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) @@ -666,12 +684,13 @@ return error(GL_INVALID_FRAMEBUFFER_OPERATION); } - if(context->getReadFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1) + es2::Renderbuffer *source = framebuffer->getReadColorbuffer(); + + if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1)) { return error(GL_INVALID_OPERATION); } - es2::Renderbuffer *source = framebuffer->getColorbuffer(); GLenum colorbufferFormat = source->getFormat(); es2::Texture3D *texture = context->getTexture3D(); @@ -1063,7 +1082,78 @@ { TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs); - UNIMPLEMENTED(); + if(n < 0 || n > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS) + { + return error(GL_INVALID_VALUE); + } + + if(n == 0) + { + return; + } + + es2::Context *context = es2::getContext(); + + if(context) + { + GLuint drawFramebufferName = context->getDrawFramebufferName(); + + if((drawFramebufferName == 0) && (n != 1)) + { + return error(GL_INVALID_OPERATION); + } + + for(int i = 0; i < n; ++i) + { + switch(bufs[i]) + { + case GL_BACK: + if(drawFramebufferName != 0) + { + return error(GL_INVALID_OPERATION); + } + break; + case GL_NONE: + break; + case GL_COLOR_ATTACHMENT0: + case GL_COLOR_ATTACHMENT1: + case GL_COLOR_ATTACHMENT2: + case GL_COLOR_ATTACHMENT3: + case GL_COLOR_ATTACHMENT4: + case GL_COLOR_ATTACHMENT5: + case GL_COLOR_ATTACHMENT6: + case GL_COLOR_ATTACHMENT7: + case GL_COLOR_ATTACHMENT8: + case GL_COLOR_ATTACHMENT9: + case GL_COLOR_ATTACHMENT10: + case GL_COLOR_ATTACHMENT11: + case GL_COLOR_ATTACHMENT12: + case GL_COLOR_ATTACHMENT13: + case GL_COLOR_ATTACHMENT14: + case GL_COLOR_ATTACHMENT15: + { + GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0); + if(index >= es2::IMPLEMENTATION_MAX_COLOR_ATTACHMENTS) + { + return error(GL_INVALID_ENUM); + } + if(index != i) + { + return error(GL_INVALID_OPERATION); + } + if(drawFramebufferName == 0) + { + return error(GL_INVALID_OPERATION); + } + } + break; + default: + return error(GL_INVALID_ENUM); + } + } + + context->setDrawFramebufferColorIndices(n, bufs); + } } GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)