Index: Source/modules/webgl/WebGLRenderingContextBase.cpp |
diff --git a/Source/modules/webgl/WebGLRenderingContextBase.cpp b/Source/modules/webgl/WebGLRenderingContextBase.cpp |
index 53aaea0151620316a369e2c80916623f0b6df6ab..e7ae2706065aa6304a0e718e6597a6d1cdcdab62 100644 |
--- a/Source/modules/webgl/WebGLRenderingContextBase.cpp |
+++ b/Source/modules/webgl/WebGLRenderingContextBase.cpp |
@@ -967,6 +967,7 @@ void WebGLRenderingContextBase::initializeNewContext() |
m_unpackPremultiplyAlpha = false; |
m_unpackColorspaceConversion = GC3D_BROWSER_DEFAULT_WEBGL; |
m_boundArrayBuffer = nullptr; |
+ m_boundPixelPackBuffer = nullptr; |
m_currentProgram = nullptr; |
m_framebufferBinding = nullptr; |
m_renderbufferBinding = nullptr; |
@@ -1098,6 +1099,7 @@ WebGLRenderingContextBase::~WebGLRenderingContextBase() |
// Remove all references to WebGLObjects so if they are the last reference |
// they will be freed before the last context is removed from the context group. |
m_boundArrayBuffer = nullptr; |
+ m_boundPixelPackBuffer = nullptr; |
m_defaultVertexArrayObject = nullptr; |
m_boundVertexArrayObject = nullptr; |
m_vertexAttrib0Buffer = nullptr; |
@@ -3729,6 +3731,31 @@ DOMArrayBufferView::ViewType WebGLRenderingContextBase::readPixelsExpectedArrayB |
} |
} |
+bool WebGLRenderingContextBase::validateReadPixelsFuncParameters(GLsizei width, GLsizei height, GLenum format, GLenum type, unsigned domArrayBufferLength, WebGLFramebuffer*& readFramebufferBinding) |
+{ |
+ if (!validateReadPixelsFormatAndType(format, type)) |
+ return false; |
+ GLenum readBufferInternalFormat = 0, readBufferType = 0; |
+ if (!validateReadBufferAndGetInfo("readPixels", readFramebufferBinding, &readBufferInternalFormat, &readBufferType)) |
+ return false; |
+ if (!validateReadPixelsFormatTypeCombination(format, type, readBufferInternalFormat, readBufferType)) |
+ return false; |
+ |
+ // Calculate array size, taking into consideration of PACK_ALIGNMENT. |
+ unsigned totalBytesRequired = 0; |
+ unsigned padding = 0; |
+ GLenum error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); |
+ if (error != GL_NO_ERROR) { |
+ synthesizeGLError(error, "readPixels", "invalid dimensions"); |
+ return false; |
+ } |
+ if (domArrayBufferLength && domArrayBufferLength < totalBytesRequired) { |
+ synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions"); |
+ return false; |
+ } |
+ return true; |
+} |
+ |
void WebGLRenderingContextBase::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, DOMArrayBufferView* pixels) |
{ |
if (isContextLost()) |
@@ -3736,19 +3763,15 @@ void WebGLRenderingContextBase::readPixels(GLint x, GLint y, GLsizei width, GLsi |
// Due to WebGL's same-origin restrictions, it is not possible to |
// taint the origin using the WebGL API. |
ASSERT(canvas()->originClean()); |
+ if (isWebGL2OrHigher() && m_boundPixelPackBuffer.get()) { |
+ synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "PIXEL_PACK buffer should not bound"); |
+ return; |
+ } |
// Validate input parameters. |
if (!pixels) { |
synthesizeGLError(GL_INVALID_VALUE, "readPixels", "no destination ArrayBufferView"); |
return; |
} |
- if (!validateReadPixelsFormatAndType(format, type)) |
- return; |
- GLenum readBufferInternalFormat = 0, readBufferType = 0; |
- WebGLFramebuffer* readFramebufferBinding = nullptr; |
- if (!validateReadBufferAndGetInfo("readPixels", readFramebufferBinding, &readBufferInternalFormat, &readBufferType)) |
- return; |
- if (!validateReadPixelsFormatTypeCombination(format, type, readBufferInternalFormat, readBufferType)) |
- return; |
DOMArrayBufferView::ViewType expectedViewType = readPixelsExpectedArrayBufferViewType(type); |
// Validate array type against pixel type. |
@@ -3757,18 +3780,9 @@ void WebGLRenderingContextBase::readPixels(GLint x, GLint y, GLsizei width, GLsi |
return; |
} |
- // Calculate array size, taking into consideration of PACK_ALIGNMENT. |
- unsigned totalBytesRequired = 0; |
- unsigned padding = 0; |
- GLenum error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); |
- if (error != GL_NO_ERROR) { |
- synthesizeGLError(error, "readPixels", "invalid dimensions"); |
- return; |
- } |
- if (pixels->byteLength() < totalBytesRequired) { |
- synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions"); |
+ WebGLFramebuffer* readFramebufferBinding = nullptr; |
+ if (!validateReadPixelsFuncParameters(format, type, width, height, pixels->byteLength(), readFramebufferBinding)) |
return; |
- } |
clearIfComposited(); |
void* data = pixels->baseAddress(); |
@@ -3779,6 +3793,29 @@ void WebGLRenderingContextBase::readPixels(GLint x, GLint y, GLsizei width, GLsi |
} |
} |
+void WebGLRenderingContextBase::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, long long offset) |
+{ |
+ if (isContextLost() || !isWebGL2OrHigher()) |
+ return; |
+ // Due to WebGL's same-origin restrictions, it is not possible to |
+ // taint the origin using the WebGL API. |
+ ASSERT(canvas()->originClean()); |
+ if (!m_boundPixelPackBuffer.get()) { |
+ synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "no PIXEL_PACK buffer bound"); |
+ return; |
+ } |
+ |
+ WebGLFramebuffer* readFramebufferBinding = nullptr; |
+ if (!validateReadPixelsFuncParameters(format, type, width, height, 0, readFramebufferBinding)) |
+ return; |
+ |
+ clearIfComposited(); |
+ { |
+ ScopedDrawingBufferBinder binder(drawingBuffer(), readFramebufferBinding); |
+ webContext()->readPixels(x, y, width, height, format, type, (void*)offset); |
+ } |
+} |
+ |
void WebGLRenderingContextBase::renderbufferStorageImpl( |
GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, |
const char* functionName) |
@@ -6588,6 +6625,7 @@ DEFINE_TRACE(WebGLRenderingContextBase) |
visitor->trace(m_contextLostCallbackAdapter); |
visitor->trace(m_errorMessageCallbackAdapter); |
visitor->trace(m_boundArrayBuffer); |
+ visitor->trace(m_boundPixelPackBuffer); |
visitor->trace(m_defaultVertexArrayObject); |
visitor->trace(m_boundVertexArrayObject); |
visitor->trace(m_vertexAttrib0Buffer); |