Factor code between PixelUnpackState and PixelPackState
BUG=angleproject:1512
Change-Id: I4c60472d216bfc5198e635d70fd197a5738dde98
Reviewed-on: https://chromium-review.googlesource.com/390133
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/angletypes.h b/src/libANGLE/angletypes.h
index e6923c8..0c5c7ea 100644
--- a/src/libANGLE/angletypes.h
+++ b/src/libANGLE/angletypes.h
@@ -197,59 +197,39 @@
bool operator==(const SamplerState &a, const SamplerState &b);
bool operator!=(const SamplerState &a, const SamplerState &b);
-struct PixelUnpackState
+struct PixelStoreStateBase
{
BindingPointer<Buffer> pixelBuffer;
- GLint alignment;
- GLint rowLength;
- GLint skipRows;
- GLint skipPixels;
- GLint imageHeight;
- GLint skipImages;
-
- PixelUnpackState()
- : alignment(4),
- rowLength(0),
- skipRows(0),
- skipPixels(0),
- imageHeight(0),
- skipImages(0)
- {}
-
- PixelUnpackState(GLint alignmentIn, GLint rowLengthIn)
- : alignment(alignmentIn),
- rowLength(rowLengthIn),
- skipRows(0),
- skipPixels(0),
- imageHeight(0),
- skipImages(0)
- {}
+ GLint alignment = 4;
+ GLint rowLength = 0;
+ GLint skipRows = 0;
+ GLint skipPixels = 0;
+ GLint imageHeight = 0;
+ GLint skipImages = 0;
};
-struct PixelPackState
+struct PixelUnpackState : PixelStoreStateBase
{
- BindingPointer<Buffer> pixelBuffer;
- GLint alignment;
- bool reverseRowOrder;
- GLint rowLength;
- GLint skipRows;
- GLint skipPixels;
+ PixelUnpackState() {}
- PixelPackState()
- : alignment(4),
- reverseRowOrder(false),
- rowLength(0),
- skipRows(0),
- skipPixels(0)
- {}
+ PixelUnpackState(GLint alignmentIn, GLint rowLengthIn)
+ {
+ alignment = alignmentIn;
+ rowLength = rowLengthIn;
+ }
+};
- explicit PixelPackState(GLint alignmentIn, bool reverseRowOrderIn)
- : alignment(alignmentIn),
- reverseRowOrder(reverseRowOrderIn),
- rowLength(0),
- skipRows(0),
- skipPixels(0)
- {}
+struct PixelPackState : PixelStoreStateBase
+{
+ PixelPackState() {}
+
+ PixelPackState(GLint alignmentIn, bool reverseRowOrderIn)
+ : reverseRowOrder(reverseRowOrderIn)
+ {
+ alignment = alignmentIn;
+ }
+
+ bool reverseRowOrder = false;
};
// Used in Program and VertexArray.
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
index 4222d72..b9c5b4e 100644
--- a/src/libANGLE/formatutils.cpp
+++ b/src/libANGLE/formatutils.cpp
@@ -858,7 +858,7 @@
return components * typeInfo.bytes;
}
-gl::ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType,
+ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType,
GLsizei width,
GLint alignment,
GLint rowLength) const
@@ -867,7 +867,7 @@
if (compressed)
{
ASSERT(rowLength == 0);
- return computeCompressedImageSize(formatType, gl::Extents(width, 1, 1));
+ return computeCompressedImageSize(formatType, Extents(width, 1, 1));
}
CheckedNumeric<GLuint> checkedWidth(rowLength > 0 ? rowLength : width);
@@ -880,7 +880,7 @@
return aligned.ValueOrDie();
}
-gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
+ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
GLsizei width,
GLsizei height,
GLint alignment,
@@ -898,8 +898,8 @@
return depthPitch.ValueOrDie();
}
-gl::ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(GLenum formatType,
- const gl::Extents &size) const
+ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(GLenum formatType,
+ const Extents &size) const
{
CheckedNumeric<GLuint> checkedWidth(size.width);
CheckedNumeric<GLuint> checkedHeight(size.height);
@@ -915,21 +915,19 @@
return bytes.ValueOrDie();
}
-gl::ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch,
+ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch,
GLuint depthPitch,
- GLint skipImages,
- GLint skipRows,
- GLint skipPixels,
- bool applySkipImages) const
+ const PixelStoreStateBase &state,
+ bool is3D) const
{
CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
CheckedNumeric<GLuint> checkedDepthPitch(depthPitch);
- CheckedNumeric<GLuint> checkedSkipImages(static_cast<GLuint>(skipImages));
- CheckedNumeric<GLuint> checkedSkipRows(static_cast<GLuint>(skipRows));
- CheckedNumeric<GLuint> checkedSkipPixels(static_cast<GLuint>(skipPixels));
+ CheckedNumeric<GLuint> checkedSkipImages(static_cast<GLuint>(state.skipImages));
+ CheckedNumeric<GLuint> checkedSkipRows(static_cast<GLuint>(state.skipRows));
+ CheckedNumeric<GLuint> checkedSkipPixels(static_cast<GLuint>(state.skipPixels));
CheckedNumeric<GLuint> checkedPixelBytes(pixelBytes);
auto checkedSkipImagesBytes = checkedSkipImages * checkedDepthPitch;
- if (!applySkipImages)
+ if (!is3D)
{
checkedSkipImagesBytes = 0;
}
@@ -939,108 +937,46 @@
return skipBytes.ValueOrDie();
}
-gl::ErrorOrResult<GLuint> InternalFormat::computePackSize(GLenum formatType,
- const gl::Extents &size,
- const gl::PixelPackState &pack) const
+ErrorOrResult<GLuint> InternalFormat::computePackUnpackEndByte(
+ GLenum formatType,
+ const Extents &size,
+ const PixelStoreStateBase &state,
+ bool is3D) const
{
- ASSERT(!compressed);
-
- if (size.height == 0)
+ GLuint depthPitch = 0;
+ if (is3D)
{
- return 0;
+ ANGLE_TRY_RESULT(computeDepthPitch(formatType, size.width, size.height, state.alignment,
+ state.rowLength, state.imageHeight),
+ depthPitch);
}
- CheckedNumeric<GLuint> rowPitch;
- ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, pack.alignment, pack.rowLength),
+ GLuint rowPitch = 0;
+ ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, state.alignment, state.rowLength),
rowPitch);
- CheckedNumeric<GLuint> heightMinusOne = size.height - 1;
- CheckedNumeric<GLuint> bytes = computePixelBytes(formatType);
-
- CheckedNumeric<GLuint> totalSize = heightMinusOne * rowPitch;
- totalSize += size.width * bytes;
-
- ANGLE_TRY_CHECKED_MATH(totalSize);
-
- return totalSize.ValueOrDie();
-}
-
-gl::ErrorOrResult<GLuint> InternalFormat::computeUnpackSize(
- GLenum formatType,
- const gl::Extents &size,
- const gl::PixelUnpackState &unpack) const
-{
- // Compressed images do not use unpack parameters.
+ CheckedNumeric<GLuint> checkedCopyBytes = 0;
if (compressed)
{
- return computeCompressedImageSize(formatType, size);
+ ANGLE_TRY_RESULT(computeCompressedImageSize(formatType, size), checkedCopyBytes);
}
-
- if (size.height == 0 || size.depth == 0)
+ else if (size.height != 0 && (!is3D || size.depth != 0))
{
- return 0;
+ CheckedNumeric<GLuint> bytes = computePixelBytes(formatType);
+ checkedCopyBytes += size.width * bytes;
+
+ CheckedNumeric<GLuint> heightMinusOne = size.height - 1;
+ checkedCopyBytes += heightMinusOne * rowPitch;
+
+ if (is3D)
+ {
+ CheckedNumeric<GLuint> depthMinusOne = size.depth - 1;
+ checkedCopyBytes += depthMinusOne * depthPitch;
+ }
}
- CheckedNumeric<GLuint> rowPitch;
- CheckedNumeric<GLuint> depthPitch;
- ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, unpack.alignment, unpack.rowLength),
- rowPitch);
- ANGLE_TRY_RESULT(computeDepthPitch(formatType, size.width, size.height, unpack.alignment,
- unpack.rowLength, unpack.imageHeight),
- depthPitch);
-
- CheckedNumeric<GLuint> depthMinusOne = size.depth - 1;
- CheckedNumeric<GLuint> heightMinusOne = size.height - 1;
- CheckedNumeric<GLuint> bytes = computePixelBytes(formatType);
-
- CheckedNumeric<GLuint> totalSize = depthMinusOne * depthPitch;
- totalSize += heightMinusOne * rowPitch;
- totalSize += size.width * bytes;
-
- ANGLE_TRY_CHECKED_MATH(totalSize);
-
- return totalSize.ValueOrDie();
-}
-
-gl::ErrorOrResult<GLuint> InternalFormat::computePackEndByte(GLenum formatType,
- const gl::Extents &size,
- const gl::PixelPackState &pack) const
-{
- GLuint rowPitch;
- CheckedNumeric<GLuint> checkedSkipBytes;
- CheckedNumeric<GLuint> checkedCopyBytes;
-
- ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, pack.alignment, pack.rowLength),
- rowPitch);
- ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, 0, 0, pack.skipRows, pack.skipPixels, false),
- checkedSkipBytes);
- ANGLE_TRY_RESULT(computePackSize(formatType, size, pack), checkedCopyBytes);
-
- CheckedNumeric<GLuint> endByte = checkedCopyBytes + checkedSkipBytes;
-
- ANGLE_TRY_CHECKED_MATH(endByte);
- return endByte.ValueOrDie();
-}
-
-gl::ErrorOrResult<GLuint> InternalFormat::computeUnpackEndByte(GLenum formatType,
- const gl::Extents &size,
- const gl::PixelUnpackState &unpack,
- bool applySkipImages) const
-{
- GLuint rowPitch;
- GLuint depthPitch;
- CheckedNumeric<GLuint> checkedSkipBytes;
- CheckedNumeric<GLuint> checkedCopyBytes;
-
- ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, unpack.alignment, unpack.rowLength),
- rowPitch);
- ANGLE_TRY_RESULT(computeDepthPitch(formatType, size.width, size.height, unpack.alignment,
- unpack.rowLength, unpack.imageHeight),
- depthPitch);
- ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, depthPitch, unpack.skipImages, unpack.skipRows,
- unpack.skipPixels, applySkipImages),
- checkedSkipBytes);
- ANGLE_TRY_RESULT(computeUnpackSize(formatType, size, unpack), checkedCopyBytes);
+ CheckedNumeric<GLuint> checkedSkipBytes = 0;
+ ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, depthPitch, state, is3D), checkedSkipBytes);
CheckedNumeric<GLuint> endByte = checkedCopyBytes + checkedSkipBytes;
diff --git a/src/libANGLE/formatutils.h b/src/libANGLE/formatutils.h
index 0bd3ae6..6339038 100644
--- a/src/libANGLE/formatutils.h
+++ b/src/libANGLE/formatutils.h
@@ -49,39 +49,30 @@
GLuint computePixelBytes(GLenum formatType) const;
- gl::ErrorOrResult<GLuint> computeRowPitch(GLenum formatType,
- GLsizei width,
- GLint alignment,
- GLint rowLength) const;
- gl::ErrorOrResult<GLuint> computeDepthPitch(GLenum formatType,
- GLsizei width,
- GLsizei height,
- GLint alignment,
- GLint rowLength,
- GLint imageHeight) const;
- gl::ErrorOrResult<GLuint> computeCompressedImageSize(GLenum formatType,
- const gl::Extents &size) const;
- gl::ErrorOrResult<GLuint> computeSkipBytes(GLuint rowPitch,
- GLuint depthPitch,
- GLint skipImages,
- GLint skipRows,
- GLint skipPixels,
- bool applySkipImages) const;
+ ErrorOrResult<GLuint> computeRowPitch(GLenum formatType,
+ GLsizei width,
+ GLint alignment,
+ GLint rowLength) const;
+ ErrorOrResult<GLuint> computeDepthPitch(GLenum formatType,
+ GLsizei width,
+ GLsizei height,
+ GLint alignment,
+ GLint rowLength,
+ GLint imageHeight) const;
- gl::ErrorOrResult<GLuint> computePackSize(GLenum formatType,
- const gl::Extents &size,
- const gl::PixelPackState &pack) const;
- gl::ErrorOrResult<GLuint> computeUnpackSize(GLenum formatType,
- const gl::Extents &size,
- const gl::PixelUnpackState &unpack) const;
+ ErrorOrResult<GLuint> computeCompressedImageSize(GLenum formatType,
+ const Extents &size) const;
- gl::ErrorOrResult<GLuint> computePackEndByte(GLenum formatType,
- const gl::Extents &size,
- const gl::PixelPackState &pack) const;
- gl::ErrorOrResult<GLuint> computeUnpackEndByte(GLenum formatType,
- const gl::Extents &size,
- const gl::PixelUnpackState &unpack,
- bool applySkipImages) const;
+ ErrorOrResult<GLuint> computeSkipBytes(GLuint rowPitch,
+ GLuint depthPitch,
+ const PixelStoreStateBase &state,
+ bool is3D) const;
+
+ ErrorOrResult<GLuint> computePackUnpackEndByte(GLenum formatType,
+ const Extents &size,
+ const PixelStoreStateBase &state,
+ bool is3D) const;
+
bool isLUMA() const;
GLenum getReadPixelsFormat() const;
GLenum getReadPixelsType() const;
@@ -282,7 +273,7 @@
VERTEX_FORMAT_UINT210_INT,
};
-typedef std::vector<gl::VertexFormatType> InputLayout;
+typedef std::vector<VertexFormatType> InputLayout;
struct VertexFormat : angle::NonCopyable
{
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
index a272264..f6eef6f 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -242,13 +242,13 @@
GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
- GLuint outputPitch = 0;
+
+ GLuint outputPitch = 0;
ANGLE_TRY_RESULT(
sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength),
outputPitch);
GLuint outputSkipBytes = 0;
- ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, 0, packState.skipRows,
- packState.skipPixels, false),
+ ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false),
outputSkipBytes);
return readPixelsImpl(area, format, type, outputPitch, packState,
diff --git a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
index d27a8d5..bde01b8 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -262,8 +262,7 @@
inputDepthPitch);
GLuint inputSkipBytes = 0;
ANGLE_TRY_RESULT(
- formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack.skipImages,
- unpack.skipRows, unpack.skipPixels, applySkipImages),
+ formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
inputSkipBytes);
const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
index 8fe8fc3..6764dfe 100644
--- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -630,8 +630,7 @@
srcDepthPitch);
GLuint srcSkipBytes = 0;
ANGLE_TRY_RESULT(
- internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack.skipImages,
- unpack.skipRows, unpack.skipPixels, index.is3D()),
+ internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()),
srcSkipBytes);
const d3d11::Format &d3d11Format =
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index 24b5c31..4f8a4f0 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -22,6 +22,7 @@
#include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/WorkaroundsGL.h"
#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
#include "platform/Platform.h"
using namespace gl;
@@ -30,50 +31,6 @@
namespace rx
{
-namespace
-{
-gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Rectangle &area,
- const gl::PixelPackState &pack,
- GLenum format,
- GLenum type,
- const void *pixels)
-{
- if (pack.pixelBuffer.get() == nullptr)
- {
- return false;
- }
-
- // We are using an pack buffer, compute what the driver thinks is going to be the last
- // byte written. If it is past the end of the buffer, we will need to use the workaround
- // otherwise the driver will generate INVALID_OPERATION.
- CheckedNumeric<size_t> checkedEndByte;
- CheckedNumeric<size_t> pixelBytes;
- size_t rowPitch;
-
- gl::Extents size(area.width, area.height, 1);
- const gl::InternalFormat &glFormat =
- gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
- ANGLE_TRY_RESULT(glFormat.computePackEndByte(type, size, pack), checkedEndByte);
- ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
- rowPitch);
- pixelBytes = glFormat.computePixelBytes(type);
-
- checkedEndByte += reinterpret_cast<intptr_t>(pixels);
-
- // At this point checkedEndByte is the actual last byte written.
- // The driver adds an extra row padding (if any), mimic it.
- ANGLE_TRY_CHECKED_MATH(pixelBytes);
- if (pixelBytes.ValueOrDie() * size.width < rowPitch)
- {
- checkedEndByte += rowPitch - pixelBytes * size.width;
- }
-
- ANGLE_TRY_CHECKED_MATH(checkedEndByte);
-
- return checkedEndByte.ValueOrDie() > static_cast<size_t>(pack.pixelBuffer->getSize());
-}
-} // anonymous namespace
-
FramebufferGL::FramebufferGL(const FramebufferState &state,
const FunctionsGL *functions,
StateManagerGL *stateManager,
@@ -294,10 +251,12 @@
if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
{
+ gl::Extents size(area.width, area.height, 1);
+
bool apply;
- ANGLE_TRY_RESULT(
- ShouldApplyLastRowPaddingWorkaround(area, packState, readFormat, readType, pixels),
- apply);
+ ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
+ false, pixels),
+ apply);
if (apply)
{
@@ -476,9 +435,7 @@
ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
rowBytes);
GLuint skipBytes = 0;
- ANGLE_TRY_RESULT(
- glFormat.computeSkipBytes(rowBytes, 0, 0, pack.skipRows, pack.skipPixels, false),
- skipBytes);
+ ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
gl::PixelPackState directPack;
directPack.pixelBuffer = pack.pixelBuffer;
@@ -509,9 +466,7 @@
ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
rowBytes);
GLuint skipBytes = 0;
- ANGLE_TRY_RESULT(
- glFormat.computeSkipBytes(rowBytes, 0, 0, pack.skipRows, pack.skipPixels, false),
- skipBytes);
+ ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
// Get all by the last row
if (area.height > 1)
diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp
index 02f17a2..cfc19cb 100644
--- a/src/libANGLE/renderer/gl/TextureGL.cpp
+++ b/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -20,6 +20,7 @@
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/WorkaroundsGL.h"
#include "libANGLE/renderer/gl/formatutilsgl.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
using angle::CheckedNumeric;
@@ -89,50 +90,6 @@
GetLUMAWorkaroundInfo(originalFormatInfo, destinationFormat));
}
-gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Box &area,
- const gl::PixelUnpackState &unpack,
- GLenum format,
- GLenum type,
- bool useTexImage3D,
- const uint8_t *pixels)
-{
- if (unpack.pixelBuffer.get() == nullptr)
- {
- return false;
- }
-
- // We are using an unpack buffer, compute what the driver thinks is going to be the last
- // byte read. If it is past the end of the buffer, we will need to use the workaround
- // otherwise the driver will generate INVALID_OPERATION and not do the texture specification
- // and upload.
- CheckedNumeric<size_t> checkedEndByte;
- CheckedNumeric<size_t> pixelBytes;
- size_t rowPitch;
-
- gl::Extents size(area.width, area.height, area.depth);
- const gl::InternalFormat &glFormat =
- gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
- ANGLE_TRY_RESULT(glFormat.computeUnpackEndByte(type, size, unpack, useTexImage3D),
- checkedEndByte);
- ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
- rowPitch);
- pixelBytes = glFormat.computePixelBytes(type);
-
- checkedEndByte += reinterpret_cast<intptr_t>(pixels);
-
- // At this point checkedEndByte is the actual last byte read.
- // The driver adds an extra row padding (if any), mimic it.
- ANGLE_TRY_CHECKED_MATH(pixelBytes);
- if (pixelBytes.ValueOrDie() * size.width < rowPitch)
- {
- checkedEndByte += rowPitch - pixelBytes * size.width;
- }
-
- ANGLE_TRY_CHECKED_MATH(checkedEndByte);
-
- return checkedEndByte.ValueOrDie() > static_cast<size_t>(unpack.pixelBuffer->getSize());
-}
-
} // anonymous namespace
LUMAWorkaroundGL::LUMAWorkaroundGL() : LUMAWorkaroundGL(false, GL_NONE)
@@ -185,8 +142,14 @@
mTextureID = 0;
}
-gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels)
+gl::Error TextureGL::setImage(GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
{
if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpack.pixelBuffer.get() &&
unpack.rowLength != 0 && unpack.rowLength < size.width)
@@ -207,8 +170,7 @@
if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
{
bool apply;
- gl::Box area(0, 0, 0, size.width, size.height, size.depth);
- ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(area, unpack, format, type,
+ ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type,
UseTexImage3D(mState.mTarget), pixels),
apply);
@@ -223,6 +185,7 @@
return gl::NoError();
}
+ gl::Box area(0, 0, 0, size.width, size.height, size.depth);
return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels);
}
}
@@ -303,8 +266,10 @@
if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
{
+ gl::Extents size(area.width, area.height, area.depth);
+
bool apply;
- ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(area, unpack, format, type,
+ ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type,
UseTexImage3D(mState.mTarget), pixels),
apply);
@@ -359,8 +324,7 @@
imageBytes);
bool useTexImage3D = UseTexImage3D(mState.mTarget);
GLuint skipBytes = 0;
- ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack.skipImages,
- unpack.skipRows, unpack.skipPixels, useTexImage3D),
+ ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
skipBytes);
const uint8_t *pixelsWithSkip = pixels + skipBytes;
@@ -412,8 +376,7 @@
imageBytes);
bool useTexImage3D = UseTexImage3D(mState.mTarget);
GLuint skipBytes = 0;
- ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack.skipImages,
- unpack.skipRows, unpack.skipPixels, useTexImage3D),
+ ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
skipBytes);
gl::PixelUnpackState directUnpack;
diff --git a/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/libANGLE/renderer/gl/renderergl_utils.cpp
index 4fcc135..b9e6e53 100644
--- a/src/libANGLE/renderer/gl/renderergl_utils.cpp
+++ b/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -11,6 +11,8 @@
#include <limits>
+#include "common/mathutil.h"
+#include "libANGLE/Buffer.h"
#include "libANGLE/Caps.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
@@ -20,6 +22,8 @@
#include <algorithm>
#include <sstream>
+using angle::CheckedNumeric;
+
namespace rx
{
VendorID GetVendorID(const FunctionsGL *functions)
@@ -968,4 +972,45 @@
return nullptr;
}
}
+
+gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &size,
+ const gl::PixelStoreStateBase &state,
+ GLenum format,
+ GLenum type,
+ bool is3D,
+ const void *pixels)
+{
+ if (state.pixelBuffer.get() == nullptr)
+ {
+ return false;
+ }
+
+ // We are using an pack or unpack buffer, compute what the driver thinks is going to be the
+ // last byte read or written. If it is past the end of the buffer, we will need to use the
+ // workaround otherwise the driver will generate INVALID_OPERATION and not do the operation.
+ CheckedNumeric<size_t> checkedEndByte;
+ CheckedNumeric<size_t> pixelBytes;
+ size_t rowPitch;
+
+ const gl::InternalFormat &glFormat =
+ gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
+ ANGLE_TRY_RESULT(glFormat.computePackUnpackEndByte(type, size, state, is3D), checkedEndByte);
+ ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, size.width, state.alignment, state.rowLength),
+ rowPitch);
+ pixelBytes = glFormat.computePixelBytes(type);
+
+ checkedEndByte += reinterpret_cast<intptr_t>(pixels);
+
+ // At this point checkedEndByte is the actual last byte read.
+ // The driver adds an extra row padding (if any), mimic it.
+ ANGLE_TRY_CHECKED_MATH(pixelBytes);
+ if (pixelBytes.ValueOrDie() * size.width < rowPitch)
+ {
+ checkedEndByte += rowPitch - pixelBytes * size.width;
+ }
+
+ ANGLE_TRY_CHECKED_MATH(checkedEndByte);
+
+ return checkedEndByte.ValueOrDie() > static_cast<size_t>(state.pixelBuffer->getSize());
+}
}
diff --git a/src/libANGLE/renderer/gl/renderergl_utils.h b/src/libANGLE/renderer/gl/renderergl_utils.h
index 3b0cab2..bd5a425 100644
--- a/src/libANGLE/renderer/gl/renderergl_utils.h
+++ b/src/libANGLE/renderer/gl/renderergl_utils.h
@@ -11,6 +11,7 @@
#define LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
#include "libANGLE/renderer/gl/functionsgl_typedefs.h"
#include <string>
@@ -47,6 +48,13 @@
size_t offset,
size_t length,
GLbitfield access);
+
+gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &size,
+ const gl::PixelStoreStateBase &state,
+ GLenum format,
+ GLenum type,
+ bool is3D,
+ const void *pixels);
}
#endif // LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 2d3474a..7daa549 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -1179,7 +1179,7 @@
const gl::Extents size(width, height, 1);
const auto &pack = context->getGLState().getPackState();
- auto endByteOrErr = formatInfo.computePackEndByte(type, size, pack);
+ auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
if (endByteOrErr.isError())
{
context->handleError(endByteOrErr.getError());
@@ -1230,7 +1230,7 @@
const gl::Extents size(width, height, 1);
const auto &pack = context->getGLState().getPackState();
- auto endByteOrErr = formatInfo.computePackEndByte(type, size, pack);
+ auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
if (endByteOrErr.isError())
{
context->handleError(endByteOrErr.getError());
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index 782646f..b594965 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -487,7 +487,7 @@
const auto &unpack = context->getGLState().getUnpackState();
bool targetIs3D = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
- auto endByteOrErr = formatInfo.computeUnpackEndByte(type, size, unpack, targetIs3D);
+ auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
if (endByteOrErr.isError())
{
context->handleError(endByteOrErr.getError());