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 ...@@ -132,14 +132,15 @@ FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
FramebufferAttachment *Framebuffer::getReadColorbuffer() const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
{ {
// Will require more logic if glReadBuffers is supported size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
return mColorbuffers[0]; ASSERT(readIndex < IMPLEMENTATION_MAX_DRAW_BUFFERS);
return mColorbuffers[readIndex];
} }
GLenum Framebuffer::getReadColorbufferType() const GLenum Framebuffer::getReadColorbufferType() const
{ {
// Will require more logic if glReadBuffers is supported FramebufferAttachment *readAttachment = getReadColorbuffer();
return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE); return (readAttachment ? readAttachment->type() : GL_NONE);
} }
FramebufferAttachment *Framebuffer::getFirstColorbuffer() const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
...@@ -204,6 +205,9 @@ GLenum Framebuffer::getReadBufferState() const ...@@ -204,6 +205,9 @@ GLenum Framebuffer::getReadBufferState() const
void Framebuffer::setReadBuffer(GLenum buffer) 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; mReadBufferState = buffer;
mImpl->setReadBuffer(buffer); mImpl->setReadBuffer(buffer);
} }
......
...@@ -207,18 +207,25 @@ gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, G ...@@ -207,18 +207,25 @@ gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, G
return clear(state, clearParams); 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 GLenum FramebufferD3D::getImplementationColorReadFormat() const
{ {
// Will require more logic if glReadBuffers is supported const gl::FramebufferAttachment *readAttachment = getReadAttachment();
ASSERT(mReadBuffer == GL_COLOR_ATTACHMENT0 || mReadBuffer == GL_BACK);
if (mColorBuffers[0] == nullptr) if (readAttachment == nullptr)
{ {
return GL_NONE; return GL_NONE;
} }
RenderTargetD3D *attachmentRenderTarget = NULL; RenderTargetD3D *attachmentRenderTarget = NULL;
gl::Error error = GetAttachmentRenderTarget(mColorBuffers[0], &attachmentRenderTarget); gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
if (error.isError()) if (error.isError())
{ {
return GL_NONE; return GL_NONE;
...@@ -232,16 +239,15 @@ GLenum FramebufferD3D::getImplementationColorReadFormat() const ...@@ -232,16 +239,15 @@ GLenum FramebufferD3D::getImplementationColorReadFormat() const
GLenum FramebufferD3D::getImplementationColorReadType() const GLenum FramebufferD3D::getImplementationColorReadType() const
{ {
// Will require more logic if glReadBuffers is supported const gl::FramebufferAttachment *readAttachment = getReadAttachment();
ASSERT(mReadBuffer == GL_COLOR_ATTACHMENT0 || mReadBuffer == GL_BACK);
if (mColorBuffers[0] == nullptr) if (readAttachment == nullptr)
{ {
return GL_NONE; return GL_NONE;
} }
RenderTargetD3D *attachmentRenderTarget = NULL; RenderTargetD3D *attachmentRenderTarget = NULL;
gl::Error error = GetAttachmentRenderTarget(mColorBuffers[0], &attachmentRenderTarget); gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
if (error.isError()) if (error.isError())
{ {
return GL_NONE; return GL_NONE;
......
...@@ -78,6 +78,7 @@ class FramebufferD3D : public FramebufferImpl ...@@ -78,6 +78,7 @@ class FramebufferD3D : public FramebufferImpl
GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override; GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override;
GLenum checkStatus() const override; GLenum checkStatus() const override;
const gl::FramebufferAttachment *getReadAttachment() const;
protected: protected:
std::vector<const gl::FramebufferAttachment*> mColorBuffers; std::vector<const gl::FramebufferAttachment*> mColorBuffers;
......
...@@ -108,7 +108,7 @@ gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GL ...@@ -108,7 +108,7 @@ gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GL
ID3D11Texture2D *colorBufferTexture = NULL; ID3D11Texture2D *colorBufferTexture = NULL;
unsigned int subresourceIndex = 0; unsigned int subresourceIndex = 0;
const gl::FramebufferAttachment *colorbuffer = mColorBuffers[0]; const gl::FramebufferAttachment *colorbuffer = getReadAttachment();
ASSERT(colorbuffer); ASSERT(colorbuffer);
gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture); gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture);
......
...@@ -1228,4 +1228,55 @@ bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLu ...@@ -1228,4 +1228,55 @@ bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLu
return ValidateGetUniformBase(context, program, location); 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); ...@@ -42,6 +42,8 @@ bool ValidateClearBuffer(Context *context);
bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params); bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params);
bool ValidateReadBuffer(Context *context, GLenum mode);
} }
#endif // LIBANGLE_VALIDATION_ES3_H_ #endif // LIBANGLE_VALIDATION_ES3_H_
...@@ -35,14 +35,13 @@ void GL_APIENTRY ReadBuffer(GLenum mode) ...@@ -35,14 +35,13 @@ void GL_APIENTRY ReadBuffer(GLenum mode)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (context->getClientVersion() < 3) if (!ValidateReadBuffer(context, mode))
{ {
context->recordError(Error(GL_INVALID_OPERATION));
return; return;
} }
// glReadBuffer Framebuffer *readFBO = context->getState().getReadFramebuffer();
UNIMPLEMENTED(); 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