summaryrefslogtreecommitdiff
path: root/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp')
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp256
1 files changed, 166 insertions, 90 deletions
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
index 15f23d47334..805f923dc27 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -10,13 +10,14 @@
#include "common/bitset_utils.h"
#include "common/debug.h"
-#include "libANGLE/ContextState.h"
+#include "libANGLE/Context.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/State.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/gl/BlitGL.h"
+#include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/RenderbufferGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
@@ -44,7 +45,8 @@ FramebufferGL::FramebufferGL(const FramebufferState &state,
mWorkarounds(workarounds),
mBlitter(blitter),
mFramebufferID(0),
- mIsDefault(isDefault)
+ mIsDefault(isDefault),
+ mAppliedEnabledDrawBuffers(1)
{
if (!mIsDefault)
{
@@ -64,7 +66,8 @@ FramebufferGL::FramebufferGL(GLuint id,
mWorkarounds(workarounds),
mBlitter(blitter),
mFramebufferID(id),
- mIsDefault(true)
+ mIsDefault(true),
+ mAppliedEnabledDrawBuffers(1)
{
}
@@ -130,13 +133,13 @@ static void BindFramebufferAttachment(const FunctionsGL *functions,
}
}
-Error FramebufferGL::discard(size_t count, const GLenum *attachments)
+Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
{
// glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
- return invalidate(count, attachments);
+ return invalidate(context, count, attachments);
}
-Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
+Error FramebufferGL::invalidate(const gl::Context *context, size_t count, const GLenum *attachments)
{
const GLenum *finalAttachmentsPtr = attachments;
@@ -163,7 +166,8 @@ Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
return gl::NoError();
}
-Error FramebufferGL::invalidateSub(size_t count,
+Error FramebufferGL::invalidateSub(const gl::Context *context,
+ size_t count,
const GLenum *attachments,
const gl::Rectangle &area)
{
@@ -186,19 +190,19 @@ Error FramebufferGL::invalidateSub(size_t count,
area.height);
}
- return NoError();
+ return gl::NoError();
}
-Error FramebufferGL::clear(ContextImpl *context, GLbitfield mask)
+Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
{
syncClearState(context, mask);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clear(mask);
- return NoError();
+ return gl::NoError();
}
-Error FramebufferGL::clearBufferfv(ContextImpl *context,
+Error FramebufferGL::clearBufferfv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLfloat *values)
@@ -207,10 +211,10 @@ Error FramebufferGL::clearBufferfv(ContextImpl *context,
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clearBufferfv(buffer, drawbuffer, values);
- return NoError();
+ return gl::NoError();
}
-Error FramebufferGL::clearBufferuiv(ContextImpl *context,
+Error FramebufferGL::clearBufferuiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLuint *values)
@@ -219,10 +223,10 @@ Error FramebufferGL::clearBufferuiv(ContextImpl *context,
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clearBufferuiv(buffer, drawbuffer, values);
- return NoError();
+ return gl::NoError();
}
-Error FramebufferGL::clearBufferiv(ContextImpl *context,
+Error FramebufferGL::clearBufferiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLint *values)
@@ -231,10 +235,10 @@ Error FramebufferGL::clearBufferiv(ContextImpl *context,
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clearBufferiv(buffer, drawbuffer, values);
- return NoError();
+ return gl::NoError();
}
-Error FramebufferGL::clearBufferfi(ContextImpl *context,
+Error FramebufferGL::clearBufferfi(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
GLfloat depth,
@@ -244,33 +248,41 @@ Error FramebufferGL::clearBufferfi(ContextImpl *context,
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
- return NoError();
+ return gl::NoError();
}
-GLenum FramebufferGL::getImplementationColorReadFormat() const
+GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
{
const auto *readAttachment = mState.getReadAttachment();
const Format &format = readAttachment->getFormat();
return format.info->getReadPixelsFormat();
}
-GLenum FramebufferGL::getImplementationColorReadType() const
+GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
{
const auto *readAttachment = mState.getReadAttachment();
const Format &format = readAttachment->getFormat();
return format.info->getReadPixelsType();
}
-Error FramebufferGL::readPixels(ContextImpl *context,
- const gl::Rectangle &area,
+Error FramebufferGL::readPixels(const gl::Context *context,
+ const gl::Rectangle &origArea,
GLenum format,
GLenum type,
- void *pixels) const
+ void *ptrOrOffset) const
{
- // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
- // binding
- const PixelPackState &packState = context->getGLState().getPackState();
- mStateManager->setPixelPackState(packState);
+ // Clip read area to framebuffer.
+ const gl::Extents fbSize = getState().getReadAttachment()->getSize();
+ const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
+ gl::Rectangle area;
+ if (!ClipRectangle(origArea, fbRect, &area))
+ {
+ // nothing to read
+ return gl::NoError();
+ }
+
+ PixelPackState packState;
+ packState.copyFrom(context, context->getGLState().getPackState());
nativegl::ReadPixelsFormat readPixelsFormat =
nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
@@ -279,33 +291,67 @@ Error FramebufferGL::readPixels(ContextImpl *context,
mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
- if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
- packState.rowLength != 0 && packState.rowLength < area.width)
+ bool useOverlappingRowsWorkaround = mWorkarounds.packOverlappingRowsSeparatelyPackBuffer &&
+ packState.pixelBuffer.get() && packState.rowLength != 0 &&
+ packState.rowLength < area.width;
+
+ GLubyte *pixels = reinterpret_cast<GLubyte *>(ptrOrOffset);
+ int leftClip = area.x - origArea.x;
+ int topClip = area.y - origArea.y;
+ if (leftClip || topClip)
{
- return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
+ // Adjust destination to match portion clipped off left and/or top.
+ const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
+
+ GLuint rowBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeRowPitch(readType, origArea.width, packState.alignment,
+ packState.rowLength),
+ rowBytes);
+ pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
}
- if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
+ if (packState.rowLength == 0 && area.width != origArea.width)
{
- gl::Extents size(area.width, area.height, 1);
+ // No rowLength was specified so it will derive from read width, but clipping changed the
+ // read width. Use the original width so we fill the user's buffer as they intended.
+ packState.rowLength = origArea.width;
+ }
- bool apply;
- ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
- false, pixels),
- apply);
+ // We want to use rowLength, but that might not be supported.
+ bool cannotSetDesiredRowLength =
+ packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
- if (apply)
+ gl::Error retVal = gl::NoError();
+ if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
+ {
+ retVal = readPixelsRowByRow(context, area, readFormat, readType, packState, pixels);
+ }
+ else
+ {
+ gl::ErrorOrResult<bool> useLastRowPaddingWorkaround = false;
+ if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
{
- return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
+ useLastRowPaddingWorkaround =
+ ShouldApplyLastRowPaddingWorkaround(gl::Extents(area.width, area.height, 1),
+ packState, readFormat, readType, false, pixels);
}
- }
- mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels);
+ if (useLastRowPaddingWorkaround.isError())
+ {
+ retVal = useLastRowPaddingWorkaround.getError();
+ }
+ else
+ {
+ retVal = readPixelsAllAtOnce(context, area, readFormat, readType, packState, pixels,
+ useLastRowPaddingWorkaround.getResult());
+ }
+ }
- return gl::NoError();
+ packState.pixelBuffer.set(context, nullptr);
+ return retVal;
}
-Error FramebufferGL::blit(ContextImpl *context,
+Error FramebufferGL::blit(const gl::Context *context,
const gl::Rectangle &sourceArea,
const gl::Rectangle &destArea,
GLbitfield mask,
@@ -367,7 +413,7 @@ Error FramebufferGL::blit(ContextImpl *context,
}
// Enable FRAMEBUFFER_SRGB if needed
- mStateManager->setFramebufferSRGBEnabledForFramebuffer(context->getContextState(), true, this);
+ mStateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
GLenum blitMask = mask;
if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
@@ -411,7 +457,7 @@ bool FramebufferGL::checkStatus() const
return (status == GL_FRAMEBUFFER_COMPLETE);
}
-void FramebufferGL::syncState(ContextImpl *contextImpl, const Framebuffer::DirtyBits &dirtyBits)
+void FramebufferGL::syncState(const gl::Context *context, const Framebuffer::DirtyBits &dirtyBits)
{
// Don't need to sync state for the default FBO.
if (mIsDefault)
@@ -438,6 +484,7 @@ void FramebufferGL::syncState(ContextImpl *contextImpl, const Framebuffer::Dirty
const auto &drawBuffers = mState.getDrawBufferStates();
mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
drawBuffers.data());
+ mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
break;
}
case Framebuffer::DIRTY_BIT_READ_BUFFER:
@@ -485,7 +532,29 @@ bool FramebufferGL::isDefault() const
return mIsDefault;
}
-void FramebufferGL::syncClearState(ContextImpl *context, GLbitfield mask)
+void FramebufferGL::maskOutInactiveOutputDrawBuffers(DrawBufferMask maxSet)
+{
+ auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
+ if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
+ {
+ mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
+
+ const auto &stateDrawBuffers = mState.getDrawBufferStates();
+ GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
+ ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
+
+ GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
+ {
+ drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
+ }
+
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctions->drawBuffers(drawBufferCount, drawBuffers);
+ }
+}
+
+void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
{
if (mFunctions->standard == STANDARD_GL_DESKTOP)
{
@@ -502,16 +571,18 @@ void FramebufferGL::syncClearState(ContextImpl *context, GLbitfield mask)
}
}
- mStateManager->setFramebufferSRGBEnabled(context->getContextState(), hasSRGBAttachment);
+ mStateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
}
else
{
- mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
+ mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
}
}
}
-void FramebufferGL::syncClearBufferState(ContextImpl *context, GLenum buffer, GLint drawBuffer)
+void FramebufferGL::syncClearBufferState(const gl::Context *context,
+ GLenum buffer,
+ GLint drawBuffer)
{
if (mFunctions->standard == STANDARD_GL_DESKTOP)
{
@@ -534,13 +605,13 @@ void FramebufferGL::syncClearBufferState(ContextImpl *context, GLenum buffer, GL
if (attachment != nullptr)
{
- mStateManager->setFramebufferSRGBEnabled(context->getContextState(),
+ mStateManager->setFramebufferSRGBEnabled(context,
attachment->getColorEncoding() == GL_SRGB);
}
}
else
{
- mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
+ mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
}
}
}
@@ -582,68 +653,73 @@ bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
return true;
}
-gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
- GLenum format,
- GLenum type,
- const gl::PixelPackState &pack,
- void *pixels) const
+gl::Error FramebufferGL::readPixelsRowByRow(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelPackState &pack,
+ GLubyte *pixels) const
{
- intptr_t offset = reinterpret_cast<intptr_t>(pixels);
const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
- GLuint rowBytes = 0;
+
+ GLuint rowBytes = 0;
ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
rowBytes);
GLuint skipBytes = 0;
ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
gl::PixelPackState directPack;
- directPack.pixelBuffer = pack.pixelBuffer;
+ directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
directPack.alignment = 1;
mStateManager->setPixelPackState(directPack);
- directPack.pixelBuffer.set(nullptr);
+ directPack.pixelBuffer.set(context, nullptr);
- offset += skipBytes;
- for (GLint row = 0; row < area.height; ++row)
+ pixels += skipBytes;
+ for (GLint y = area.y; y < area.y + area.height; ++y)
{
- mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
- reinterpret_cast<void *>(offset));
- offset += row * rowBytes;
+ mFunctions->readPixels(area.x, y, area.width, 1, format, type, pixels);
+ pixels += rowBytes;
}
return gl::NoError();
}
-gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
- GLenum format,
- GLenum type,
- const gl::PixelPackState &pack,
- void *pixels) const
+gl::Error FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelPackState &pack,
+ GLubyte *pixels,
+ bool readLastRowSeparately) const
{
- const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
- GLuint rowBytes = 0;
- ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
- rowBytes);
- GLuint skipBytes = 0;
- ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
-
- // Get all by the last row
- if (area.height > 1)
+ GLint height = area.height - readLastRowSeparately;
+ if (height > 0)
{
- mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
+ mStateManager->setPixelPackState(pack);
+ mFunctions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
}
- // Get the last row manually
- gl::PixelPackState directPack;
- directPack.pixelBuffer = pack.pixelBuffer;
- directPack.alignment = 1;
- mStateManager->setPixelPackState(directPack);
- directPack.pixelBuffer.set(nullptr);
-
- intptr_t lastRowOffset =
- reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
- mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
- reinterpret_cast<void *>(lastRowOffset));
+ if (readLastRowSeparately)
+ {
+ const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
+
+ GLuint rowBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
+ rowBytes);
+ GLuint skipBytes = 0;
+ ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
+
+ gl::PixelPackState directPack;
+ directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
+ directPack.alignment = 1;
+ mStateManager->setPixelPackState(directPack);
+ directPack.pixelBuffer.set(context, nullptr);
+
+ pixels += skipBytes + (area.height - 1) * rowBytes;
+ mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
+ pixels);
+ }
return gl::NoError();
}