Commit b885e571 by Jamie Madill

Implement ReadBuffer functionality.

This enables ReadPixels from non-0 FBO attachments. Tested with: dEQP-GLES3.functional.negative_api.buffer.read_buffer (fails due to a possible error in dEQP) dEQP-GLES3.functional.shaders.fragdata.draw_buffers (passes) BUG=angle:903 Change-Id: Ib095e1d50b8fbbc6f197de25f19ec0993309145a Reviewed-on: https://chromium-review.googlesource.com/244841Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org>
parent b4b53c5c
......@@ -132,14 +132,15 @@ FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
FramebufferAttachment *Framebuffer::getReadColorbuffer() const
{
// Will require more logic if glReadBuffers is supported
return mColorbuffers[0];
size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
ASSERT(readIndex < IMPLEMENTATION_MAX_DRAW_BUFFERS);
return mColorbuffers[readIndex];
}
GLenum Framebuffer::getReadColorbufferType() const
{
// Will require more logic if glReadBuffers is supported
return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
FramebufferAttachment *readAttachment = getReadColorbuffer();
return (readAttachment ? readAttachment->type() : GL_NONE);
}
FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
......@@ -204,6 +205,9 @@ GLenum Framebuffer::getReadBufferState() const
void Framebuffer::setReadBuffer(GLenum buffer)
{
ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
(buffer >= GL_COLOR_ATTACHMENT0 &&
(buffer - GL_COLOR_ATTACHMENT0) < IMPLEMENTATION_MAX_DRAW_BUFFERS));
mReadBufferState = buffer;
mImpl->setReadBuffer(buffer);
}
......
......@@ -207,18 +207,25 @@ gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, G
return clear(state, clearParams);
}
const gl::FramebufferAttachment *FramebufferD3D::getReadAttachment() const
{
ASSERT(mReadBuffer == GL_BACK || (mReadBuffer >= GL_COLOR_ATTACHMENT0 && mReadBuffer <= GL_COLOR_ATTACHMENT15));
size_t readIndex = (mReadBuffer == GL_BACK ? 0 : static_cast<size_t>(mReadBuffer - GL_COLOR_ATTACHMENT0));
ASSERT(readIndex < mColorBuffers.size());
return mColorBuffers[readIndex];
}
GLenum FramebufferD3D::getImplementationColorReadFormat() const
{
// Will require more logic if glReadBuffers is supported
ASSERT(mReadBuffer == GL_COLOR_ATTACHMENT0 || mReadBuffer == GL_BACK);
const gl::FramebufferAttachment *readAttachment = getReadAttachment();
if (mColorBuffers[0] == nullptr)
if (readAttachment == nullptr)
{
return GL_NONE;
}
RenderTargetD3D *attachmentRenderTarget = NULL;
gl::Error error = GetAttachmentRenderTarget(mColorBuffers[0], &attachmentRenderTarget);
gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
if (error.isError())
{
return GL_NONE;
......@@ -232,16 +239,15 @@ GLenum FramebufferD3D::getImplementationColorReadFormat() const
GLenum FramebufferD3D::getImplementationColorReadType() const
{
// Will require more logic if glReadBuffers is supported
ASSERT(mReadBuffer == GL_COLOR_ATTACHMENT0 || mReadBuffer == GL_BACK);
const gl::FramebufferAttachment *readAttachment = getReadAttachment();
if (mColorBuffers[0] == nullptr)
if (readAttachment == nullptr)
{
return GL_NONE;
}
RenderTargetD3D *attachmentRenderTarget = NULL;
gl::Error error = GetAttachmentRenderTarget(mColorBuffers[0], &attachmentRenderTarget);
gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
if (error.isError())
{
return GL_NONE;
......
......@@ -78,6 +78,7 @@ class FramebufferD3D : public FramebufferImpl
GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override;
GLenum checkStatus() const override;
const gl::FramebufferAttachment *getReadAttachment() const;
protected:
std::vector<const gl::FramebufferAttachment*> mColorBuffers;
......
......@@ -108,7 +108,7 @@ gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GL
ID3D11Texture2D *colorBufferTexture = NULL;
unsigned int subresourceIndex = 0;
const gl::FramebufferAttachment *colorbuffer = mColorBuffers[0];
const gl::FramebufferAttachment *colorbuffer = getReadAttachment();
ASSERT(colorbuffer);
gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture);
......
......@@ -1228,4 +1228,55 @@ bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLu
return ValidateGetUniformBase(context, program, location);
}
bool ValidateReadBuffer(Context *context, GLenum src)
{
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
Framebuffer *readFBO = context->getState().getReadFramebuffer();
if (readFBO == nullptr)
{
context->recordError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
return false;
}
if (src == GL_NONE)
{
return true;
}
if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT15))
{
context->recordError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
return false;
}
if (readFBO->id() == 0)
{
if (src != GL_BACK)
{
const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg));
return false;
}
}
else
{
GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
if (drawBuffer >= context->getCaps().maxDrawBuffers)
{
const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg));
return false;
}
}
return true;
}
}
......@@ -42,6 +42,8 @@ bool ValidateClearBuffer(Context *context);
bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params);
bool ValidateReadBuffer(Context *context, GLenum mode);
}
#endif // LIBANGLE_VALIDATION_ES3_H_
......@@ -35,14 +35,13 @@ void GL_APIENTRY ReadBuffer(GLenum mode)
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientVersion() < 3)
if (!ValidateReadBuffer(context, mode))
{
context->recordError(Error(GL_INVALID_OPERATION));
return;
}
// glReadBuffer
UNIMPLEMENTED();
Framebuffer *readFBO = context->getState().getReadFramebuffer();
readFBO->setReadBuffer(mode);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment