Bug 1616715 - Make ReadPixelDesc per-call. r=lsalzman

GetSurfaceSnapshot (and similar) want to ReadPixels the backbuffer,
without having to navigate the GL PIXEL_PACK state.
Since this is cold cold code, it's nice to reduce the backend state by
making ReadPixelsDesc/PixelPackState per-call, and tracked by the
client. Arguably, PIXEL_PACK_BUFFER should be per-call as well.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jeff Gilbert 2020-02-21 03:12:41 +00:00
Родитель 011c0a1fd7
Коммит 1abd55a851
9 изменённых файлов: 238 добавлений и 172 удалений

Просмотреть файл

@ -895,16 +895,17 @@ already_AddRefed<gfx::SourceSurface> ClientWebGLContext::GetSurfaceSnapshot(
const auto drawFbWas = state.mBoundDrawFb;
const auto readFbWas = state.mBoundReadFb;
const auto alignmentWas = Run<RPROC(GetParameter)>(LOCAL_GL_PACK_ALIGNMENT);
if (!alignmentWas) return nullptr;
const auto pboWas =
Find(state.mBoundBufferByTarget, LOCAL_GL_PIXEL_PACK_BUFFER);
const auto size = DrawingBufferSize();
// -
BindFramebuffer(LOCAL_GL_FRAMEBUFFER, nullptr);
PixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
if (pboWas) {
BindBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, nullptr);
}
auto reset = MakeScopeExit([&] {
if (drawFbWas == readFbWas) {
@ -913,7 +914,9 @@ already_AddRefed<gfx::SourceSurface> ClientWebGLContext::GetSurfaceSnapshot(
BindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER, drawFbWas);
BindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, readFbWas);
}
PixelStorei(LOCAL_GL_PACK_ALIGNMENT, *alignmentWas);
if (pboWas) {
BindBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, pboWas);
}
});
const auto surfFormat = options.alpha ? gfx::SurfaceFormat::B8G8R8A8
@ -934,10 +937,11 @@ already_AddRefed<gfx::SourceSurface> ClientWebGLContext::GetSurfaceSnapshot(
}
MOZ_ASSERT(static_cast<uint32_t>(map.GetStride()) == stride);
const auto desc = webgl::ReadPixelsDesc{{0, 0}, size};
const auto range = Range<uint8_t>(map.GetData(), stride * size.y);
auto view = RawBufferView(range);
Run<RPROC(ReadPixels)>(0, 0, size.x, size.y, LOCAL_GL_RGBA,
LOCAL_GL_UNSIGNED_BYTE, view);
Run<RPROC(ReadPixels)>(desc, view);
// -
@ -1695,6 +1699,10 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
}
break;
case LOCAL_GL_PACK_ALIGNMENT:
retval.set(JS::NumberValue(state.mPixelPackState.alignment));
return;
// -
// Array returns
@ -1827,6 +1835,16 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
case LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS:
retval.set(JS::NumberValue(limits.maxTexArrayLayers));
return;
case LOCAL_GL_PACK_ROW_LENGTH:
retval.set(JS::NumberValue(state.mPixelPackState.rowLength));
return;
case LOCAL_GL_PACK_SKIP_PIXELS:
retval.set(JS::NumberValue(state.mPixelPackState.skipPixels));
return;
case LOCAL_GL_PACK_SKIP_ROWS:
retval.set(JS::NumberValue(state.mPixelPackState.skipRows));
return;
} // switch pname
} // if webgl2
@ -2410,7 +2428,50 @@ void ClientWebGLContext::LineWidth(GLfloat width) {
Run<RPROC(LineWidth)>(width);
}
void ClientWebGLContext::PixelStorei(GLenum pname, GLint param) {
void ClientWebGLContext::PixelStorei(const GLenum pname, const GLint iparam) {
const FuncScope funcScope(*this, "pixelStorei");
if (IsContextLost()) return;
if (!ValidateNonNegative("param", iparam)) return;
const auto param = static_cast<uint32_t>(iparam);
auto& state = State();
auto& packState = state.mPixelPackState;
switch (pname) {
case LOCAL_GL_PACK_ALIGNMENT:
switch (param) {
case 1:
case 2:
case 4:
case 8:
break;
default:
EnqueueError(LOCAL_GL_INVALID_VALUE,
"PACK_ALIGNMENT must be one of [1,2,4,8], was %i.",
iparam);
return;
}
packState.alignment = param;
return;
case LOCAL_GL_PACK_ROW_LENGTH:
if (!mIsWebGL2) break;
packState.rowLength = param;
return;
case LOCAL_GL_PACK_SKIP_PIXELS:
if (!mIsWebGL2) break;
packState.skipPixels = param;
return;
case LOCAL_GL_PACK_SKIP_ROWS:
if (!mIsWebGL2) break;
packState.skipRows = param;
return;
default:
break;
}
Run<RPROC(PixelStorei)>(pname, param);
}
@ -3841,9 +3902,16 @@ void ClientWebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
ErrorResult& out_error) const {
const FuncScope funcScope(*this, "readPixels");
if (!ReadPixels_SharedPrecheck(aCallerType, out_error)) return;
const auto& state = State();
if (!ValidateNonNegative("width", width)) return;
if (!ValidateNonNegative("height", height)) return;
if (!ValidateNonNegative("offset", offset)) return;
Run<RPROC(ReadPixelsPbo)>(x, y, width, height, format, type,
static_cast<uint64_t>(offset));
const auto desc = webgl::ReadPixelsDesc{{x, y},
*uvec2::From(width, height),
{format, type},
state.mPixelPackState};
Run<RPROC(ReadPixelsPbo)>(desc, static_cast<uint64_t>(offset));
}
void ClientWebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
@ -3854,6 +3922,9 @@ void ClientWebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
ErrorResult& out_error) const {
const FuncScope funcScope(*this, "readPixels");
if (!ReadPixels_SharedPrecheck(aCallerType, out_error)) return;
const auto& state = State();
if (!ValidateNonNegative("width", width)) return;
if (!ValidateNonNegative("height", height)) return;
////
@ -3882,9 +3953,14 @@ void ClientWebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
LOCAL_GL_INVALID_VALUE, &bytes, &byteLen)) {
return;
}
const auto desc = webgl::ReadPixelsDesc{{x, y},
*uvec2::From(width, height),
{format, type},
state.mPixelPackState};
const auto range = Range<uint8_t>(bytes, byteLen);
auto view = RawBufferView(range);
Run<RPROC(ReadPixels)>(x, y, width, height, format, type, view);
Run<RPROC(ReadPixels)>(desc, view);
}
bool ClientWebGLContext::ReadPixels_SharedPrecheck(

Просмотреть файл

@ -177,6 +177,7 @@ class ContextGenerationInfo final {
std::array<float, 4> mClearColor = {{0, 0, 0, 0}};
std::array<float, 4> mBlendColor = {{0, 0, 0, 0}};
std::array<float, 2> mDepthRange = {{0, 1}};
webgl::PixelPackState mPixelPackState;
std::vector<GLenum> mCompressedTextureFormats;

Просмотреть файл

@ -409,7 +409,7 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
mContext->LinkProgram(*obj);
}
void PixelStorei(GLenum pname, GLint param) const {
void PixelStorei(GLenum pname, uint32_t param) const {
mContext->PixelStorei(pname, param);
}
@ -646,15 +646,15 @@ class HostWebGLContext final : public SupportsWeakPtr<HostWebGLContext> {
}
// ------------------------------ Readback -------------------------------
void ReadPixelsPbo(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, uint64_t offset) const {
mContext->ReadPixelsPbo(x, y, width, height, format, type, offset);
void ReadPixelsPbo(const webgl::ReadPixelsDesc& desc,
const uint64_t offset) const {
mContext->ReadPixelsPbo(desc, offset);
}
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, RawBuffer<uint8_t>& dest) const {
void ReadPixels(const webgl::ReadPixelsDesc& desc,
RawBuffer<uint8_t>& dest) const {
const auto range = MakeRange(dest);
mContext->ReadPixels(x, y, width, height, format, type, range);
mContext->ReadPixels(desc, range);
}
// ----------------------------- Sampler -----------------------------------

Просмотреть файл

@ -610,7 +610,7 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
void LineWidth(GLfloat width);
void LinkProgram(WebGLProgram& prog);
void PixelStorei(GLenum pname, GLint param);
void PixelStorei(GLenum pname, uint32_t param);
void PolygonOffset(GLfloat factor, GLfloat units);
RefPtr<layers::SharedSurfaceTextureClient> GetVRFrame();
@ -623,20 +623,15 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
const webgl::FormatUsageInfo* usage) const;
protected:
void ReadPixelsImpl(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, uintptr_t data,
void ReadPixelsImpl(const webgl::ReadPixelsDesc&, uintptr_t data,
uint64_t dataLen);
bool DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat, GLint x,
GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum destType, uintptr_t dest,
bool DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat,
const webgl::ReadPixelsDesc&, uintptr_t dest,
uint64_t dataLen, uint32_t rowStride);
public:
void ReadPixelsPbo(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, uint64_t offset);
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, const Range<uint8_t>& dest);
void ReadPixelsPbo(const webgl::ReadPixelsDesc&, uint64_t offset);
void ReadPixels(const webgl::ReadPixelsDesc&, const Range<uint8_t>& dest);
////
@ -1161,10 +1156,6 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr<WebGLContext> {
CheckedUint32 GetUnpackSize(bool isFunc3D, uint32_t width, uint32_t height,
uint32_t depth, uint8_t bytesPerPixel);
bool ValidatePackSize(uint32_t width, uint32_t height, uint8_t bytesPerPixel,
uint32_t* const out_rowStride,
uint32_t* const out_endOffset);
UniquePtr<webgl::TexUnpackBlob> FromDomElem(
const dom::HTMLCanvasElement& canvas, TexImageTarget target, uvec3 size,
const dom::Element& elem, ErrorResult* const out_error) const;

Просмотреть файл

@ -734,7 +734,7 @@ void WebGLContext::LinkProgram(WebGLProgram& prog) {
}
}
void WebGLContext::PixelStorei(GLenum pname, GLint param) {
void WebGLContext::PixelStorei(GLenum pname, uint32_t param) {
const FuncScope funcScope(*this, "pixelStorei");
if (IsContextLost()) return;
@ -760,24 +760,10 @@ void WebGLContext::PixelStorei(GLenum pname, GLint param) {
case LOCAL_GL_UNPACK_SKIP_PIXELS:
pValueSlot = &mPixelStore.mUnpackSkipPixels;
break;
case LOCAL_GL_PACK_ROW_LENGTH:
pValueSlot = &mPixelStore.mPackRowLength;
break;
case LOCAL_GL_PACK_SKIP_ROWS:
pValueSlot = &mPixelStore.mPackSkipRows;
break;
case LOCAL_GL_PACK_SKIP_PIXELS:
pValueSlot = &mPixelStore.mPackSkipPixels;
break;
}
if (pValueSlot) {
if (!ValidateNonNegative("param", param)) return;
gl->fPixelStorei(pname, param);
gl->fPixelStorei(pname, static_cast<int32_t>(param));
*pValueSlot = param;
return;
}
@ -811,19 +797,14 @@ void WebGLContext::PixelStorei(GLenum pname, GLint param) {
}
break;
case LOCAL_GL_PACK_ALIGNMENT:
case LOCAL_GL_UNPACK_ALIGNMENT:
switch (param) {
case 1:
case 2:
case 4:
case 8:
if (pname == LOCAL_GL_PACK_ALIGNMENT)
mPixelStore.mPackAlignment = param;
else if (pname == LOCAL_GL_UNPACK_ALIGNMENT)
mPixelStore.mUnpackAlignment = param;
gl->fPixelStorei(pname, param);
mPixelStore.mUnpackAlignment = param;
gl->fPixelStorei(pname, static_cast<int32_t>(param));
return;
default:
@ -839,30 +820,32 @@ void WebGLContext::PixelStorei(GLenum pname, GLint param) {
return;
}
bool WebGLContext::DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat,
GLint x, GLint y, GLsizei width,
GLsizei height, GLenum format,
GLenum destType, uintptr_t dest,
uint64_t destSize,
uint32_t rowStride) {
bool WebGLContext::DoReadPixelsAndConvert(
const webgl::FormatInfo* const srcFormat, const webgl::ReadPixelsDesc& desc,
const uintptr_t dest, const uint64_t destSize, const uint32_t rowStride) {
const auto& x = desc.srcOffset.x;
const auto& y = desc.srcOffset.y;
const auto size = *ivec2::From(desc.size);
const auto& pi = desc.pi;
// On at least Win+NV, we'll get PBO errors if we don't have at least
// `rowStride * height` bytes available to read into.
const auto naiveBytesNeeded = CheckedInt<uint64_t>(rowStride) * height;
const auto naiveBytesNeeded = CheckedInt<uint64_t>(rowStride) * size.y;
const bool isDangerCloseToEdge =
(!naiveBytesNeeded.isValid() || naiveBytesNeeded.value() > destSize);
const bool useParanoidHandling =
(gl->WorkAroundDriverBugs() && isDangerCloseToEdge &&
mBoundPixelPackBuffer);
if (!useParanoidHandling) {
gl->fReadPixels(x, y, width, height, format, destType,
gl->fReadPixels(x, y, size.x, size.y, pi.format, pi.type,
reinterpret_cast<void*>(dest));
return true;
}
// Read everything but the last row.
const auto bodyHeight = height - 1;
const auto bodyHeight = size.y - 1;
if (bodyHeight) {
gl->fReadPixels(x, y, width, bodyHeight, format, destType,
gl->fReadPixels(x, y, size.x, bodyHeight, pi.format, pi.type,
reinterpret_cast<void*>(dest));
}
@ -871,20 +854,33 @@ bool WebGLContext::DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat,
gl->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, 0);
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, 0);
const auto tailRowOffset = (char*)dest + rowStride * bodyHeight;
gl->fReadPixels(x, y + bodyHeight, width, 1, format, destType, tailRowOffset);
const auto tailRowOffset =
reinterpret_cast<uint8_t*>(dest) + rowStride * bodyHeight;
gl->fReadPixels(x, y + bodyHeight, size.x, 1, pi.format, pi.type,
tailRowOffset);
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, mPixelStore.mPackAlignment);
gl->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, mPixelStore.mPackRowLength);
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, mPixelStore.mPackSkipRows);
return true;
}
bool WebGLContext::ValidatePackSize(uint32_t width, uint32_t height,
uint8_t bytesPerPixel,
uint32_t* const out_rowStride,
uint32_t* const out_endOffset) {
if (!width || !height) {
static bool ValidatePackSize(const WebGLContext& webgl,
const webgl::PixelPackState& packing,
const uvec2& size, uint8_t bytesPerPixel,
uint32_t* const out_rowStride,
uint32_t* const out_endOffset) {
const auto alignment = packing.alignment;
switch (alignment) {
case 1:
case 2:
case 4:
case 8:
break;
default:
MOZ_ASSERT(false);
webgl.ErrorImplementationBug("Invalid PACK_ALIGNMENT.");
return false;
}
if (!size.x || !size.y) {
*out_rowStride = 0;
*out_endOffset = 0;
return true;
@ -892,17 +888,15 @@ bool WebGLContext::ValidatePackSize(uint32_t width, uint32_t height,
// GLES 3.0.4, p116 (PACK_ functions like UNPACK_)
const auto rowLength =
(mPixelStore.mPackRowLength ? mPixelStore.mPackRowLength : width);
const auto skipPixels = mPixelStore.mPackSkipPixels;
const auto skipRows = mPixelStore.mPackSkipRows;
const auto alignment = mPixelStore.mPackAlignment;
const auto rowLength = (packing.rowLength ? packing.rowLength : size.x);
const auto skipPixels = packing.skipPixels;
const auto skipRows = packing.skipRows;
const auto usedPixelsPerRow = CheckedUint32(skipPixels) + width;
const auto usedRowsPerImage = CheckedUint32(skipRows) + height;
const auto usedPixelsPerRow = CheckedUint32(skipPixels) + size.x;
const auto usedRowsPerImage = CheckedUint32(skipRows) + size.y;
if (!usedPixelsPerRow.isValid() || usedPixelsPerRow.value() > rowLength) {
ErrorInvalidOperation("SKIP_PIXELS + width > ROW_LENGTH.");
webgl.ErrorInvalidOperation("SKIP_PIXELS + width > ROW_LENGTH.");
return false;
}
@ -914,7 +908,7 @@ bool WebGLContext::ValidatePackSize(uint32_t width, uint32_t height,
(usedRowsPerImage - 1) * rowStride + usedBytesPerRow;
if (!rowStride.isValid() || !usedBytesPerImage.isValid()) {
ErrorInvalidOperation("Invalid UNPACK_ params.");
webgl.ErrorInvalidOperation("Invalid UNPACK_ params.");
return false;
}
@ -923,8 +917,7 @@ bool WebGLContext::ValidatePackSize(uint32_t width, uint32_t height,
return true;
}
void WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
void WebGLContext::ReadPixels(const webgl::ReadPixelsDesc& desc,
const Range<uint8_t>& dest) {
const FuncScope funcScope(*this, "readPixels");
if (IsContextLost()) return;
@ -934,14 +927,12 @@ void WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
return;
}
ReadPixelsImpl(x, y, width, height, format, type,
reinterpret_cast<uintptr_t>(dest.begin().get()),
ReadPixelsImpl(desc, reinterpret_cast<uintptr_t>(dest.begin().get()),
dest.length());
}
void WebGLContext::ReadPixelsPbo(GLint x, GLint y, GLsizei width,
GLsizei height, GLenum format, GLenum type,
uint64_t offset) {
void WebGLContext::ReadPixelsPbo(const webgl::ReadPixelsDesc& desc,
const uint64_t offset) {
const FuncScope funcScope(*this, "readPixels");
if (IsContextLost()) return;
@ -951,7 +942,8 @@ void WebGLContext::ReadPixelsPbo(GLint x, GLint y, GLsizei width,
//////
{
const auto bytesPerType = webgl::BytesPerPixel({LOCAL_GL_RED, type});
const auto bytesPerType =
webgl::BytesPerPixel({LOCAL_GL_RED, desc.pi.type});
if (offset % bytesPerType != 0) {
ErrorInvalidOperation(
@ -974,7 +966,7 @@ void WebGLContext::ReadPixelsPbo(GLint x, GLint y, GLsizei width,
const ScopedLazyBind lazyBind(gl, LOCAL_GL_PIXEL_PACK_BUFFER, buffer);
ReadPixelsImpl(x, y, width, height, format, type, offset, bytesAvailable);
ReadPixelsImpl(desc, offset, bytesAvailable);
buffer->ResetLastUpdateFenceId();
}
@ -1082,20 +1074,9 @@ static bool ValidateReadPixelsFormatAndType(
return false;
}
void WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth,
GLsizei rawHeight, GLenum packFormat,
GLenum packType, uintptr_t dest,
uint64_t availBytes) {
if (!ValidateNonNegative("width", rawWidth) ||
!ValidateNonNegative("height", rawHeight)) {
return;
}
const uint32_t width(rawWidth);
const uint32_t height(rawHeight);
//////
void WebGLContext::ReadPixelsImpl(const webgl::ReadPixelsDesc& desc,
const uintptr_t dest,
const uint64_t availBytes) {
const webgl::FormatUsageInfo* srcFormat;
uint32_t srcWidth;
uint32_t srcHeight;
@ -1103,20 +1084,29 @@ void WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth,
//////
const webgl::PackingInfo pi = {packFormat, packType};
if (!ValidateReadPixelsFormatAndType(srcFormat, pi, gl, this)) return;
if (!ValidateReadPixelsFormatAndType(srcFormat, desc.pi, gl, this)) return;
uint8_t bytesPerPixel;
if (!webgl::GetBytesPerPixel(pi, &bytesPerPixel)) {
if (!webgl::GetBytesPerPixel(desc.pi, &bytesPerPixel)) {
ErrorInvalidOperation("Unsupported format and type.");
return;
}
//////
const auto& srcOffset = desc.srcOffset;
const auto& size = desc.size;
if (!ivec2::From(size)) {
ErrorInvalidValue("width and height must be non-negative.");
return;
}
const auto& packing = desc.packState;
uint32_t rowStride;
uint32_t bytesNeeded;
if (!ValidatePackSize(width, height, bytesPerPixel, &rowStride, &bytesNeeded))
if (!ValidatePackSize(*this, packing, size, bytesPerPixel, &rowStride,
&bytesNeeded))
return;
if (bytesNeeded > availBytes) {
@ -1129,8 +1119,8 @@ void WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth,
int32_t readX, readY;
int32_t writeX, writeY;
int32_t rwWidth, rwHeight;
if (!Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth) ||
!Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight)) {
if (!Intersect(srcWidth, srcOffset.x, size.x, &readX, &writeX, &rwWidth) ||
!Intersect(srcHeight, srcOffset.y, size.y, &readY, &writeY, &rwHeight)) {
ErrorOutOfMemory("Bad subrect selection.");
return;
}
@ -1138,15 +1128,23 @@ void WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth,
////////////////
// Now that the errors are out of the way, on to actually reading!
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, packing.alignment);
if (IsWebGL2()) {
gl->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, packing.rowLength);
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, packing.skipPixels);
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, packing.skipRows);
}
if (!rwWidth || !rwHeight) {
// Disjoint rects, so we're done already.
DummyReadFramebufferOperation();
return;
}
const auto rwSize = *uvec2::From(rwWidth, rwHeight);
if (uint32_t(rwWidth) == width && uint32_t(rwHeight) == height) {
DoReadPixelsAndConvert(srcFormat->format, x, y, width, height, packFormat,
packType, dest, bytesNeeded, rowStride);
if (rwSize == size) {
DoReadPixelsAndConvert(srcFormat->format, desc, dest, bytesNeeded,
rowStride);
return;
}
@ -1166,29 +1164,31 @@ void WebGLContext::ReadPixelsImpl(GLint x, GLint y, GLsizei rawWidth,
// Read only the in-bounds pixels.
if (IsWebGL2()) {
if (!mPixelStore.mPackRowLength) {
gl->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH,
mPixelStore.mPackSkipPixels + width);
if (!packing.rowLength) {
gl->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, packing.skipPixels + size.x);
}
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS,
mPixelStore.mPackSkipPixels + writeX);
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS,
mPixelStore.mPackSkipRows + writeY);
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, packing.skipPixels + writeX);
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, packing.skipRows + writeY);
DoReadPixelsAndConvert(srcFormat->format, readX, readY, rwWidth, rwHeight,
packFormat, packType, dest, bytesNeeded, rowStride);
auto desc2 = desc;
desc2.srcOffset = {readX, readY};
desc2.size = rwSize;
gl->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, mPixelStore.mPackRowLength);
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, mPixelStore.mPackSkipPixels);
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, mPixelStore.mPackSkipRows);
DoReadPixelsAndConvert(srcFormat->format, desc2, dest, bytesNeeded,
rowStride);
} else {
// I *did* say "hilariously slow".
auto desc2 = desc;
desc2.srcOffset = {readX, readY};
desc2.size = {rwSize.x, 1};
auto row = dest + writeX * bytesPerPixel;
row += writeY * rowStride;
for (uint32_t j = 0; j < uint32_t(rwHeight); j++) {
DoReadPixelsAndConvert(srcFormat->format, readX, readY + j, rwWidth, 1,
packFormat, packType, row, bytesNeeded, rowStride);
for (const auto j : IntegerRange(size.y)) {
desc2.srcOffset.y = readY + j;
DoReadPixelsAndConvert(srcFormat->format, desc2, row, bytesNeeded,
rowStride);
row += rowStride;
}
}

Просмотреть файл

@ -546,8 +546,6 @@ void WebGLContext::AssertCachedGlobalState() const {
MOZ_ASSERT(int4[0] == mViewportX && int4[1] == mViewportY &&
int4[2] == mViewportWidth && int4[3] == mViewportHeight);
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT,
mPixelStore.mPackAlignment);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT,
mPixelStore.mUnpackAlignment);
@ -562,12 +560,6 @@ void WebGLContext::AssertCachedGlobalState() const {
mPixelStore.mUnpackSkipRows);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_SKIP_PIXELS,
mPixelStore.mUnpackSkipPixels);
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ROW_LENGTH,
mPixelStore.mPackRowLength);
AssertUintParamCorrect(gl, LOCAL_GL_PACK_SKIP_ROWS,
mPixelStore.mPackSkipRows);
AssertUintParamCorrect(gl, LOCAL_GL_PACK_SKIP_PIXELS,
mPixelStore.mPackSkipPixels);
}
MOZ_ASSERT(!gl::GLContext::IsBadCallError(errorScope.GetError()));

Просмотреть файл

@ -589,10 +589,6 @@ bool WebGLContext::InitAndValidateGL(FailureReason* const out_failReason) {
mPixelStore.mUnpackSkipRows = 0;
mPixelStore.mUnpackSkipPixels = 0;
mPixelStore.mUnpackAlignment = 4;
mPixelStore.mPackRowLength = 0;
mPixelStore.mPackSkipRows = 0;
mPixelStore.mPackSkipPixels = 0;
mPixelStore.mPackAlignment = 4;
mPrimRestartTypeBytes = 0;

Просмотреть файл

@ -276,29 +276,6 @@ struct FormatInfo {
}
};
struct PackingInfo {
GLenum format;
GLenum type;
bool operator<(const PackingInfo& x) const {
if (format != x.format) return format < x.format;
return type < x.type;
}
bool operator==(const PackingInfo& x) const {
return (format == x.format && type == x.type);
}
};
struct DriverUnpackInfo {
GLenum internalFormat;
GLenum unpackFormat;
GLenum unpackType;
PackingInfo ToPacking() const { return {unpackFormat, unpackType}; }
};
//////////////////////////////////////////////////////////////////////////////////////////
const FormatInfo* GetFormat(EffectiveFormat format);

Просмотреть файл

@ -349,17 +349,13 @@ struct FloatOrInt final // For TexParameter[fi] and friends.
}
};
struct WebGLPixelStore {
struct WebGLPixelStore final {
uint32_t mUnpackImageHeight = 0;
uint32_t mUnpackSkipImages = 0;
uint32_t mUnpackRowLength = 0;
uint32_t mUnpackSkipRows = 0;
uint32_t mUnpackSkipPixels = 0;
uint32_t mUnpackAlignment = 0;
uint32_t mPackRowLength = 0;
uint32_t mPackSkipRows = 0;
uint32_t mPackSkipPixels = 0;
uint32_t mPackAlignment = 0;
GLenum mColorspaceConversion = 0;
bool mFlipY = false;
bool mPremultiplyAlpha = false;
@ -465,6 +461,43 @@ typedef avec3<uint32_t> uvec3;
namespace webgl {
struct PackingInfo final {
GLenum format = 0;
GLenum type = 0;
bool operator<(const PackingInfo& x) const {
if (format != x.format) return format < x.format;
return type < x.type;
}
bool operator==(const PackingInfo& x) const {
return (format == x.format && type == x.type);
}
};
struct DriverUnpackInfo final {
GLenum internalFormat = 0;
GLenum unpackFormat = 0;
GLenum unpackType = 0;
PackingInfo ToPacking() const { return {unpackFormat, unpackType}; }
};
struct PixelPackState final {
uint32_t alignment = 4;
uint32_t rowLength = 0;
uint32_t skipRows = 0;
uint32_t skipPixels = 0;
};
struct ReadPixelsDesc final {
ivec2 srcOffset;
uvec2 size;
PackingInfo pi = {LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE};
PixelPackState packState;
};
class ExtensionBits final {
uint64_t mBits = 0;