author | Morris Tseng <mtseng@mozilla.com> |
Thu, 21 Jan 2016 14:51:59 +0800 | |
changeset 280831 | 136001a011e82e9a9b5c9cd776f9982e4a41bf39 |
parent 280830 | 2cd90b7d3dbd3cbc4759a493da12cfbbb1364c92 |
child 280832 | d556ea474a82901a827c0d9654ed961f8d835ca7 |
push id | 70605 |
push user | mtseng@mozilla.com |
push date | Thu, 21 Jan 2016 06:53:07 +0000 |
treeherder | mozilla-inbound@d556ea474a82 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jgilbert |
bugs | 1238865 |
milestone | 46.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -1311,25 +1311,60 @@ WebGLContext::DoReadPixelsAndConvert(GLi return true; } gl->fReadPixels(x, y, width, height, destFormat, destType, destBytes); return true; } static bool -IsFormatAndTypeUnpackable(GLenum format, GLenum type) +IsFormatAndTypeUnpackable(GLenum format, GLenum type, bool isWebGL2) { switch (type) { case LOCAL_GL_UNSIGNED_BYTE: + switch (format) { + case LOCAL_GL_LUMINANCE: + case LOCAL_GL_LUMINANCE_ALPHA: + if (!isWebGL2) + return false; + case LOCAL_GL_ALPHA: + case LOCAL_GL_RED: + case LOCAL_GL_RED_INTEGER: + case LOCAL_GL_RG: + case LOCAL_GL_RG_INTEGER: + case LOCAL_GL_RGB: + case LOCAL_GL_RGB_INTEGER: + case LOCAL_GL_RGBA: + case LOCAL_GL_RGBA_INTEGER: + return true; + default: + return false; + } + + case LOCAL_GL_BYTE: + switch (format) { + case LOCAL_GL_RED: + case LOCAL_GL_RED_INTEGER: + case LOCAL_GL_RG: + case LOCAL_GL_RG_INTEGER: + case LOCAL_GL_RGB: + case LOCAL_GL_RGB_INTEGER: + case LOCAL_GL_RGBA: + case LOCAL_GL_RGBA_INTEGER: + return true; + default: + return false; + } + case LOCAL_GL_FLOAT: case LOCAL_GL_HALF_FLOAT: case LOCAL_GL_HALF_FLOAT_OES: switch (format) { - case LOCAL_GL_ALPHA: + case LOCAL_GL_RED: + case LOCAL_GL_RG: case LOCAL_GL_RGB: case LOCAL_GL_RGBA: return true; default: return false; } case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4: @@ -1343,24 +1378,38 @@ IsFormatAndTypeUnpackable(GLenum format, return false; } } static bool IsIntegerFormatAndTypeUnpackable(GLenum format, GLenum type) { switch (type) { + case LOCAL_GL_UNSIGNED_SHORT: + case LOCAL_GL_SHORT: case LOCAL_GL_UNSIGNED_INT: case LOCAL_GL_INT: switch (format) { + case LOCAL_GL_RED_INTEGER: + case LOCAL_GL_RG_INTEGER: + case LOCAL_GL_RGB_INTEGER: case LOCAL_GL_RGBA_INTEGER: return true; default: return false; } + + case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV: + return format == LOCAL_GL_RGBA || + format == LOCAL_GL_RGBA_INTEGER; + + case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV: + case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV: + return format == LOCAL_GL_RGB; + default: return false; } } CheckedUint32 WebGLContext::GetPackSize(uint32_t width, uint32_t height, uint8_t bytesPerPixel, @@ -1413,62 +1462,90 @@ WebGLContext::ReadPixels(GLint x, GLint if (width < 0 || height < 0) return ErrorInvalidValue("readPixels: negative size passed"); if (pixels.IsNull()) return ErrorInvalidValue("readPixels: null destination buffer"); if (!(IsWebGL2() && IsIntegerFormatAndTypeUnpackable(format, type)) && - !IsFormatAndTypeUnpackable(format, type)) { + !IsFormatAndTypeUnpackable(format, type, IsWebGL2())) { return ErrorInvalidEnum("readPixels: Bad format or type."); } int channels = 0; // Check the format param switch (format) { case LOCAL_GL_ALPHA: + case LOCAL_GL_LUMINANCE: + case LOCAL_GL_RED: + case LOCAL_GL_RED_INTEGER: channels = 1; break; + case LOCAL_GL_LUMINANCE_ALPHA: + case LOCAL_GL_RG: + case LOCAL_GL_RG_INTEGER: + channels = 2; + break; case LOCAL_GL_RGB: + case LOCAL_GL_RGB_INTEGER: channels = 3; break; case LOCAL_GL_RGBA: case LOCAL_GL_RGBA_INTEGER: channels = 4; break; default: MOZ_CRASH("bad `format`"); } // Check the type param int bytesPerPixel; int requiredDataType; switch (type) { + case LOCAL_GL_BYTE: + bytesPerPixel = 1*channels; + requiredDataType = js::Scalar::Int8; + break; + case LOCAL_GL_UNSIGNED_BYTE: bytesPerPixel = 1*channels; requiredDataType = js::Scalar::Uint8; break; + case LOCAL_GL_SHORT: + bytesPerPixel = 2*channels; + requiredDataType = js::Scalar::Int16; + break; + + case LOCAL_GL_UNSIGNED_SHORT: case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4: case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1: case LOCAL_GL_UNSIGNED_SHORT_5_6_5: bytesPerPixel = 2; requiredDataType = js::Scalar::Uint16; break; + case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV: + case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV: + case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV: + case LOCAL_GL_UNSIGNED_INT_24_8: + bytesPerPixel = 4; + requiredDataType = js::Scalar::Uint32; + break; + case LOCAL_GL_UNSIGNED_INT: - bytesPerPixel = 4; + bytesPerPixel = 4*channels; requiredDataType = js::Scalar::Uint32; break; case LOCAL_GL_INT: - bytesPerPixel = 4; + bytesPerPixel = 4*channels; requiredDataType = js::Scalar::Int32; break; case LOCAL_GL_FLOAT: bytesPerPixel = 4*channels; requiredDataType = js::Scalar::Float32; break; @@ -1519,40 +1596,65 @@ WebGLContext::ReadPixels(GLint x, GLint MakeContextCurrent(); const webgl::FormatUsageInfo* srcFormat; uint32_t srcWidth; uint32_t srcHeight; if (!ValidateCurFBForRead("readPixels", &srcFormat, &srcWidth, &srcHeight)) return; + // Check the format and type params to assure they are an acceptable pair (as per spec) auto srcType = srcFormat->format->componentType; - const bool isSrcTypeFloat = (srcType == webgl::ComponentType::Float); - - // Check the format and type params to assure they are an acceptable pair (as per spec) - - const GLenum mainReadFormat = LOCAL_GL_RGBA; - const GLenum mainReadType = isSrcTypeFloat ? LOCAL_GL_FLOAT - : LOCAL_GL_UNSIGNED_BYTE; + GLenum mainReadFormat; + GLenum mainReadType; + switch (srcType) { + case webgl::ComponentType::Float: + mainReadFormat = LOCAL_GL_RGBA; + mainReadType = LOCAL_GL_FLOAT; + break; + case webgl::ComponentType::UInt: + mainReadFormat = LOCAL_GL_RGBA_INTEGER; + mainReadType = LOCAL_GL_UNSIGNED_INT; + break; + case webgl::ComponentType::Int: + mainReadFormat = LOCAL_GL_RGBA_INTEGER; + mainReadType = LOCAL_GL_INT; + break; + default: + mainReadFormat = LOCAL_GL_RGBA; + mainReadType = LOCAL_GL_UNSIGNED_BYTE; + break; + } GLenum auxReadFormat = mainReadFormat; GLenum auxReadType = mainReadType; // OpenGL ES 2.0 $4.3.1 - IMPLEMENTATION_COLOR_READ_{TYPE/FORMAT} is a valid // combination for glReadPixels(). if (gl->IsSupported(gl::GLFeature::ES2_compatibility)) { gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, reinterpret_cast<GLint*>(&auxReadFormat)); gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, reinterpret_cast<GLint*>(&auxReadType)); } const bool mainMatches = (format == mainReadFormat && type == mainReadType); const bool auxMatches = (format == auxReadFormat && type == auxReadType); - const bool isValid = mainMatches || auxMatches; + bool isValid = mainMatches || auxMatches; + + // OpenGL ES 3.0.4 p194 - When the internal format of the rendering surface is + // RGB10_A2, a third combination of format RGBA and type UNSIGNED_INT_2_10_10_10_REV + // is accepted. + if (srcFormat->format->effectiveFormat == webgl::EffectiveFormat::RGB10_A2 && + format == LOCAL_GL_RGBA && + type == LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV) + { + isValid = true; + } + if (!isValid) return ErrorInvalidOperation("readPixels: Invalid format/type pair"); // Now that the errors are out of the way, on to actually reading! uint32_t readX, readY; uint32_t writeX, writeY; uint32_t rwWidth, rwHeight;