Commit 886de369 by Corentin Wallez Committed by Commit Bot

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: 's avatarGeoff Lang <geofflang@chromium.org>
parent 6f0a0dca
...@@ -197,59 +197,39 @@ struct SamplerState ...@@ -197,59 +197,39 @@ struct SamplerState
bool operator==(const SamplerState &a, const SamplerState &b); bool operator==(const SamplerState &a, const SamplerState &b);
bool operator!=(const SamplerState &a, const SamplerState &b); bool operator!=(const SamplerState &a, const SamplerState &b);
struct PixelUnpackState struct PixelStoreStateBase
{ {
BindingPointer<Buffer> pixelBuffer; BindingPointer<Buffer> pixelBuffer;
GLint alignment; GLint alignment = 4;
GLint rowLength; GLint rowLength = 0;
GLint skipRows; GLint skipRows = 0;
GLint skipPixels; GLint skipPixels = 0;
GLint imageHeight; GLint imageHeight = 0;
GLint skipImages; GLint skipImages = 0;
};
PixelUnpackState()
: alignment(4), struct PixelUnpackState : PixelStoreStateBase
rowLength(0), {
skipRows(0), PixelUnpackState() {}
skipPixels(0),
imageHeight(0),
skipImages(0)
{}
PixelUnpackState(GLint alignmentIn, GLint rowLengthIn) PixelUnpackState(GLint alignmentIn, GLint rowLengthIn)
: alignment(alignmentIn), {
rowLength(rowLengthIn), alignment = alignmentIn;
skipRows(0), rowLength = rowLengthIn;
skipPixels(0), }
imageHeight(0),
skipImages(0)
{}
}; };
struct PixelPackState struct PixelPackState : PixelStoreStateBase
{ {
BindingPointer<Buffer> pixelBuffer; PixelPackState() {}
GLint alignment;
bool reverseRowOrder; PixelPackState(GLint alignmentIn, bool reverseRowOrderIn)
GLint rowLength; : reverseRowOrder(reverseRowOrderIn)
GLint skipRows; {
GLint skipPixels; alignment = alignmentIn;
}
PixelPackState()
: alignment(4), bool reverseRowOrder = false;
reverseRowOrder(false),
rowLength(0),
skipRows(0),
skipPixels(0)
{}
explicit PixelPackState(GLint alignmentIn, bool reverseRowOrderIn)
: alignment(alignmentIn),
reverseRowOrder(reverseRowOrderIn),
rowLength(0),
skipRows(0),
skipPixels(0)
{}
}; };
// Used in Program and VertexArray. // Used in Program and VertexArray.
......
...@@ -858,7 +858,7 @@ GLuint InternalFormat::computePixelBytes(GLenum formatType) const ...@@ -858,7 +858,7 @@ GLuint InternalFormat::computePixelBytes(GLenum formatType) const
return components * typeInfo.bytes; return components * typeInfo.bytes;
} }
gl::ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType, ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType,
GLsizei width, GLsizei width,
GLint alignment, GLint alignment,
GLint rowLength) const GLint rowLength) const
...@@ -867,7 +867,7 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType, ...@@ -867,7 +867,7 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType,
if (compressed) if (compressed)
{ {
ASSERT(rowLength == 0); 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); CheckedNumeric<GLuint> checkedWidth(rowLength > 0 ? rowLength : width);
...@@ -880,7 +880,7 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType, ...@@ -880,7 +880,7 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType,
return aligned.ValueOrDie(); return aligned.ValueOrDie();
} }
gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType, ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
GLsizei width, GLsizei width,
GLsizei height, GLsizei height,
GLint alignment, GLint alignment,
...@@ -898,8 +898,8 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType, ...@@ -898,8 +898,8 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
return depthPitch.ValueOrDie(); return depthPitch.ValueOrDie();
} }
gl::ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(GLenum formatType, ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(GLenum formatType,
const gl::Extents &size) const const Extents &size) const
{ {
CheckedNumeric<GLuint> checkedWidth(size.width); CheckedNumeric<GLuint> checkedWidth(size.width);
CheckedNumeric<GLuint> checkedHeight(size.height); CheckedNumeric<GLuint> checkedHeight(size.height);
...@@ -915,21 +915,19 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(GLenum form ...@@ -915,21 +915,19 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(GLenum form
return bytes.ValueOrDie(); return bytes.ValueOrDie();
} }
gl::ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch, ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch,
GLuint depthPitch, GLuint depthPitch,
GLint skipImages, const PixelStoreStateBase &state,
GLint skipRows, bool is3D) const
GLint skipPixels,
bool applySkipImages) const
{ {
CheckedNumeric<GLuint> checkedRowPitch(rowPitch); CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
CheckedNumeric<GLuint> checkedDepthPitch(depthPitch); CheckedNumeric<GLuint> checkedDepthPitch(depthPitch);
CheckedNumeric<GLuint> checkedSkipImages(static_cast<GLuint>(skipImages)); CheckedNumeric<GLuint> checkedSkipImages(static_cast<GLuint>(state.skipImages));
CheckedNumeric<GLuint> checkedSkipRows(static_cast<GLuint>(skipRows)); CheckedNumeric<GLuint> checkedSkipRows(static_cast<GLuint>(state.skipRows));
CheckedNumeric<GLuint> checkedSkipPixels(static_cast<GLuint>(skipPixels)); CheckedNumeric<GLuint> checkedSkipPixels(static_cast<GLuint>(state.skipPixels));
CheckedNumeric<GLuint> checkedPixelBytes(pixelBytes); CheckedNumeric<GLuint> checkedPixelBytes(pixelBytes);
auto checkedSkipImagesBytes = checkedSkipImages * checkedDepthPitch; auto checkedSkipImagesBytes = checkedSkipImages * checkedDepthPitch;
if (!applySkipImages) if (!is3D)
{ {
checkedSkipImagesBytes = 0; checkedSkipImagesBytes = 0;
} }
...@@ -939,108 +937,46 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch, ...@@ -939,108 +937,46 @@ gl::ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch,
return skipBytes.ValueOrDie(); return skipBytes.ValueOrDie();
} }
gl::ErrorOrResult<GLuint> InternalFormat::computePackSize(GLenum formatType, ErrorOrResult<GLuint> InternalFormat::computePackUnpackEndByte(
const gl::Extents &size, GLenum formatType,
const gl::PixelPackState &pack) const const Extents &size,
const PixelStoreStateBase &state,
bool is3D) const
{ {
ASSERT(!compressed); GLuint depthPitch = 0;
if (is3D)
if (size.height == 0)
{ {
return 0; ANGLE_TRY_RESULT(computeDepthPitch(formatType, size.width, size.height, state.alignment,
state.rowLength, state.imageHeight),
depthPitch);
} }
CheckedNumeric<GLuint> rowPitch; GLuint rowPitch = 0;
ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, pack.alignment, pack.rowLength), ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, state.alignment, state.rowLength),
rowPitch); rowPitch);
CheckedNumeric<GLuint> heightMinusOne = size.height - 1; CheckedNumeric<GLuint> checkedCopyBytes = 0;
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.
if (compressed) if (compressed)
{ {
return computeCompressedImageSize(formatType, size); ANGLE_TRY_RESULT(computeCompressedImageSize(formatType, size), checkedCopyBytes);
} }
else if (size.height != 0 && (!is3D || size.depth != 0))
if (size.height == 0 || size.depth == 0)
{ {
return 0; CheckedNumeric<GLuint> bytes = computePixelBytes(formatType);
} checkedCopyBytes += size.width * bytes;
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; CheckedNumeric<GLuint> heightMinusOne = size.height - 1;
totalSize += heightMinusOne * rowPitch; checkedCopyBytes += heightMinusOne * rowPitch;
totalSize += size.width * bytes;
ANGLE_TRY_CHECKED_MATH(totalSize); if (is3D)
{
return totalSize.ValueOrDie(); CheckedNumeric<GLuint> depthMinusOne = size.depth - 1;
} checkedCopyBytes += depthMinusOne * depthPitch;
}
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), CheckedNumeric<GLuint> checkedSkipBytes = 0;
rowPitch); ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, depthPitch, state, is3D), checkedSkipBytes);
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> endByte = checkedCopyBytes + checkedSkipBytes; CheckedNumeric<GLuint> endByte = checkedCopyBytes + checkedSkipBytes;
......
...@@ -49,39 +49,30 @@ struct InternalFormat ...@@ -49,39 +49,30 @@ struct InternalFormat
GLuint computePixelBytes(GLenum formatType) const; GLuint computePixelBytes(GLenum formatType) const;
gl::ErrorOrResult<GLuint> computeRowPitch(GLenum formatType, ErrorOrResult<GLuint> computeRowPitch(GLenum formatType,
GLsizei width, GLsizei width,
GLint alignment, GLint alignment,
GLint rowLength) const; GLint rowLength) const;
gl::ErrorOrResult<GLuint> computeDepthPitch(GLenum formatType, ErrorOrResult<GLuint> computeDepthPitch(GLenum formatType,
GLsizei width, GLsizei width,
GLsizei height, GLsizei height,
GLint alignment, GLint alignment,
GLint rowLength, GLint rowLength,
GLint imageHeight) const; GLint imageHeight) const;
gl::ErrorOrResult<GLuint> computeCompressedImageSize(GLenum formatType,
const gl::Extents &size) const; ErrorOrResult<GLuint> computeCompressedImageSize(GLenum formatType,
gl::ErrorOrResult<GLuint> computeSkipBytes(GLuint rowPitch, const Extents &size) const;
GLuint depthPitch,
GLint skipImages, ErrorOrResult<GLuint> computeSkipBytes(GLuint rowPitch,
GLint skipRows, GLuint depthPitch,
GLint skipPixels, const PixelStoreStateBase &state,
bool applySkipImages) const; bool is3D) const;
gl::ErrorOrResult<GLuint> computePackSize(GLenum formatType, ErrorOrResult<GLuint> computePackUnpackEndByte(GLenum formatType,
const gl::Extents &size, const Extents &size,
const gl::PixelPackState &pack) const; const PixelStoreStateBase &state,
gl::ErrorOrResult<GLuint> computeUnpackSize(GLenum formatType, bool is3D) const;
const gl::Extents &size,
const gl::PixelUnpackState &unpack) 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;
bool isLUMA() const; bool isLUMA() const;
GLenum getReadPixelsFormat() const; GLenum getReadPixelsFormat() const;
GLenum getReadPixelsType() const; GLenum getReadPixelsType() const;
...@@ -282,7 +273,7 @@ enum VertexFormatType ...@@ -282,7 +273,7 @@ enum VertexFormatType
VERTEX_FORMAT_UINT210_INT, VERTEX_FORMAT_UINT210_INT,
}; };
typedef std::vector<gl::VertexFormatType> InputLayout; typedef std::vector<VertexFormatType> InputLayout;
struct VertexFormat : angle::NonCopyable struct VertexFormat : angle::NonCopyable
{ {
......
...@@ -242,13 +242,13 @@ gl::Error FramebufferD3D::readPixels(ContextImpl *context, ...@@ -242,13 +242,13 @@ gl::Error FramebufferD3D::readPixels(ContextImpl *context,
GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
GLuint outputPitch = 0;
GLuint outputPitch = 0;
ANGLE_TRY_RESULT( ANGLE_TRY_RESULT(
sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength), sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength),
outputPitch); outputPitch);
GLuint outputSkipBytes = 0; GLuint outputSkipBytes = 0;
ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, 0, packState.skipRows, ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false),
packState.skipPixels, false),
outputSkipBytes); outputSkipBytes);
return readPixelsImpl(area, format, type, outputPitch, packState, return readPixelsImpl(area, format, type, outputPitch, packState,
......
...@@ -262,8 +262,7 @@ gl::Error Image11::loadData(const gl::Box &area, ...@@ -262,8 +262,7 @@ gl::Error Image11::loadData(const gl::Box &area,
inputDepthPitch); inputDepthPitch);
GLuint inputSkipBytes = 0; GLuint inputSkipBytes = 0;
ANGLE_TRY_RESULT( ANGLE_TRY_RESULT(
formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack.skipImages, formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
unpack.skipRows, unpack.skipPixels, applySkipImages),
inputSkipBytes); inputSkipBytes);
const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
......
...@@ -630,8 +630,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ...@@ -630,8 +630,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
srcDepthPitch); srcDepthPitch);
GLuint srcSkipBytes = 0; GLuint srcSkipBytes = 0;
ANGLE_TRY_RESULT( ANGLE_TRY_RESULT(
internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack.skipImages, internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()),
unpack.skipRows, unpack.skipPixels, index.is3D()),
srcSkipBytes); srcSkipBytes);
const d3d11::Format &d3d11Format = const d3d11::Format &d3d11Format =
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "libANGLE/renderer/gl/TextureGL.h" #include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/WorkaroundsGL.h" #include "libANGLE/renderer/gl/WorkaroundsGL.h"
#include "libANGLE/renderer/gl/formatutilsgl.h" #include "libANGLE/renderer/gl/formatutilsgl.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"
#include "platform/Platform.h" #include "platform/Platform.h"
using namespace gl; using namespace gl;
...@@ -30,50 +31,6 @@ using angle::CheckedNumeric; ...@@ -30,50 +31,6 @@ using angle::CheckedNumeric;
namespace rx 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, FramebufferGL::FramebufferGL(const FramebufferState &state,
const FunctionsGL *functions, const FunctionsGL *functions,
StateManagerGL *stateManager, StateManagerGL *stateManager,
...@@ -294,10 +251,12 @@ Error FramebufferGL::readPixels(ContextImpl *context, ...@@ -294,10 +251,12 @@ Error FramebufferGL::readPixels(ContextImpl *context,
if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion) if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
{ {
gl::Extents size(area.width, area.height, 1);
bool apply; bool apply;
ANGLE_TRY_RESULT( ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
ShouldApplyLastRowPaddingWorkaround(area, packState, readFormat, readType, pixels), false, pixels),
apply); apply);
if (apply) if (apply)
{ {
...@@ -476,9 +435,7 @@ gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area, ...@@ -476,9 +435,7 @@ gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength), ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
rowBytes); rowBytes);
GLuint skipBytes = 0; GLuint skipBytes = 0;
ANGLE_TRY_RESULT( ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
glFormat.computeSkipBytes(rowBytes, 0, 0, pack.skipRows, pack.skipPixels, false),
skipBytes);
gl::PixelPackState directPack; gl::PixelPackState directPack;
directPack.pixelBuffer = pack.pixelBuffer; directPack.pixelBuffer = pack.pixelBuffer;
...@@ -509,9 +466,7 @@ gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area, ...@@ -509,9 +466,7 @@ gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength), ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
rowBytes); rowBytes);
GLuint skipBytes = 0; GLuint skipBytes = 0;
ANGLE_TRY_RESULT( ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
glFormat.computeSkipBytes(rowBytes, 0, 0, pack.skipRows, pack.skipPixels, false),
skipBytes);
// Get all by the last row // Get all by the last row
if (area.height > 1) if (area.height > 1)
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "libANGLE/renderer/gl/StateManagerGL.h" #include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/WorkaroundsGL.h" #include "libANGLE/renderer/gl/WorkaroundsGL.h"
#include "libANGLE/renderer/gl/formatutilsgl.h" #include "libANGLE/renderer/gl/formatutilsgl.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"
using angle::CheckedNumeric; using angle::CheckedNumeric;
...@@ -89,50 +90,6 @@ LevelInfoGL GetLevelInfo(GLenum originalFormat, GLenum destinationFormat) ...@@ -89,50 +90,6 @@ LevelInfoGL GetLevelInfo(GLenum originalFormat, GLenum destinationFormat)
GetLUMAWorkaroundInfo(originalFormatInfo, destinationFormat)); 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 } // anonymous namespace
LUMAWorkaroundGL::LUMAWorkaroundGL() : LUMAWorkaroundGL(false, GL_NONE) LUMAWorkaroundGL::LUMAWorkaroundGL() : LUMAWorkaroundGL(false, GL_NONE)
...@@ -185,8 +142,14 @@ TextureGL::~TextureGL() ...@@ -185,8 +142,14 @@ TextureGL::~TextureGL()
mTextureID = 0; mTextureID = 0;
} }
gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, gl::Error TextureGL::setImage(GLenum target,
const gl::PixelUnpackState &unpack, const uint8_t *pixels) 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() && if (mWorkarounds.unpackOverlappingRowsSeparatelyUnpackBuffer && unpack.pixelBuffer.get() &&
unpack.rowLength != 0 && unpack.rowLength < size.width) unpack.rowLength != 0 && unpack.rowLength < size.width)
...@@ -207,8 +170,7 @@ gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat ...@@ -207,8 +170,7 @@ gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat
if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion) if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
{ {
bool apply; bool apply;
gl::Box area(0, 0, 0, size.width, size.height, size.depth); ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type,
ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(area, unpack, format, type,
UseTexImage3D(mState.mTarget), pixels), UseTexImage3D(mState.mTarget), pixels),
apply); apply);
...@@ -223,6 +185,7 @@ gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat ...@@ -223,6 +185,7 @@ gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat
return gl::NoError(); return gl::NoError();
} }
gl::Box area(0, 0, 0, size.width, size.height, size.depth);
return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels); return setSubImagePaddingWorkaround(target, level, area, format, type, unpack, pixels);
} }
} }
...@@ -303,8 +266,10 @@ gl::Error TextureGL::setSubImage(GLenum target, size_t level, const gl::Box &are ...@@ -303,8 +266,10 @@ gl::Error TextureGL::setSubImage(GLenum target, size_t level, const gl::Box &are
if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion) if (mWorkarounds.unpackLastRowSeparatelyForPaddingInclusion)
{ {
gl::Extents size(area.width, area.height, area.depth);
bool apply; bool apply;
ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(area, unpack, format, type, ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, unpack, format, type,
UseTexImage3D(mState.mTarget), pixels), UseTexImage3D(mState.mTarget), pixels),
apply); apply);
...@@ -359,8 +324,7 @@ gl::Error TextureGL::setSubImageRowByRowWorkaround(GLenum target, ...@@ -359,8 +324,7 @@ gl::Error TextureGL::setSubImageRowByRowWorkaround(GLenum target,
imageBytes); imageBytes);
bool useTexImage3D = UseTexImage3D(mState.mTarget); bool useTexImage3D = UseTexImage3D(mState.mTarget);
GLuint skipBytes = 0; GLuint skipBytes = 0;
ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack.skipImages, ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
unpack.skipRows, unpack.skipPixels, useTexImage3D),
skipBytes); skipBytes);
const uint8_t *pixelsWithSkip = pixels + skipBytes; const uint8_t *pixelsWithSkip = pixels + skipBytes;
...@@ -412,8 +376,7 @@ gl::Error TextureGL::setSubImagePaddingWorkaround(GLenum target, ...@@ -412,8 +376,7 @@ gl::Error TextureGL::setSubImagePaddingWorkaround(GLenum target,
imageBytes); imageBytes);
bool useTexImage3D = UseTexImage3D(mState.mTarget); bool useTexImage3D = UseTexImage3D(mState.mTarget);
GLuint skipBytes = 0; GLuint skipBytes = 0;
ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack.skipImages, ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
unpack.skipRows, unpack.skipPixels, useTexImage3D),
skipBytes); skipBytes);
gl::PixelUnpackState directUnpack; gl::PixelUnpackState directUnpack;
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <limits> #include <limits>
#include "common/mathutil.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Caps.h" #include "libANGLE/Caps.h"
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "libANGLE/renderer/gl/FunctionsGL.h" #include "libANGLE/renderer/gl/FunctionsGL.h"
...@@ -20,6 +22,8 @@ ...@@ -20,6 +22,8 @@
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
using angle::CheckedNumeric;
namespace rx namespace rx
{ {
VendorID GetVendorID(const FunctionsGL *functions) VendorID GetVendorID(const FunctionsGL *functions)
...@@ -968,4 +972,45 @@ uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions, ...@@ -968,4 +972,45 @@ uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions,
return nullptr; 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());
}
} }
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_ #define LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
#include "libANGLE/renderer/gl/functionsgl_typedefs.h" #include "libANGLE/renderer/gl/functionsgl_typedefs.h"
#include <string> #include <string>
...@@ -47,6 +48,13 @@ uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions, ...@@ -47,6 +48,13 @@ uint8_t *MapBufferRangeWithFallback(const FunctionsGL *functions,
size_t offset, size_t offset,
size_t length, size_t length,
GLbitfield access); 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_ #endif // LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
...@@ -1179,7 +1179,7 @@ bool ValidateReadPixels(ValidationContext *context, ...@@ -1179,7 +1179,7 @@ bool ValidateReadPixels(ValidationContext *context,
const gl::Extents size(width, height, 1); const gl::Extents size(width, height, 1);
const auto &pack = context->getGLState().getPackState(); const auto &pack = context->getGLState().getPackState();
auto endByteOrErr = formatInfo.computePackEndByte(type, size, pack); auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
if (endByteOrErr.isError()) if (endByteOrErr.isError())
{ {
context->handleError(endByteOrErr.getError()); context->handleError(endByteOrErr.getError());
...@@ -1230,7 +1230,7 @@ bool ValidateReadnPixelsEXT(Context *context, ...@@ -1230,7 +1230,7 @@ bool ValidateReadnPixelsEXT(Context *context,
const gl::Extents size(width, height, 1); const gl::Extents size(width, height, 1);
const auto &pack = context->getGLState().getPackState(); const auto &pack = context->getGLState().getPackState();
auto endByteOrErr = formatInfo.computePackEndByte(type, size, pack); auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
if (endByteOrErr.isError()) if (endByteOrErr.isError())
{ {
context->handleError(endByteOrErr.getError()); context->handleError(endByteOrErr.getError());
......
...@@ -487,7 +487,7 @@ bool ValidateES3TexImageParametersBase(Context *context, ...@@ -487,7 +487,7 @@ bool ValidateES3TexImageParametersBase(Context *context,
const auto &unpack = context->getGLState().getUnpackState(); const auto &unpack = context->getGLState().getUnpackState();
bool targetIs3D = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY; 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()) if (endByteOrErr.isError())
{ {
context->handleError(endByteOrErr.getError()); context->handleError(endByteOrErr.getError());
......
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