Bug 1479145 - Handle arbitrary strides for WebGL-to-SharedSurface readback on platforms that support it. r=jgilbert

The only platforms that do not support GL_PACK_ROW_LENGTH are platforms with
GLES 2. So on those platforms, trying to read back into buffers whose stride is
not width * 4 will assert.
That's fine because we usually don't encounter buffers with such large strides
on GLES 2 platforms. The only platform that really needs to handle the large
strides is macOS, and it always supports GL_PACK_ROW_LENGTH.
On macOS, we often run into large strides on surfaces that we intend to upload
as textures at some point, because large stride alignments are required for
efficient upload performance on some drivers.

Bug 1540209 tracks fixing the general case.

Differential Revision: https://phabricator.services.mozilla.com/D25464

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Markus Stange 2019-03-29 20:18:53 +00:00
parent baea6b435f
commit 2770f087b3
4 changed files with 24 additions and 9 deletions

View File

@ -387,6 +387,22 @@ ScopedPackState::ScopedPackState(GLContext* gl)
if (mSkipRows != 0) mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, 0);
}
bool ScopedPackState::SetForWidthAndStrideRGBA(GLsizei aWidth,
GLsizei aStride) {
MOZ_ASSERT(aStride % 4 == 0, "RGBA data should always be 4-byte aligned");
MOZ_ASSERT(aStride / 4 >= aWidth, "Stride too small");
if (aStride / 4 == aWidth) {
// No special handling needed.
return true;
}
if (mGL->HasPBOState()) {
// HasPBOState implies support for GL_PACK_ROW_LENGTH.
mGL->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, aStride / 4);
return true;
}
return false;
}
void ScopedPackState::UnwrapImpl() {
mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, mAlignment);

View File

@ -287,6 +287,9 @@ struct ScopedPackState : public ScopedGLWrapper<ScopedPackState> {
public:
explicit ScopedPackState(GLContext* gl);
// Returns whether the stride was handled successfully.
bool SetForWidthAndStrideRGBA(GLsizei aWidth, GLsizei aStride);
protected:
void UnwrapImpl();
};

View File

@ -508,14 +508,9 @@ bool ReadbackSharedSurface(SharedSurface* src, gfx::DrawTarget* dst) {
// ReadPixels from the current FB into lockedBits.
{
size_t alignment = 8;
if (dstStride % 4 == 0) alignment = 4;
ScopedPackState scopedPackState(gl);
if (alignment != 4) {
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, alignment);
}
bool handled = scopedPackState.SetForWidthAndStrideRGBA(width, dstStride);
MOZ_RELEASE_ASSERT(handled, "Unhandled stride");
gl->raw_fReadPixels(0, 0, width, height, readGLFormat, readType,
dstBytes);
}

View File

@ -313,11 +313,12 @@ static already_AddRefed<TextureClient> TexClientFromReadback(
// ReadPixels from the current FB into mapped.data.
auto width = src->mSize.width;
auto height = src->mSize.height;
auto stride = mapped.stride;
{
ScopedPackState scopedPackState(gl);
MOZ_ASSERT(mapped.stride / 4 == mapped.size.width);
bool handled = scopedPackState.SetForWidthAndStrideRGBA(width, stride);
MOZ_RELEASE_ASSERT(handled, "Unhandled stride");
gl->raw_fReadPixels(0, 0, width, height, readFormat, readType,
mapped.data);
}