Commit b8aee3bc by Minmin Gong Committed by Geoff Lang

Add UNPACK_ROW_LENGTH support to D3D11 renderer

Change-Id: I31ccffddcb04a45f19d3c3eb9a396c30e794b218 Reviewed-on: https://chromium-review.googlesource.com/243951Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarMinmin Gong <mgong@microsoft.com>
parent 1d57ad40
......@@ -1128,6 +1128,16 @@ GLint State::getUnpackAlignment() const
return mUnpack.alignment;
}
void State::setUnpackRowLength(GLint rowLength)
{
mUnpack.rowLength = rowLength;
}
GLint State::getUnpackRowLength() const
{
return mUnpack.rowLength;
}
const PixelUnpackState &State::getUnpackState() const
{
return mUnpack;
......@@ -1226,6 +1236,7 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
case GL_PACK_ALIGNMENT: *params = mPack.alignment; break;
case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mPack.reverseRowOrder; break;
case GL_UNPACK_ALIGNMENT: *params = mUnpack.alignment; break;
case GL_UNPACK_ROW_LENGTH: *params = mUnpack.rowLength; break;
case GL_GENERATE_MIPMAP_HINT: *params = mGenerateMipmapHint; break;
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mFragmentShaderDerivativeHint; break;
case GL_ACTIVE_TEXTURE: *params = (mActiveSampler + GL_TEXTURE0); break;
......
......@@ -233,6 +233,8 @@ class State
// Pixel unpack state manipulation
void setUnpackAlignment(GLint alignment);
GLint getUnpackAlignment() const;
void setUnpackRowLength(GLint rowLength);
GLint getUnpackRowLength() const;
const PixelUnpackState &getUnpackState() const;
// State query functions
......
......@@ -207,13 +207,16 @@ struct PixelUnpackState
{
BindingPointer<Buffer> pixelBuffer;
GLint alignment;
GLint rowLength;
PixelUnpackState()
: alignment(4)
: alignment(4),
rowLength(0)
{}
explicit PixelUnpackState(GLint alignmentIn)
: alignment(alignmentIn)
PixelUnpackState(GLint alignmentIn, GLint rowLengthIn)
: alignment(alignmentIn),
rowLength(rowLengthIn)
{}
};
......
......@@ -560,15 +560,25 @@ const InternalFormat &GetInternalFormatInfo(GLenum internalFormat)
}
}
GLuint InternalFormat::computeRowPitch(GLenum formatType, GLsizei width, GLint alignment) const
GLuint InternalFormat::computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const
{
ASSERT(alignment > 0 && isPow2(alignment));
return rx::roundUp(computeBlockSize(formatType, width, 1), static_cast<GLuint>(alignment));
GLuint rowBytes;
if (rowLength > 0)
{
ASSERT(!compressed);
rowBytes = pixelBytes * rowLength;
}
else
{
rowBytes = computeBlockSize(formatType, width, 1);
}
return rx::roundUp(rowBytes, static_cast<GLuint>(alignment));
}
GLuint InternalFormat::computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment) const
GLuint InternalFormat::computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const
{
return computeRowPitch(formatType, width, alignment) * height;
return computeRowPitch(formatType, width, alignment, rowLength) * height;
}
GLuint InternalFormat::computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const
......
......@@ -64,8 +64,8 @@ struct InternalFormat
SupportCheckFunction renderSupport;
SupportCheckFunction filterSupport;
GLuint computeRowPitch(GLenum formatType, GLsizei width, GLint alignment) const;
GLuint computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment) const;
GLuint computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const;
GLuint computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const;
GLuint computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const;
};
const InternalFormat &GetInternalFormatInfo(GLenum internalFormat);
......
......@@ -257,7 +257,7 @@ gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle
{
GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, state.getPackAlignment());
GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, state.getPackAlignment(), 0);
return readPixels(area, format, type, outputPitch, state.getPackState(), reinterpret_cast<uint8_t*>(pixels));
}
......
......@@ -23,6 +23,7 @@ struct Box;
struct Extents;
struct Offset;
struct Rectangle;
struct PixelUnpackState;
}
namespace rx
......@@ -50,7 +51,7 @@ class ImageD3D
virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0;
virtual gl::Error loadData(const gl::Box &area, GLint unpackAlignment, GLenum type, const void *input) = 0;
virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) = 0;
virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0;
virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
......
......@@ -580,7 +580,7 @@ gl::Texture *RendererD3D::getIncompleteTexture(GLenum type)
{
const GLubyte color[] = { 0, 0, 0, 255 };
const gl::Extents colorSize(1, 1, 1);
const gl::PixelUnpackState incompleteUnpackState(1);
const gl::PixelUnpackState incompleteUnpackState(1, 0);
gl::Texture* t = new gl::Texture(createTexture(type), gl::Texture::INCOMPLETE_TEXTURE_ID, type);
......
......@@ -176,7 +176,7 @@ gl::Error TextureD3D::setImage(const gl::ImageIndex &index, GLenum type,
else
{
gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
error = image->loadData(fullImageArea, unpack.alignment, type, pixelData);
error = image->loadData(fullImageArea, unpack, type, pixelData);
}
if (error.isError())
......@@ -211,7 +211,7 @@ gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area,
return mTexStorage->setData(index, image, &area, type, unpack, pixelData);
}
error = image->loadData(area, unpack.alignment, type, pixelData);
error = image->loadData(area, unpack, type, pixelData);
if (error.isError())
{
return error;
......@@ -2347,7 +2347,7 @@ gl::Error TextureD3D_2DArray::setImage(GLenum target, size_t level, GLenum inter
redefineImage(level, sizedInternalFormat, size);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment, unpack.rowLength);
for (int i = 0; i < size.depth; i++)
{
......@@ -2369,7 +2369,7 @@ gl::Error TextureD3D_2DArray::setSubImage(GLenum target, size_t level, const gl:
ASSERT(target == GL_TEXTURE_2D_ARRAY);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength);
for (int i = 0; i < area.depth; i++)
{
......@@ -2398,7 +2398,7 @@ gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, size_t level, GL
redefineImage(level, internalFormat, size);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0);
for (int i = 0; i < size.depth; i++)
{
......@@ -2421,7 +2421,7 @@ gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level,
ASSERT(target == GL_TEXTURE_2D_ARRAY);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
for (int i = 0; i < area.depth; i++)
{
......
......@@ -246,11 +246,11 @@ DXGI_FORMAT Image11::getDXGIFormat() const
// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
// into the target pixel rectangle.
gl::Error Image11::loadData(const gl::Box &area, GLint unpackAlignment, GLenum type, const void *input)
gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input)
{
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpackAlignment);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpackAlignment);
GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength);
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
......@@ -278,8 +278,8 @@ gl::Error Image11::loadData(const gl::Box &area, GLint unpackAlignment, GLenum t
gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input)
{
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1);
GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
......
......@@ -43,7 +43,7 @@ class Image11 : public ImageD3D
DXGI_FORMAT getDXGIFormat() const;
virtual gl::Error loadData(const gl::Box &area, GLint unpackAlignment, GLenum type, const void *input);
virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input);
virtual gl::Error loadCompressedData(const gl::Box &area, const void *input);
virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source);
......
......@@ -165,7 +165,7 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons
unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel);
parametersOut->FirstPixelOffset = offset / bytesPerPixel;
parametersOut->PixelsPerRow = static_cast<unsigned int>(destArea.width);
parametersOut->PixelsPerRow = static_cast<unsigned int>((unpack.rowLength > 0) ? unpack.rowLength : destArea.width);
parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels);
parametersOut->RowsPerSlice = static_cast<unsigned int>(destArea.height);
parametersOut->PositionOffset[0] = texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
......
......@@ -550,8 +550,8 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image
int width = destBox ? destBox->width : static_cast<int>(image->getWidth());
int height = destBox ? destBox->height : static_cast<int>(image->getHeight());
int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth());
UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment);
UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment);
UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment, unpack.rowLength);
const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getFeatureLevel());
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat);
......
......@@ -478,13 +478,13 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &a
// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
// into the target pixel rectangle.
gl::Error Image9::loadData(const gl::Box &area, GLint unpackAlignment, GLenum type, const void *input)
gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input)
{
// 3D textures are not supported by the D3D9 backend.
ASSERT(area.z == 0 && area.depth == 1);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpackAlignment);
GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
ASSERT(d3dFormatInfo.loadFunction != NULL);
......@@ -517,8 +517,8 @@ gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
ASSERT(area.z == 0 && area.depth == 1);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1);
GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
......
......@@ -44,7 +44,7 @@ class Image9 : public ImageD3D
virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level);
virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
virtual gl::Error loadData(const gl::Box &area, GLint unpackAlignment, GLenum type, const void *input);
virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input);
virtual gl::Error loadCompressedData(const gl::Box &area, const void *input);
virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source);
......
......@@ -927,7 +927,7 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment());
GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(), 0);
// sized query sanity check
if (bufSize)
{
......
......@@ -3128,6 +3128,23 @@ void GL_APIENTRY PixelStorei(GLenum pname, GLint param)
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientVersion() < 3)
{
switch (pname)
{
case GL_UNPACK_IMAGE_HEIGHT:
case GL_UNPACK_SKIP_IMAGES:
case GL_UNPACK_ROW_LENGTH:
case GL_UNPACK_SKIP_ROWS:
case GL_UNPACK_SKIP_PIXELS:
case GL_PACK_ROW_LENGTH:
case GL_PACK_SKIP_ROWS:
case GL_PACK_SKIP_PIXELS:
context->recordError(Error(GL_INVALID_ENUM));
return;
}
}
switch (pname)
{
case GL_UNPACK_ALIGNMENT:
......@@ -3154,19 +3171,19 @@ void GL_APIENTRY PixelStorei(GLenum pname, GLint param)
context->getState().setPackReverseRowOrder(param != 0);
break;
case GL_UNPACK_ROW_LENGTH:
ASSERT(context->getClientVersion() >= 3);
context->getState().setUnpackRowLength(param);
break;
case GL_UNPACK_IMAGE_HEIGHT:
case GL_UNPACK_SKIP_IMAGES:
case GL_UNPACK_ROW_LENGTH:
case GL_UNPACK_SKIP_ROWS:
case GL_UNPACK_SKIP_PIXELS:
case GL_PACK_ROW_LENGTH:
case GL_PACK_SKIP_ROWS:
case GL_PACK_SKIP_PIXELS:
if (context->getClientVersion() < 3)
{
context->recordError(Error(GL_INVALID_ENUM));
return;
}
ASSERT(context->getClientVersion() >= 3);
UNIMPLEMENTED();
break;
......
......@@ -46,6 +46,7 @@
'<(angle_path)/tests/angle_tests/TransformFeedbackTest.cpp',
'<(angle_path)/tests/angle_tests/UniformTest.cpp',
'<(angle_path)/tests/angle_tests/UnpackAlignmentTest.cpp',
'<(angle_path)/tests/angle_tests/UnpackRowLength.cpp',
'<(angle_path)/tests/angle_tests/VertexAttributeTest.cpp',
'<(angle_path)/tests/angle_tests/ViewportTest.cpp',
'<(angle_path)/tests/standalone_tests/EGLThreadTest.cpp',
......
#include "ANGLETest.h"
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_TYPED_TEST_CASE(UnpackRowLengthTest, ES3_D3D11, ES2_D3D11);
#include <array>
template<typename T>
class UnpackRowLengthTest : public ANGLETest
{
protected:
UnpackRowLengthTest() : ANGLETest(T::GetGlesMajorVersion(), T::GetPlatform())
{
setWindowWidth(128);
setWindowHeight(128);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
mProgram = 0;
}
virtual void SetUp() override
{
ANGLETest::SetUp();
const std::string vertexShaderSource = SHADER_SOURCE
(
precision highp float;
attribute vec4 position;
void main()
{
gl_Position = position;
}
);
const std::string fragmentShaderSource = SHADER_SOURCE
(
uniform sampler2D tex;
void main()
{
gl_FragColor = texture2D(tex, vec2(0.0, 1.0));
}
);
mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
if (mProgram == 0)
{
FAIL() << "shader compilation failed.";
}
}
virtual void TearDown() override
{
glDeleteProgram(mProgram);
ANGLETest::TearDown();
}
void testRowLength(int texSize, int rowLength)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, rowLength);
if (getClientVersion() == 3)
{
// Only texSize * texSize region is filled as WHITE, other parts are BLACK.
// If the UNPACK_ROW_LENGTH is implemented correctly, all texels inside this texture are WHITE.
std::vector<GLubyte> buf(rowLength * texSize * 4);
for (int y = 0; y < texSize; y++)
{
std::vector<GLubyte>::iterator rowIter = buf.begin() + y * rowLength * 4;
std::fill(rowIter, rowIter + texSize * 4, 255);
std::fill(rowIter + texSize * 4, rowIter + rowLength * 4, 0);
}
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texSize, texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, &buf[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
EXPECT_PIXEL_EQ(1, 0, 255, 255, 255, 255);
glDeleteTextures(1, &tex);
}
else
{
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
}
GLuint mProgram;
};
TYPED_TEST(UnpackRowLengthTest, RowLength128)
{
testRowLength(128, 128);
}
TYPED_TEST(UnpackRowLengthTest, RowLength1024)
{
testRowLength(128, 1024);
}
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