[WebGL2] Teach WebGLRenderingContextBase about new texture internal formats
authormmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Nov 2016 02:42:32 +0000 (02:42 +0000)
committermmaxfield@apple.com <mmaxfield@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Nov 2016 02:42:32 +0000 (02:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164525

Reviewed by Dean Jackson.

Source/WebCore:

Test: fast/canvas/webgl/webgl2-texture-upload-enums.html

This patch migrates the existing WebGL calls texImage2D(), texSubImage2D(),
and readPixels() to understand the new WebGL 2 texture types. In WebGL1, the
format and the internalFormat were required to be the same, and we had this
assumption baked into many places in these functions. In WebGL 2, those two
values are often different, which means I had to fix all of these assumptions
in our code. Also, rather than have two completely separate parallel
implementations of these functions, a more forward-looking approach is to
have one implementation which has a few checks to isWebGL1() in strategic
places. (This way, bugs only have to be fixed in a single place). Therefore,
this patch deletes the WebGL 2 versions of these functions.

* html/canvas/WebGL2RenderingContext.cpp: These functions are moved to
WebGLRenderingContextBase.
(WebCore::WebGL2RenderingContext::isIntegerFormat):
(WebCore::WebGL2RenderingContext::copyTexImage2D): Deleted.
(WebCore::WebGL2RenderingContext::texSubImage2DBase): Deleted.
(WebCore::WebGL2RenderingContext::texSubImage2DImpl): Deleted.
(WebCore::WebGL2RenderingContext::texSubImage2D): Deleted.
(WebCore::WebGL2RenderingContext::validateTexFuncParameters): Deleted.
(WebCore::WebGL2RenderingContext::validateTexFuncFormatAndType): Deleted.
(WebCore::WebGL2RenderingContext::validateTexFuncData): Deleted.
* html/canvas/WebGL2RenderingContext.h: Moved function implementations to
WebGLRenderingContextBase.
* html/canvas/WebGLRenderingContext.cpp: Ditto.
(WebCore::WebGLRenderingContext::copyTexImage2D): Deleted.
(WebCore::WebGLRenderingContext::texSubImage2DBase): Deleted.
(WebCore::WebGLRenderingContext::texSubImage2DImpl): Deleted.
(WebCore::WebGLRenderingContext::texSubImage2D): Deleted.
(WebCore::WebGLRenderingContext::validateTexFuncParameters): Deleted.
(WebCore::WebGLRenderingContext::validateTexFuncFormatAndType): Deleted.
(WebCore::WebGLRenderingContext::validateTexFuncData): Deleted.
* html/canvas/WebGLRenderingContext.h: Moved function implementations to
WebGLRenderingContextBase.
* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::validateSettableTexInternalFormat):
Teach about new depth texture formats.
(WebCore::WebGLRenderingContextBase::copyTexSubImage2D): Rename
"internalformat" to "internalFormat". Teach about the distinction between
format and internalFormat. When pre-filling textures with 0s to work around
buggy drivers, we need a new way of knowing which format/type arguments to
pass to texSubImage2D() which are compatible with the texture's internal
format. The implementation of this function was added to GraphicsContext3D
and is called here.
(WebCore::WebGLRenderingContextBase::generateMipmap): Teach about the
distinction between format and internalFormat.
(WebCore::internalFormatTheme): This is used so readPixels() knows what
kind of format/type arguments are compatible with the texture's internal
format.
(WebCore::numberOfComponentsForFormat): Ditto.
(WebCore::numberOfComponentsForInternalFormat): Ditto.
(WebCore::WebGLRenderingContextBase::readPixels): Many more format/type
combinations are required in order to test the various new kinds of
textures.
(WebCore::WebGLRenderingContextBase::texImage2DBase): Rename internalformat
to internalFormat, and teach about the distinction between format and
internalFormat.
(WebCore::WebGLRenderingContextBase::validateTexFunc): Ditto.
(WebCore::WebGLRenderingContextBase::texImage2D): Ditto.
(WebCore::WebGLRenderingContextBase::texSubImage2DImpl): Moved from
WebGLRenderingContext.
(WebCore::WebGLRenderingContextBase::texSubImage2D): Ditto.
(WebCore::WebGLRenderingContextBase::validateArrayBufferType): Ditto.
(WebCore::WebGLRenderingContextBase::validateTexFuncData): Ditto.
(WebCore::WebGLRenderingContextBase::validateTexFuncParameters): Ditto.
(WebCore::WebGLRenderingContextBase::validateTexFuncFormatAndType): Ditto.
This is the main function where the new internalFormats are dealt with.
The OpenGL ES spec lists a table of all the internalFormats and all their
compatible format/type values. This table is entered into this function to
check that the combinations are correct.
(WebCore::WebGLRenderingContextBase::texSubImage2DBase): Moved from
WebGLRenderingContext.
(WebCore::WebGLRenderingContextBase::copyTexImage2D): Ditto.
(WebCore::WebGLRenderingContextBase::validateSettableTexFormat): Deleted.
* html/canvas/WebGLRenderingContextBase.h: No longer overrides virtual
functions.
* platform/graphics/GraphicsContext3D.cpp:
(WebCore::GraphicsContext3D::computeFormatAndTypeParameters): Because
this is inside GraphicsContext3D, it doesn't need any isWebGL1() checks.
Teach about new enums.
(WebCore::GraphicsContext3D::possibleFormatAndTypeForInternalFormat):
Ditto.
(WebCore::GraphicsContext3D::packImageData):
(WebCore::GraphicsContext3D::packPixels): It is possible to try to
copy data from a video into one of these new formats. Currently, we
implement this by swizzling on the CPU. Rather than implementing all the
swizzling functions in this patch (which would make this patch much
larger), simply bail in this case. We will implement this later.
(WebCore::GraphicsContext3D::getClearBitsByFormat): Update.
* platform/graphics/GraphicsContext3D.h:
(WebCore::GraphicsContext3D::hasAlpha): Ditto.
(WebCore::GraphicsContext3D::hasColor): Ditto.

LayoutTests:

Test texture types without drawing. Instead, attach a texture to a framebuffer and
use readPixels() to make sure the texture retains its data.

* fast/canvas/webgl/webgl2-texture-upload-enums-expected.txt: Added.
* fast/canvas/webgl/webgl2-texture-upload-enums.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208724 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/canvas/webgl/webgl2-texture-upload-enums-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/webgl/webgl2-texture-upload-enums.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/canvas/WebGL2RenderingContext.cpp
Source/WebCore/html/canvas/WebGL2RenderingContext.h
Source/WebCore/html/canvas/WebGLRenderingContext.cpp
Source/WebCore/html/canvas/WebGLRenderingContext.h
Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp
Source/WebCore/html/canvas/WebGLRenderingContextBase.h
Source/WebCore/platform/graphics/GraphicsContext3D.cpp
Source/WebCore/platform/graphics/GraphicsContext3D.h

index 0197c73..729725b 100644 (file)
@@ -1,3 +1,16 @@
+2016-11-14  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        [WebGL2] Teach WebGLRenderingContextBase about new texture internal formats
+        https://bugs.webkit.org/show_bug.cgi?id=164525
+
+        Reviewed by Dean Jackson.
+
+        Test texture types without drawing. Instead, attach a texture to a framebuffer and
+        use readPixels() to make sure the texture retains its data.
+
+        * fast/canvas/webgl/webgl2-texture-upload-enums-expected.txt: Added.
+        * fast/canvas/webgl/webgl2-texture-upload-enums.html: Added.
+
 2016-11-14  Ryosuke Niwa  <rniwa@webkit.org>
 
         document.createElementNS doesn't construct a custom element
 2016-11-14  Ryosuke Niwa  <rniwa@webkit.org>
 
         document.createElementNS doesn't construct a custom element
diff --git a/LayoutTests/fast/canvas/webgl/webgl2-texture-upload-enums-expected.txt b/LayoutTests/fast/canvas/webgl/webgl2-texture-upload-enums-expected.txt
new file mode 100644 (file)
index 0000000..591eeca
--- /dev/null
@@ -0,0 +1,2072 @@
+Test that glTexImage2D and glTexSubImage2D accept new WebGL 2 enum values
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.checkFramebufferStatus(gl.FRAMEBUFFER) is gl.FRAMEBUFFER_COMPLETE
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS receiver[index] is expected
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS arrayBuffer[i] is receiver[i]
+PASS gl.getError() is gl.NO_ERROR
+PASS gl.getError() is gl.NO_ERROR
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/canvas/webgl/webgl2-texture-upload-enums.html b/LayoutTests/fast/canvas/webgl/webgl2-texture-upload-enums.html
new file mode 100644 (file)
index 0000000..b03bbbf
--- /dev/null
@@ -0,0 +1,296 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="40" height="40"></canvas>
+<script>
+description("Test that glTexImage2D and glTexSubImage2D accept new WebGL 2 enum values");
+
+if (window.internals)
+       internals.setWebGL2Enabled(true);
+
+var canvas = document.getElementById("canvas");
+var width = canvas.width;
+var height = canvas.height;
+var gl = canvas.getContext("webgl2");
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+var texture = gl.createTexture();
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.bindTexture(gl.TEXTURE_2D, texture);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+var arrayBuffer = new Uint8Array(width * height * 1);
+var count = 0;
+for (var i = 0; i < height; ++i) {
+       for (var j = 0; j < width; ++j) {
+               arrayBuffer[(width * i + j) * 1 + 0] = count++;
+       }
+}
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, width, height, 0, gl.RED, gl.UNSIGNED_BYTE, arrayBuffer);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+var framebuffer = gl.createFramebuffer();
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
+
+
+var count;
+var offset = 0;
+var index;
+var expected;
+function test(uploadArrayFunction, downloadArrayFunction, components, internalFormat, format, uploadType, downloadType) {
+       var width = 4;
+       var height = 4;
+       arrayBuffer = new uploadArrayFunction(2 * width * height * components);
+       var count = 0;
+       for (var i = 0; i < height; ++i) {
+               for (var j = 0; j < width; ++j) {
+                       for (var k = 0; k < components; ++k) {
+                               arrayBuffer[(width * i + j) * components + k] = offset + count++;
+                       }
+               }
+       }
+       gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, width, height, 0, format, uploadType, arrayBuffer);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+       gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, uploadType, arrayBuffer);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+       receiver = new downloadArrayFunction(2 * width * height * components);
+       gl.readPixels(0, 0, width, height, format, downloadType, receiver);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+       count = 0;
+       for (var i = 0; i < height; ++i) {
+               for (var j = 0; j < width; ++j) {
+                       for (var k = 0; k < components; ++k) {
+                               expected = offset + count++;
+                               index = (width * i + j) * components + k;
+                               shouldBe("receiver[index]", "expected");
+                       }
+               }
+       }
+
+       if (offset == 0)
+               offset = 50;
+       else
+               offset = 0;
+}
+
+// FIXME: Read from the textures in shaders
+
+test(Uint8Array, Uint8Array, 3, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+test(Uint8Array, Uint8Array, 4, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+//test(Uint8Array, Uint8Array, 2, gl.LUMINANCE_ALPHA, gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+//test(Uint8Array, Uint8Array, 1, gl.LUMINANCE, gl.LUMINANCE, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+//test(Uint8Array, Uint8Array, 1, gl.ALPHA, gl.ALPHA, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+
+test(Uint8Array, Uint8Array, 1, gl.R8, gl.RED, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+test(Int8Array, Int8Array, 1, gl.R8_SNORM, gl.RED, gl.BYTE, gl.BYTE);
+test(Float32Array, Float32Array, 1, gl.R16F, gl.RED, gl.FLOAT, gl.FLOAT);
+test(Float32Array, Float32Array, 1, gl.R32F, gl.RED, gl.FLOAT, gl.FLOAT);
+test(Uint8Array, Uint32Array, 1, gl.R8UI, gl.RED_INTEGER, gl.UNSIGNED_BYTE, gl.UNSIGNED_INT);
+test(Int8Array, Int32Array, 1, gl.R8I, gl.RED_INTEGER, gl.BYTE, gl.INT);
+test(Uint16Array, Uint32Array, 1, gl.R16UI, gl.RED_INTEGER, gl.UNSIGNED_SHORT, gl.UNSIGNED_INT);
+test(Int16Array, Int32Array, 1, gl.R16I, gl.RED_INTEGER, gl.SHORT, gl.INT);
+test(Uint32Array, Uint32Array, 1, gl.R32UI, gl.RED_INTEGER, gl.UNSIGNED_INT, gl.UNSIGNED_INT);
+test(Int32Array, Int32Array, 1, gl.R32I, gl.RED_INTEGER, gl.INT, gl.INT);
+
+test(Uint8Array, Uint8Array, 2, gl.RG8, gl.RG, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+test(Int8Array, Int8Array, 2, gl.RG8_SNORM, gl.RG, gl.BYTE, gl.BYTE);
+test(Float32Array, Float32Array, 2, gl.RG16F, gl.RG, gl.FLOAT, gl.FLOAT);
+test(Float32Array, Float32Array, 2, gl.RG32F, gl.RG, gl.FLOAT, gl.FLOAT);
+test(Uint8Array, Uint32Array, 2, gl.RG8UI, gl.RG_INTEGER, gl.UNSIGNED_BYTE, gl.UNSIGNED_INT);
+test(Int8Array, Int32Array, 2, gl.RG8I, gl.RG_INTEGER, gl.BYTE, gl.INT);
+test(Uint16Array, Uint32Array, 2, gl.RG16UI, gl.RG_INTEGER, gl.UNSIGNED_SHORT, gl.UNSIGNED_INT);
+test(Int16Array, Int32Array, 2, gl.RG16I, gl.RG_INTEGER, gl.SHORT, gl.INT);
+test(Uint32Array, Uint32Array, 2, gl.RG32UI, gl.RG_INTEGER, gl.UNSIGNED_INT, gl.UNSIGNED_INT);
+test(Int32Array, Int32Array, 2, gl.RG32I, gl.RG_INTEGER, gl.INT, gl.INT);
+
+test(Uint8Array, Uint8Array, 3, gl.RGB8, gl.RGB, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+test(Uint8Array, Uint8Array, 3, gl.SRGB8, gl.RGB, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+test(Int8Array, Int8Array, 3, gl.RGB8_SNORM, gl.RGB, gl.BYTE, gl.BYTE);
+test(Float32Array, Float32Array, 3, gl.RGB16F, gl.RGB, gl.FLOAT, gl.FLOAT);
+test(Float32Array, Float32Array, 3, gl.RGB32F, gl.RGB, gl.FLOAT, gl.FLOAT);
+test(Uint8Array, Uint32Array, 3, gl.RGB8UI, gl.RGB_INTEGER, gl.UNSIGNED_BYTE, gl.UNSIGNED_INT);
+test(Int8Array, Int32Array, 3, gl.RGB8I, gl.RGB_INTEGER, gl.BYTE, gl.INT);
+test(Uint16Array, Uint32Array, 3, gl.RGB16UI, gl.RGB_INTEGER, gl.UNSIGNED_SHORT, gl.UNSIGNED_INT);
+test(Int16Array, Int32Array, 3, gl.RGB16I, gl.RGB_INTEGER, gl.SHORT, gl.INT);
+test(Uint32Array, Uint32Array, 3, gl.RGB32UI, gl.RGB_INTEGER, gl.UNSIGNED_INT, gl.UNSIGNED_INT);
+test(Int32Array, Int32Array, 3, gl.RGB32I, gl.RGB_INTEGER, gl.INT, gl.INT);
+
+test(Uint8Array, Uint8Array, 4, gl.RGBA8, gl.RGBA, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+test(Uint8Array, Uint8Array, 3, gl.SRGB8_ALPHA8, gl.RGBA, gl.UNSIGNED_BYTE, gl.UNSIGNED_BYTE);
+test(Int8Array, Int8Array, 4, gl.RGBA8_SNORM, gl.RGBA, gl.BYTE, gl.BYTE);
+test(Float32Array, Float32Array, 4, gl.RGBA16F, gl.RGBA, gl.FLOAT, gl.FLOAT);
+test(Float32Array, Float32Array, 4, gl.RGBA32F, gl.RGBA, gl.FLOAT, gl.FLOAT);
+test(Uint8Array, Uint32Array, 4, gl.RGBA8UI, gl.RGBA_INTEGER, gl.UNSIGNED_BYTE, gl.UNSIGNED_INT);
+test(Int8Array, Int32Array, 4, gl.RGBA8I, gl.RGBA_INTEGER, gl.BYTE, gl.INT);
+test(Uint16Array, Uint32Array, 4, gl.RGBA16UI, gl.RGBA_INTEGER, gl.UNSIGNED_SHORT, gl.UNSIGNED_INT);
+test(Int16Array, Int32Array, 4, gl.RGBA16I, gl.RGBA_INTEGER, gl.SHORT, gl.INT);
+test(Uint32Array, Uint32Array, 4, gl.RGBA32UI, gl.RGBA_INTEGER, gl.UNSIGNED_INT, gl.UNSIGNED_INT);
+test(Int32Array, Int32Array, 4, gl.RGBA32I, gl.RGBA_INTEGER, gl.INT, gl.INT);
+
+var i;
+function test565() {
+       var width = 4;
+       var height = 4;
+       arrayBuffer = new Uint16Array(width * height);
+       for (var i = 0; i < height; ++i) {
+               for (var j = 0; j < width; ++j) {
+                       arrayBuffer[width * i + j] = (i << 11) | ((i + j) << 5) | j;
+               }
+       }
+       gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB565, width, height, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, arrayBuffer);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+       receiver = new Uint16Array(width * height);
+       gl.readPixels(0, 0, width, height, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, receiver);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+
+       for (i = 0; i < width * height; ++i) {
+               shouldBe("arrayBuffer[i]", "receiver[i]");
+       }
+}
+
+function test5551() {
+       var width = 4;
+       var height = 4;
+       arrayBuffer = new Uint16Array(width * height);
+       for (var i = 0; i < height; ++i) {
+               for (var j = 0; j < width; ++j) {
+                       arrayBuffer[width * i + j] = (i << 11) | ((i + j) << 6) | (j << 1);
+               }
+       }
+       gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB5_A1, width, height, 0, gl.RGBA, gl.UNSIGNED_SHORT_5_5_5_1, arrayBuffer);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+       receiver = new Uint16Array(width * height);
+       gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_SHORT_5_5_5_1, receiver);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+
+       for (i = 0; i < width * height; ++i) {
+               shouldBe("arrayBuffer[i]", "receiver[i]");
+       }
+}
+
+function test4444() {
+       var width = 4;
+       var height = 4;
+       arrayBuffer = new Uint16Array(width * height);
+       for (var i = 0; i < height; ++i) {
+               for (var j = 0; j < width; ++j) {
+                       arrayBuffer[width * i + j] = (i << 12) | ((i + j) << 8) | (j << 4);
+               }
+       }
+       gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA4, width, height, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, arrayBuffer);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+       receiver = new Uint16Array(width * height);
+       gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, receiver);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+
+       for (i = 0; i < width * height; ++i) {
+               shouldBe("arrayBuffer[i]", "receiver[i]");
+       }
+}
+
+function test9995() {
+       var width = 4;
+       var height = 4;
+       arrayBuffer = new Uint32Array(width * height);
+       for (var i = 0; i < height; ++i) {
+               for (var j = 0; j < width; ++j) {
+                       arrayBuffer[width * i + j] = (i << 23) | ((i + j) << 14) | (j << 5);
+               }
+       }
+       gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB9_E5, width, height, 0, gl.RGB, gl.UNSIGNED_INT_5_9_9_9_REV, arrayBuffer);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+}
+
+function test1010102() {
+       var width = 4;
+       var height = 4;
+       arrayBuffer = new Uint32Array(width * height);
+       for (var i = 0; i < height; ++i) {
+               for (var j = 0; j < width; ++j) {
+                       arrayBuffer[width * i + j] = (i << 22) | ((i + j) << 12) | (j << 2);
+               }
+       }
+       gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2, width, height, 0, gl.RGBA, gl.UNSIGNED_INT_2_10_10_10_REV, arrayBuffer);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+       receiver = new Uint32Array(width * height);
+       gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_INT_2_10_10_10_REV, receiver);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+
+       for (i = 0; i < width * height; ++i) {
+               shouldBe("arrayBuffer[i]", "receiver[i]");
+       }
+}
+
+function test111110() {
+       var width = 4;
+       var height = 4;
+       arrayBuffer = new Uint32Array(width * height);
+       for (var i = 0; i < height; ++i) {
+               for (var j = 0; j < width; ++j) {
+                       arrayBuffer[width * i + j] = (i << 21) | ((i + j) << 10) | j;
+               }
+       }
+       gl.texImage2D(gl.TEXTURE_2D, 0, gl.R11F_G11F_B10F, width, height, 0, gl.RGB, gl.UNSIGNED_INT_10F_11F_11F_REV, arrayBuffer);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+       receiver = new Uint32Array(width * height);
+       gl.readPixels(0, 0, width, height, gl.RGB, gl.UNSIGNED_INT_10F_11F_11F_REV, receiver);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+
+       for (i = 0; i < width * height; ++i) {
+               shouldBe("arrayBuffer[i]", "receiver[i]");
+       }
+}
+
+function test1010102UI() {
+       var width = 4;
+       var height = 4;
+       arrayBuffer = new Uint32Array(width * height);
+       for (var i = 0; i < height; ++i) {
+               for (var j = 0; j < width; ++j) {
+                       arrayBuffer[width * i + j] = (i << 22) | ((i + j) << 12) | (j << 2);
+               }
+       }
+       gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2UI, width, height, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT_2_10_10_10_REV, arrayBuffer);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+       receiver = new Uint32Array(width * height);
+       gl.readPixels(0, 0, width, height, gl.RGBA_INTEGER, gl.UNSIGNED_INT_2_10_10_10_REV, receiver);
+       shouldBe("gl.getError()", "gl.NO_ERROR");
+
+       for (i = 0; i < width * height; ++i) {
+               shouldBe("arrayBuffer[i]", "receiver[i]");
+       }
+}
+
+test565();
+test5551();
+test4444();
+test9995();
+test1010102();
+test111110();
+test1010102UI()
+
+gl.deleteFramebuffer(framebuffer);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+
+gl.deleteTexture(texture);
+shouldBe("gl.getError()", "gl.NO_ERROR");
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
\ No newline at end of file
index 7663ec9..f80c92f 100644 (file)
@@ -1,3 +1,104 @@
+2016-11-14  Myles C. Maxfield  <mmaxfield@apple.com>
+
+        [WebGL2] Teach WebGLRenderingContextBase about new texture internal formats
+        https://bugs.webkit.org/show_bug.cgi?id=164525
+
+        Reviewed by Dean Jackson.
+
+        Test: fast/canvas/webgl/webgl2-texture-upload-enums.html
+
+        This patch migrates the existing WebGL calls texImage2D(), texSubImage2D(),
+        and readPixels() to understand the new WebGL 2 texture types. In WebGL1, the
+        format and the internalFormat were required to be the same, and we had this
+        assumption baked into many places in these functions. In WebGL 2, those two
+        values are often different, which means I had to fix all of these assumptions
+        in our code. Also, rather than have two completely separate parallel
+        implementations of these functions, a more forward-looking approach is to
+        have one implementation which has a few checks to isWebGL1() in strategic
+        places. (This way, bugs only have to be fixed in a single place). Therefore,
+        this patch deletes the WebGL 2 versions of these functions.
+
+        * html/canvas/WebGL2RenderingContext.cpp: These functions are moved to
+        WebGLRenderingContextBase.
+        (WebCore::WebGL2RenderingContext::isIntegerFormat):
+        (WebCore::WebGL2RenderingContext::copyTexImage2D): Deleted.
+        (WebCore::WebGL2RenderingContext::texSubImage2DBase): Deleted.
+        (WebCore::WebGL2RenderingContext::texSubImage2DImpl): Deleted.
+        (WebCore::WebGL2RenderingContext::texSubImage2D): Deleted.
+        (WebCore::WebGL2RenderingContext::validateTexFuncParameters): Deleted.
+        (WebCore::WebGL2RenderingContext::validateTexFuncFormatAndType): Deleted.
+        (WebCore::WebGL2RenderingContext::validateTexFuncData): Deleted.
+        * html/canvas/WebGL2RenderingContext.h: Moved function implementations to
+        WebGLRenderingContextBase.
+        * html/canvas/WebGLRenderingContext.cpp: Ditto.
+        (WebCore::WebGLRenderingContext::copyTexImage2D): Deleted.
+        (WebCore::WebGLRenderingContext::texSubImage2DBase): Deleted.
+        (WebCore::WebGLRenderingContext::texSubImage2DImpl): Deleted.
+        (WebCore::WebGLRenderingContext::texSubImage2D): Deleted.
+        (WebCore::WebGLRenderingContext::validateTexFuncParameters): Deleted.
+        (WebCore::WebGLRenderingContext::validateTexFuncFormatAndType): Deleted.
+        (WebCore::WebGLRenderingContext::validateTexFuncData): Deleted.
+        * html/canvas/WebGLRenderingContext.h: Moved function implementations to
+        WebGLRenderingContextBase.
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::validateSettableTexInternalFormat):
+        Teach about new depth texture formats.
+        (WebCore::WebGLRenderingContextBase::copyTexSubImage2D): Rename
+        "internalformat" to "internalFormat". Teach about the distinction between
+        format and internalFormat. When pre-filling textures with 0s to work around
+        buggy drivers, we need a new way of knowing which format/type arguments to
+        pass to texSubImage2D() which are compatible with the texture's internal
+        format. The implementation of this function was added to GraphicsContext3D
+        and is called here.
+        (WebCore::WebGLRenderingContextBase::generateMipmap): Teach about the
+        distinction between format and internalFormat.
+        (WebCore::internalFormatTheme): This is used so readPixels() knows what
+        kind of format/type arguments are compatible with the texture's internal
+        format.
+        (WebCore::numberOfComponentsForFormat): Ditto.
+        (WebCore::numberOfComponentsForInternalFormat): Ditto.
+        (WebCore::WebGLRenderingContextBase::readPixels): Many more format/type
+        combinations are required in order to test the various new kinds of
+        textures.
+        (WebCore::WebGLRenderingContextBase::texImage2DBase): Rename internalformat
+        to internalFormat, and teach about the distinction between format and
+        internalFormat.
+        (WebCore::WebGLRenderingContextBase::validateTexFunc): Ditto.
+        (WebCore::WebGLRenderingContextBase::texImage2D): Ditto.
+        (WebCore::WebGLRenderingContextBase::texSubImage2DImpl): Moved from
+        WebGLRenderingContext.
+        (WebCore::WebGLRenderingContextBase::texSubImage2D): Ditto.
+        (WebCore::WebGLRenderingContextBase::validateArrayBufferType): Ditto.
+        (WebCore::WebGLRenderingContextBase::validateTexFuncData): Ditto.
+        (WebCore::WebGLRenderingContextBase::validateTexFuncParameters): Ditto.
+        (WebCore::WebGLRenderingContextBase::validateTexFuncFormatAndType): Ditto.
+        This is the main function where the new internalFormats are dealt with.
+        The OpenGL ES spec lists a table of all the internalFormats and all their
+        compatible format/type values. This table is entered into this function to
+        check that the combinations are correct.
+        (WebCore::WebGLRenderingContextBase::texSubImage2DBase): Moved from
+        WebGLRenderingContext.
+        (WebCore::WebGLRenderingContextBase::copyTexImage2D): Ditto.
+        (WebCore::WebGLRenderingContextBase::validateSettableTexFormat): Deleted.
+        * html/canvas/WebGLRenderingContextBase.h: No longer overrides virtual
+        functions.
+        * platform/graphics/GraphicsContext3D.cpp:
+        (WebCore::GraphicsContext3D::computeFormatAndTypeParameters): Because
+        this is inside GraphicsContext3D, it doesn't need any isWebGL1() checks.
+        Teach about new enums.
+        (WebCore::GraphicsContext3D::possibleFormatAndTypeForInternalFormat):
+        Ditto.
+        (WebCore::GraphicsContext3D::packImageData):
+        (WebCore::GraphicsContext3D::packPixels): It is possible to try to
+        copy data from a video into one of these new formats. Currently, we
+        implement this by swizzling on the CPU. Rather than implementing all the
+        swizzling functions in this patch (which would make this patch much
+        larger), simply bail in this case. We will implement this later.
+        (WebCore::GraphicsContext3D::getClearBitsByFormat): Update.
+        * platform/graphics/GraphicsContext3D.h:
+        (WebCore::GraphicsContext3D::hasAlpha): Ditto.
+        (WebCore::GraphicsContext3D::hasColor): Ditto.
+
 2016-11-14  Simon Fraser  <simon.fraser@apple.com>
 
         Scrolling when zoomed doesn't always use the correct layout viewport
 2016-11-14  Simon Fraser  <simon.fraser@apple.com>
 
         Scrolling when zoomed doesn't always use the correct layout viewport
index c54f614..ee140a8 100644 (file)
@@ -1154,731 +1154,6 @@ void WebGL2RenderingContext::hint(GC3Denum target, GC3Denum mode)
     m_context->hint(target, mode);
 }
 
     m_context->hint(target, mode);
 }
 
-void WebGL2RenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
-{
-    if (isContextLostOrPending())
-        return;
-    RefPtr<WebGLContextAttributes> attributes = getContextAttributes();
-    GC3Denum bufferFormat = attributes->alpha() ? GraphicsContext3D::RGBA : GraphicsContext3D::RGB;
-    if (!validateTexFuncParameters("copyTexImage2D", CopyTexImage, target, level, internalformat, width, height, border, bufferFormat, GraphicsContext3D::UNSIGNED_BYTE))
-        return;
-    if (!validateSettableTexFormat("copyTexImage2D", internalformat))
-        return;
-    WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
-    if (!tex)
-        return;
-    if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
-        return;
-    }
-    if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
-        return;
-    }
-    const char* reason = "framebuffer incomplete";
-    if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
-        synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
-        return;
-    }
-    clearIfComposited();
-    if (isResourceSafe())
-        m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
-    else {
-        GC3Dint clippedX, clippedY;
-        GC3Dsizei clippedWidth, clippedHeight;
-        if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
-            m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
-                internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
-            if (clippedWidth > 0 && clippedHeight > 0) {
-                m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
-                    clippedX, clippedY, clippedWidth, clippedHeight);
-            }
-        } else
-            m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
-    }
-    // FIXME: if the framebuffer is not complete, none of the below should be executed.
-    tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
-}
-
-void WebGL2RenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels)
-{
-    ASSERT(!isContextLost());
-    if (!validateTexFuncParameters("texSubImage2D", TexSubImage, target, level, internalformat, width, height, 0, format, type))
-        return;
-    ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
-    ASSERT(validateSettableTexFormat("texSubImage2D", format));
-    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
-    if (!tex) {
-        ASSERT_NOT_REACHED();
-        return;
-    }
-    ASSERT((xoffset + width) >= 0);
-    ASSERT((yoffset + height) >= 0);
-    ASSERT(tex->getWidth(target, level) >= (xoffset + width));
-    ASSERT(tex->getHeight(target, level) >= (yoffset + height));
-    ASSERT(tex->getInternalFormat(target, level) == format);
-    ASSERT(tex->getType(target, level) == type);
-    m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
-}
-
-void WebGL2RenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
-{
-    Vector<uint8_t> data;
-    GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
-    if (!imageExtractor.extractSucceeded()) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
-        return;
-    }
-    GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
-    GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
-    const void* imagePixelData = imageExtractor.imagePixelData();
-    
-    bool needConversion = true;
-    if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
-        needConversion = false;
-    else {
-        if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
-            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
-            return;
-        }
-    }
-    
-    if (m_unpackAlignment != 1)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-    
-    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
-    GC3Denum internalformat = tex->getInternalFormat(target, level);
-    texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), internalformat, format, type,  needConversion ? data.data() : imagePixelData);
-    if (m_unpackAlignment != 1)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
-}
-
-void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels)
-{
-    if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, GraphicsContext3D::NONE, format, type, pixels.get(), NullNotAllowed) || !validateTexFunc("texSubImage2D", TexSubImage, SourceArrayBufferView, target, level, GraphicsContext3D::NONE, width, height, 0, format, type, xoffset, yoffset))
-        return;
-    
-    void* data = pixels->baseAddress();
-    Vector<uint8_t> tempData;
-    bool changeUnpackAlignment = false;
-    if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
-        if (!m_context->extractTextureData(width, height, format, type,
-            m_unpackAlignment,
-            m_unpackFlipY, m_unpackPremultiplyAlpha,
-            data,
-            tempData))
-            return;
-        data = tempData.data();
-        changeUnpackAlignment = true;
-    }
-    if (changeUnpackAlignment)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
-    GC3Denum internalformat = tex->getInternalFormat(target, level);
-    texSubImage2DBase(target, level, xoffset, yoffset, width, height, internalformat, format, type, data);
-    if (changeUnpackAlignment)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
-}
-
-ExceptionOr<void> WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Optional<TexImageSource>&& source)
-{
-    if (!source) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "source is null");
-        return { };
-    }
-
-    auto visitor = WTF::makeVisitor([&](const RefPtr<ImageData>& pixels) -> ExceptionOr<void> {
-        if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, GraphicsContext3D::NONE,  pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
-            return { };
-
-        Vector<uint8_t> data;
-        bool needConversion = true;
-        // The data from ImageData is always of format RGBA8.
-        // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
-        if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
-            needConversion = false;
-        else {
-            if (!m_context->extractImageData(pixels.get(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
-                synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
-                return { };
-            }
-        }
-        if (m_unpackAlignment != 1)
-            m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-
-        WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
-        GC3Denum internalformat = tex->getInternalFormat(target, level);
-        texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), internalformat, format, type, needConversion ? data.data() : pixels->data()->data());
-        if (m_unpackAlignment != 1)
-            m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
-
-        return { };
-    }, [&](const RefPtr<HTMLImageElement>& image) -> ExceptionOr<void> {
-        if (wouldTaintOrigin(image.get()))
-            return Exception { SECURITY_ERR };
-        if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image.get()))
-            return { };
-
-        RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
-        if (!imageForRender)
-            return { };
-
-        if (imageForRender->isSVGImage())
-            imageForRender = drawImageIntoBuffer(*imageForRender, image->width(), image->height(), 1);
-
-        if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLImageElement, target, level, GraphicsContext3D::NONE, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
-            return { };
-
-        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
-        return { };
-    }, [&](const RefPtr<HTMLCanvasElement>& canvas) -> ExceptionOr<void> {
-        if (wouldTaintOrigin(canvas.get()))
-            return Exception { SECURITY_ERR };
-        if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas.get())
-            || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLCanvasElement, target, level, GraphicsContext3D::NONE, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
-            return { };
-
-        RefPtr<ImageData> imageData = canvas->getImageData();
-        if (imageData)
-            texSubImage2D(target, level, xoffset, yoffset, format, type, TexImageSource(imageData.get()));
-        else
-            texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
-        return { };
-    }, [&](const RefPtr<HTMLVideoElement>& video) -> ExceptionOr<void> {
-        if (wouldTaintOrigin(video.get()))
-            return Exception { SECURITY_ERR };
-        if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video.get())
-            || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, GraphicsContext3D::NONE, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
-            return { };
-
-        RefPtr<Image> image = videoFrameToImage(video.get(), ImageBuffer::fastCopyImageMode());
-        if (!image)
-            return { };
-        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
-        return { };
-    });
-
-    return WTF::visit(visitor, source.value());
-}
-
-bool WebGL2RenderingContext::validateTexFuncParameters(const char* functionName, TexFuncValidationFunctionType functionType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type)
-{
-    if (functionType == CopyTexImage) {
-        GC3Denum framebufferInternalFormat = 0;
-        WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(GraphicsContext3D::COLOR_ATTACHMENT0);
-        if (object->isTexture()) {
-            WebGLTexture* texture = reinterpret_cast<WebGLTexture*>(object);
-            framebufferInternalFormat = baseInternalFormatFromInternalFormat(texture->getInternalFormat(GraphicsContext3D::TEXTURE_2D, 0));
-        } else if (object->isRenderbuffer()) {
-            WebGLRenderbuffer* renderBuffer = reinterpret_cast<WebGLRenderbuffer*>(object);
-            framebufferInternalFormat = baseInternalFormatFromInternalFormat(renderBuffer->getInternalFormat());
-        }
-        
-        GC3Denum baseTextureInternalFormat = baseInternalFormatFromInternalFormat(internalformat);
-        bool validFormatCombination = true;
-        switch (framebufferInternalFormat) {
-        case GraphicsContext3D::RED:
-            if (baseTextureInternalFormat != GraphicsContext3D::LUMINANCE && baseTextureInternalFormat != GraphicsContext3D::RED)
-                validFormatCombination = false;
-            break;
-        case GraphicsContext3D::RG:
-            if (baseTextureInternalFormat != GraphicsContext3D::LUMINANCE && baseTextureInternalFormat != GraphicsContext3D::RED && baseTextureInternalFormat != GraphicsContext3D::RG)
-                validFormatCombination = false;
-            break;
-        case GraphicsContext3D::RGB:
-            if (baseTextureInternalFormat != GraphicsContext3D::LUMINANCE && baseTextureInternalFormat != GraphicsContext3D::RED && baseTextureInternalFormat != GraphicsContext3D::RG && baseTextureInternalFormat != GraphicsContext3D::RGB)
-                validFormatCombination = false;
-            break;
-        case GraphicsContext3D::RGBA:
-            if (baseTextureInternalFormat != GraphicsContext3D::ALPHA && baseTextureInternalFormat != GraphicsContext3D::LUMINANCE && baseTextureInternalFormat != GraphicsContext3D::LUMINANCE_ALPHA && baseTextureInternalFormat != GraphicsContext3D::RED && baseTextureInternalFormat != GraphicsContext3D::RG && baseTextureInternalFormat != GraphicsContext3D::RGB && baseTextureInternalFormat != GraphicsContext3D::RGBA)
-                validFormatCombination = false;
-            break;
-        case GraphicsContext3D::DEPTH_COMPONENT:
-            validFormatCombination = false;
-            break;
-        case GraphicsContext3D::DEPTH_STENCIL:
-            validFormatCombination = false;
-            break;
-        }
-        
-        if (!validFormatCombination) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "copyTexImage: invalid combination of framebuffer and texture formats");
-            return false;
-        }
-
-        bool isSRGB = (getFramebufferAttachmentParameter(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING).getInt() == GraphicsContext3D::SRGB);
-        if (isSRGB != (framebufferInternalFormat == GraphicsContext3D::SRGB8 || framebufferInternalFormat == GraphicsContext3D::SRGB8_ALPHA8)) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "framebuffer attachment color encoding and internal format do not match");
-        return false;
-        }
-    }
-    
-    // We absolutely have to validate the format and type combination.
-    // The texImage2D entry points taking HTMLImage, etc. will produce
-    // temporary data based on this combination, so it must be legal.
-    if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level) || !validateTexFuncLevel(functionName, target, level))
-        return false;
-    
-    if (width < 0 || height < 0) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
-        return false;
-    }
-    
-    GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
-    switch (target) {
-    case GraphicsContext3D::TEXTURE_2D:
-        if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
-            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
-        if (functionType != TexSubImage && width != height) {
-            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
-            return false;
-        }
-        // No need to check height here. For texImage width == height.
-        // For texSubImage that will be checked when checking yoffset + height is in range.
-        if (width > maxTextureSizeForLevel) {
-            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
-            return false;
-        }
-        break;
-    default:
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
-        return false;
-    }
-    
-    if (border) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
-        return false;
-    }
-    
-    return true;
-}
-    
-bool WebGL2RenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level)
-{
-    // Verify that a valid format has been provided.
-    switch (format) {
-    case GraphicsContext3D::ALPHA:
-    case GraphicsContext3D::LUMINANCE:
-    case GraphicsContext3D::LUMINANCE_ALPHA:
-    case GraphicsContext3D::RGB:
-    case GraphicsContext3D::RGBA:
-    case GraphicsContext3D::RGBA_INTEGER:
-    case GraphicsContext3D::RG:
-    case GraphicsContext3D::RG_INTEGER:
-    case GraphicsContext3D::RED_INTEGER:
-        break;
-    case GraphicsContext3D::DEPTH_STENCIL:
-    case GraphicsContext3D::DEPTH_COMPONENT:
-        if (m_webglDepthTexture)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
-        return false;
-    default:
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
-        return false;
-    }
-    
-    // Verify that a valid type has been provided.
-    switch (type) {
-    case GraphicsContext3D::UNSIGNED_BYTE:
-    case GraphicsContext3D::BYTE:
-    case GraphicsContext3D::UNSIGNED_SHORT:
-    case GraphicsContext3D::SHORT:
-    case GraphicsContext3D::UNSIGNED_INT:
-    case GraphicsContext3D::INT:
-    case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
-    case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
-    case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV:
-    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
-    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
-    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
-        break;
-    case GraphicsContext3D::FLOAT:
-        if (m_oesTextureFloat)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
-        return false;
-    case GraphicsContext3D::HALF_FLOAT:
-    case GraphicsContext3D::HALF_FLOAT_OES:
-        if (m_oesTextureHalfFloat)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
-        return false;
-    case GraphicsContext3D::UNSIGNED_INT_24_8:
-    case GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV:
-        if (isDepthStencilSupported())
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
-        return false;
-    default:
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
-        return false;
-    }
-    
-    // Veryify that a valid internal format has been provided.
-    switch (internalformat) {
-    case GraphicsContext3D::RGBA:
-    case GraphicsContext3D::RGB:
-    case GraphicsContext3D::LUMINANCE_ALPHA:
-    case GraphicsContext3D::LUMINANCE:
-    case GraphicsContext3D::ALPHA:
-    case GraphicsContext3D::RGBA32I:
-    case GraphicsContext3D::RGBA32UI:
-    case GraphicsContext3D::RGBA16I:
-    case GraphicsContext3D::RGBA16UI:
-    case GraphicsContext3D::RGBA8:
-    case GraphicsContext3D::RGBA8I:
-    case GraphicsContext3D::RGBA8UI:
-    case GraphicsContext3D::RGB10_A2:
-    case GraphicsContext3D::RGB10_A2UI:
-    case GraphicsContext3D::RGBA4:
-    case GraphicsContext3D::RG32I:
-    case GraphicsContext3D::RG32UI:
-    case GraphicsContext3D::RG16I:
-    case GraphicsContext3D::RG16UI:
-    case GraphicsContext3D::RG8:
-    case GraphicsContext3D::RG8I:
-    case GraphicsContext3D::RG8UI:
-    case GraphicsContext3D::R32I:
-    case GraphicsContext3D::R32UI:
-    case GraphicsContext3D::R16I:
-    case GraphicsContext3D::R16UI:
-    case GraphicsContext3D::R8:
-    case GraphicsContext3D::R8I:
-    case GraphicsContext3D::R8UI:
-    case GraphicsContext3D::RGB5_A1:
-    case GraphicsContext3D::RGB8:
-    case GraphicsContext3D::RGB565:
-    case GraphicsContext3D::RGBA32F:
-    case GraphicsContext3D::RGBA16F:
-    case GraphicsContext3D::RGBA8_SNORM:
-    case GraphicsContext3D::RGB32F:
-    case GraphicsContext3D::RGB32I:
-    case GraphicsContext3D::RGB32UI:
-    case GraphicsContext3D::RGB16F:
-    case GraphicsContext3D::RGB16I:
-    case GraphicsContext3D::RGB16UI:
-    case GraphicsContext3D::RGB8_SNORM:
-    case GraphicsContext3D::RGB8I:
-    case GraphicsContext3D::RGB8UI:
-    case GraphicsContext3D::SRGB8:
-    case GraphicsContext3D::SRGB8_ALPHA8:
-    case GraphicsContext3D::R11F_G11F_B10F:
-    case GraphicsContext3D::RGB9_E5:
-    case GraphicsContext3D::RG32F:
-    case GraphicsContext3D::RG16F:
-    case GraphicsContext3D::RG8_SNORM:
-    case GraphicsContext3D::R32F:
-    case GraphicsContext3D::R16F:
-    case GraphicsContext3D::R8_SNORM:
-    case GraphicsContext3D::STENCIL_INDEX8:
-        break;
-    case GraphicsContext3D::DEPTH_COMPONENT16:
-    case GraphicsContext3D::DEPTH_COMPONENT32F:
-    case GraphicsContext3D::DEPTH_COMPONENT24:
-        if (m_webglDepthTexture)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
-        return false;
-    case GraphicsContext3D::DEPTH32F_STENCIL8:
-    case GraphicsContext3D::DEPTH24_STENCIL8:
-        if (isDepthStencilSupported())
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture internal format");
-        return false;
-    case GraphicsContext3D::NONE:
-        // When calling validateTexFuncFormatAndType with internalformat == GraphicsContext3D::NONE, the intent is
-        // only to check for whether or not the format and type are valid types, which we have already done at this point.
-        return true;
-        break;
-    default:
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture internal format");
-        return false;
-    }
-
-    // Verify that the combination of format, internalformat and type is supported.
-    switch (format) {
-    case GraphicsContext3D::RGBA:
-        if (type == GraphicsContext3D::UNSIGNED_BYTE
-            && (internalformat == GraphicsContext3D::RGBA || internalformat == GraphicsContext3D::RGBA8 || internalformat == GraphicsContext3D::RGB5_A1 || internalformat == GraphicsContext3D::RGBA4 || internalformat == GraphicsContext3D::SRGB8_ALPHA8))
-            break;
-        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RGBA8_SNORM)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
-            && (internalformat == GraphicsContext3D::RGBA || internalformat == GraphicsContext3D::RGBA4))
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
-            && (internalformat == GraphicsContext3D::RGBA || internalformat == GraphicsContext3D::RGB5_A1))
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV
-            && (internalformat == GraphicsContext3D::RGB10_A2 || internalformat == GraphicsContext3D::RGB5_A1))
-            break;
-        if ((type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::HALF_FLOAT_OES) && internalformat == GraphicsContext3D::RGBA16F)
-            break;
-        if (type == GraphicsContext3D::FLOAT
-            && (internalformat == GraphicsContext3D::RGBA32F || internalformat == GraphicsContext3D::RGBA16F))
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::RGBA_INTEGER:
-        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::RGBA8UI)
-        break;
-        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RGBA8I)
-        break;
-        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::RGBA16UI)
-        break;
-        if (type == GraphicsContext3D::SHORT && internalformat == GraphicsContext3D::RGBA16I)
-        break;
-        if (type == GraphicsContext3D::UNSIGNED_INT && internalformat == GraphicsContext3D::RGBA32UI)
-        break;
-        if (type == GraphicsContext3D::INT && internalformat == GraphicsContext3D::RGBA32I)
-        break;
-        if (type == GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV && internalformat == GraphicsContext3D::RGB10_A2UI)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::RGB:
-        if (type == GraphicsContext3D::UNSIGNED_BYTE
-            && (internalformat == GraphicsContext3D::RGB || internalformat == GraphicsContext3D::RGB8 || internalformat == GraphicsContext3D::RGB565
-            || internalformat == GraphicsContext3D::SRGB8))
-            break;
-        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RGB8_SNORM)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_SHORT_5_6_5
-            && (internalformat == GraphicsContext3D::RGB || internalformat == GraphicsContext3D::RGB565))
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV && internalformat == GraphicsContext3D::R11F_G11F_B10F)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV && internalformat == GraphicsContext3D::RGB9_E5)
-            break;
-        if ((type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::HALF_FLOAT_OES)
-            && (internalformat == GraphicsContext3D::RGB16F || internalformat == GraphicsContext3D::R11F_G11F_B10F || internalformat == GraphicsContext3D::RGB9_E5))
-            break;
-        if (type == GraphicsContext3D::FLOAT
-            && (internalformat == GraphicsContext3D::RGB32F || internalformat == GraphicsContext3D::RGB16F || internalformat == GraphicsContext3D::R11F_G11F_B10F || internalformat == GraphicsContext3D::RGB9_E5))
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::RGB_INTEGER:
-        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::RGB8UI)
-            break;
-        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RGB8I)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::RGB16UI)
-            break;
-        if (type == GraphicsContext3D::SHORT && internalformat == GraphicsContext3D::RGB16I)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_INT && internalformat == GraphicsContext3D::RGB32UI)
-            break;
-        if (type == GraphicsContext3D::INT && internalformat == GraphicsContext3D::RGB32I)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::RG:
-        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::RG8)
-            break;
-        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RG8_SNORM)
-            break;
-        if ((type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::HALF_FLOAT_OES) && internalformat == GraphicsContext3D::RG16F)
-            break;
-        if (type == GraphicsContext3D::FLOAT
-            && (internalformat == GraphicsContext3D::RG32F || internalformat == GraphicsContext3D::RG16F))
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::RG_INTEGER:
-        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::RG8UI)
-            break;
-        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RG8I)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::RG16UI)
-            break;
-        if (type == GraphicsContext3D::SHORT && internalformat == GraphicsContext3D::RG16I)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_INT && internalformat == GraphicsContext3D::RG32UI)
-            break;
-        if (type == GraphicsContext3D::INT && internalformat == GraphicsContext3D::RG32I)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::RED:
-        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::R8)
-            break;
-        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::R8_SNORM)
-            break;
-        if ((type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::HALF_FLOAT_OES) && internalformat == GraphicsContext3D::R16F)
-            break;
-        if (type == GraphicsContext3D::FLOAT
-            && (internalformat == GraphicsContext3D::R32F || internalformat == GraphicsContext3D::R16F))
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::RED_INTEGER:
-        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::R8UI)
-            break;
-        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::R8I)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::R16UI)
-            break;
-        if (type == GraphicsContext3D::SHORT && internalformat == GraphicsContext3D::R16I)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_INT && internalformat == GraphicsContext3D::R32UI)
-            break;
-        if (type == GraphicsContext3D::INT && internalformat == GraphicsContext3D::R32I)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::DEPTH_COMPONENT:
-        if (!m_webglDepthTexture) {
-            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
-            return false;
-        }
-        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::DEPTH_COMPONENT16)
-            break;
-        if (type == GraphicsContext3D::UNSIGNED_INT
-            && (internalformat == GraphicsContext3D::DEPTH_COMPONENT24 || internalformat == GraphicsContext3D::DEPTH_COMPONENT16))
-            break;
-        if (type == GraphicsContext3D::FLOAT && internalformat == GraphicsContext3D::DEPTH_COMPONENT32F)
-            break;
-        if (level > 0) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
-            return false;
-        }
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::DEPTH_STENCIL:
-        if (!m_webglDepthTexture || !isDepthStencilSupported()) {
-            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
-            return false;
-        }
-        if (type == GraphicsContext3D::UNSIGNED_INT_24_8 && internalformat == GraphicsContext3D::DEPTH24_STENCIL8)
-            break;
-        if (type == GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV && internalformat == GraphicsContext3D::DEPTH32F_STENCIL8)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    case GraphicsContext3D::ALPHA:
-    case GraphicsContext3D::LUMINANCE:
-    case GraphicsContext3D::LUMINANCE_ALPHA:
-        if ((type == GraphicsContext3D::UNSIGNED_BYTE || type == GraphicsContext3D::HALF_FLOAT_OES || type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::FLOAT) && internalformat == format)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
-        return false;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-
-    return true;
-}
-
-bool WebGL2RenderingContext::validateTexFuncData(const char* functionName, GC3Dint level,
-    GC3Dsizei width, GC3Dsizei height,
-    GC3Denum internalformat, GC3Denum format, GC3Denum type,
-    ArrayBufferView* pixels,
-    NullDisposition disposition)
-{
-    if (!pixels) {
-        if (disposition == NullAllowed)
-            return true;
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
-        return false;
-    }
-
-    if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level))
-        return false;
-    if (!validateSettableTexFormat(functionName, format))
-        return false;
-    
-    switch (type) {
-    case GraphicsContext3D::BYTE:
-        if (pixels->getType() != JSC::TypeInt8) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type BYTE but ArrayBufferView not Int8Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::UNSIGNED_BYTE:
-        if (pixels->getType() != JSC::TypeUint8) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::SHORT:
-        if (pixels->getType() != JSC::TypeInt16) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type SHORT but ArrayBufferView not Int16Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::UNSIGNED_SHORT:
-    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
-    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
-    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
-        if (pixels->getType() != JSC::TypeUint16) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::INT:
-        if (pixels->getType() != JSC::TypeInt32) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type INT but ArrayBufferView not Int32Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::UNSIGNED_INT:
-    case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
-    case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
-        if (pixels->getType() != JSC::TypeUint32) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_INT but ArrayBufferView not Uint32Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::HALF_FLOAT:
-    case GraphicsContext3D::FLOAT:
-        if (pixels->getType() != JSC::TypeFloat32) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
-        // As per the specification, ArrayBufferView should be null when
-        // OES_texture_half_float is enabled.
-        if (pixels) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
-            return false;
-        }
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    
-    unsigned totalBytesRequired;
-    GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
-    if (error != GraphicsContext3D::NO_ERROR) {
-        synthesizeGLError(error, functionName, "invalid texture dimensions");
-        return false;
-    }
-    if (pixels->byteLength() < totalBytesRequired) {
-        if (m_unpackAlignment != 1) {
-            m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
-            if (pixels->byteLength() == totalBytesRequired) {
-                synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
-                return false;
-            }
-        }
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
-        return false;
-    }
-    return true;
-}
-
 GC3Denum WebGL2RenderingContext::baseInternalFormatFromInternalFormat(GC3Denum internalformat)
 {
     // Handles sized, unsized, and compressed internal formats.
 GC3Denum WebGL2RenderingContext::baseInternalFormatFromInternalFormat(GC3Denum internalformat)
 {
     // Handles sized, unsized, and compressed internal formats.
@@ -1965,6 +1240,8 @@ GC3Denum WebGL2RenderingContext::baseInternalFormatFromInternalFormat(GC3Denum i
 
 bool WebGL2RenderingContext::isIntegerFormat(GC3Denum internalformat)
 {
 
 bool WebGL2RenderingContext::isIntegerFormat(GC3Denum internalformat)
 {
+    // FIXME: baseInternalFormatFromInternalFormat() never returns any of these enums.
+    // Currently, This function erroneously always returns false.
     switch (baseInternalFormatFromInternalFormat(internalformat)) {
     case GraphicsContext3D::RED_INTEGER:
     case GraphicsContext3D::RG_INTEGER:
     switch (baseInternalFormatFromInternalFormat(internalformat)) {
     case GraphicsContext3D::RED_INTEGER:
     case GraphicsContext3D::RG_INTEGER:
index 105bce7..1dc0ee4 100644 (file)
@@ -179,29 +179,12 @@ private:
 
     void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) final;
     void hint(GC3Denum target, GC3Denum mode) final;
 
     void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) final;
     void hint(GC3Denum target, GC3Denum mode) final;
-    void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) final;
-    void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels) final;
-    void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha) final;
-    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&) final;
-    ExceptionOr<void> texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Optional<TexImageSource>&&) final;
 
     void initializeVertexArrayObjects() final;
     GC3Dint getMaxDrawBuffers() final;
     GC3Dint getMaxColorAttachments() final;
     bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) final;
     bool validateBlendEquation(const char* functionName, GC3Denum mode) final;
 
     void initializeVertexArrayObjects() final;
     GC3Dint getMaxDrawBuffers() final;
     GC3Dint getMaxColorAttachments() final;
     bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) final;
     bool validateBlendEquation(const char* functionName, GC3Denum mode) final;
-    bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level) final;
-    bool validateTexFuncParameters(const char* functionName,
-        TexFuncValidationFunctionType,
-        GC3Denum target, GC3Dint level,
-        GC3Denum internalformat,
-        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
-        GC3Denum format, GC3Denum type) final;
-    bool validateTexFuncData(const char* functionName, GC3Dint level,
-        GC3Dsizei width, GC3Dsizei height,
-        GC3Denum internalformat, GC3Denum format, GC3Denum type,
-        ArrayBufferView* pixels,
-        NullDisposition) final;
     bool validateCapability(const char* functionName, GC3Denum cap) final;
     bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) final;
     
     bool validateCapability(const char* functionName, GC3Denum cap) final;
     bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) final;
     
index 49c8cd1..96b808d 100644 (file)
@@ -465,457 +465,6 @@ void WebGLRenderingContext::clear(GC3Dbitfield mask)
     markContextChanged();
 }
 
     markContextChanged();
 }
 
-void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
-{
-    if (isContextLostOrPending())
-        return;
-    if (!validateTexFuncParameters("copyTexImage2D", CopyTexImage, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
-        return;
-    if (!validateSettableTexFormat("copyTexImage2D", internalformat))
-        return;
-    WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
-    if (!tex)
-        return;
-    if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
-        return;
-    }
-    if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
-        return;
-    }
-    const char* reason = "framebuffer incomplete";
-    if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
-        synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
-        return;
-    }
-    clearIfComposited();
-    if (isResourceSafe())
-        m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
-    else {
-        GC3Dint clippedX, clippedY;
-        GC3Dsizei clippedWidth, clippedHeight;
-        if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
-            m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
-                internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
-            if (clippedWidth > 0 && clippedHeight > 0) {
-                m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
-                    clippedX, clippedY, clippedWidth, clippedHeight);
-            }
-        } else
-            m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
-    }
-    // FIXME: if the framebuffer is not complete, none of the below should be executed.
-    tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
-}
-
-void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels)
-{
-    UNUSED_PARAM(internalformat);
-    ASSERT(!isContextLost());
-    ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage, target, level, format, width, height, 0, format, type));
-    ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
-    ASSERT(validateSettableTexFormat("texSubImage2D", format));
-    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
-    if (!tex) {
-        ASSERT_NOT_REACHED();
-        return;
-    }
-    ASSERT((xoffset + width) >= 0);
-    ASSERT((yoffset + height) >= 0);
-    ASSERT(tex->getWidth(target, level) >= (xoffset + width));
-    ASSERT(tex->getHeight(target, level) >= (yoffset + height));
-    ASSERT(tex->getInternalFormat(target, level) == format);
-    ASSERT(tex->getType(target, level) == type);
-    m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
-}
-
-void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
-{
-    Vector<uint8_t> data;
-    GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
-    if (!imageExtractor.extractSucceeded()) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
-        return;
-    }
-    GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
-    GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
-    const void* imagePixelData = imageExtractor.imagePixelData();
-    
-    bool needConversion = true;
-    if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
-        needConversion = false;
-    else {
-        if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
-            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
-            return;
-        }
-    }
-    
-    if (m_unpackAlignment != 1)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-
-    texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, format, type, needConversion ? data.data() : imagePixelData);
-    if (m_unpackAlignment != 1)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
-}
-
-void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels)
-{
-    if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, format, type, pixels.get(), NullNotAllowed) || !validateTexFunc("texSubImage2D", TexSubImage, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
-        return;
-    
-    void* data = pixels->baseAddress();
-    Vector<uint8_t> tempData;
-    bool changeUnpackAlignment = false;
-    if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
-        if (!m_context->extractTextureData(width, height, format, type,
-            m_unpackAlignment,
-            m_unpackFlipY, m_unpackPremultiplyAlpha,
-            data,
-            tempData))
-            return;
-        data = tempData.data();
-        changeUnpackAlignment = true;
-    }
-    if (changeUnpackAlignment)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-
-    texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, format, type, data);
-    if (changeUnpackAlignment)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
-}
-
-ExceptionOr<void> WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Optional<TexImageSource>&& source)
-{
-    if (!source) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "source is null");
-        return { };
-    }
-
-    auto visitor = WTF::makeVisitor([&](const RefPtr<ImageData>& pixels) -> ExceptionOr<void> {
-        if (isContextLostOrPending() || !validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, format,  pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
-            return { };
-
-        Vector<uint8_t> data;
-        bool needConversion = true;
-        // The data from ImageData is always of format RGBA8.
-        // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
-        if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
-            needConversion = false;
-        else {
-            if (!m_context->extractImageData(pixels.get(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
-                synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
-                return { };
-            }
-        }
-        if (m_unpackAlignment != 1)
-            m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-
-        texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, format, type, needConversion ? data.data() : pixels->data()->data());
-        if (m_unpackAlignment != 1)
-            m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
-
-        return { };
-    } , [&](const RefPtr<HTMLImageElement>& image) -> ExceptionOr<void> {
-        if (wouldTaintOrigin(image.get()))
-            return Exception { SECURITY_ERR };
-        if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image.get()))
-            return { };
-
-        RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
-        if (!imageForRender)
-            return { };
-
-        if (imageForRender->isSVGImage())
-            imageForRender = drawImageIntoBuffer(*imageForRender, image->width(), image->height(), 1);
-
-        if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
-            return { };
-
-        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
-        return { };
-    }, [&](const RefPtr<HTMLCanvasElement>& canvas) -> ExceptionOr<void> {
-        if (wouldTaintOrigin(canvas.get()))
-            return Exception { SECURITY_ERR };
-        if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas.get())
-            || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
-            return { };
-
-        RefPtr<ImageData> imageData = canvas->getImageData();
-        if (imageData)
-            texSubImage2D(target, level, xoffset, yoffset, format, type, TexImageSource(imageData.get()));
-        else
-            texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
-        return { };
-    }, [&](const RefPtr<HTMLVideoElement>& video) -> ExceptionOr<void> {
-        if (wouldTaintOrigin(video.get()))
-            return Exception { SECURITY_ERR };
-        if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video.get())
-            || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
-            return { };
-
-        RefPtr<Image> image = videoFrameToImage(video.get(), ImageBuffer::fastCopyImageMode());
-        if (!image)
-            return { };
-        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
-        return { };
-    });
-
-    return WTF::visit(visitor, source.value());
-}
-
-bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName,
-    TexFuncValidationFunctionType functionType,
-    GC3Denum target, GC3Dint level,
-    GC3Denum internalformat,
-    GC3Dsizei width, GC3Dsizei height, GC3Dint border,
-    GC3Denum format, GC3Denum type)
-{
-    // We absolutely have to validate the format and type combination.
-    // The texImage2D entry points taking HTMLImage, etc. will produce
-    // temporary data based on this combination, so it must be legal.
-    if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level) || !validateTexFuncLevel(functionName, target, level))
-        return false;
-    
-    if (width < 0 || height < 0) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
-        return false;
-    }
-    
-    GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
-    switch (target) {
-    case GraphicsContext3D::TEXTURE_2D:
-        if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
-            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
-    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
-        if (functionType != TexSubImage && width != height) {
-            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
-            return false;
-        }
-        // No need to check height here. For texImage width == height.
-        // For texSubImage that will be checked when checking yoffset + height is in range.
-        if (width > maxTextureSizeForLevel) {
-            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
-            return false;
-        }
-        break;
-    default:
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
-        return false;
-    }
-
-    if (format != internalformat) {
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
-        return false;
-    }
-    
-    if (border) {
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
-        return false;
-    }
-    
-    return true;
-}
-
-bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level)
-{
-    UNUSED_PARAM(internalformat);
-    switch (format) {
-    case GraphicsContext3D::ALPHA:
-    case GraphicsContext3D::LUMINANCE:
-    case GraphicsContext3D::LUMINANCE_ALPHA:
-    case GraphicsContext3D::RGB:
-    case GraphicsContext3D::RGBA:
-        break;
-    case GraphicsContext3D::DEPTH_STENCIL:
-    case GraphicsContext3D::DEPTH_COMPONENT:
-        if (m_webglDepthTexture)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
-        return false;
-    case Extensions3D::SRGB_EXT:
-    case Extensions3D::SRGB_ALPHA_EXT:
-    default:
-        if ((format == Extensions3D::SRGB_EXT || format == Extensions3D::SRGB_ALPHA_EXT)
-            && m_extsRGB)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
-        return false;
-    }
-    
-    switch (type) {
-    case GraphicsContext3D::UNSIGNED_BYTE:
-    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
-    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
-    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
-        break;
-    case GraphicsContext3D::FLOAT:
-        if (m_oesTextureFloat)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
-        return false;
-    case GraphicsContext3D::HALF_FLOAT_OES:
-        if (m_oesTextureHalfFloat)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
-        return false;
-    case GraphicsContext3D::UNSIGNED_INT:
-    case GraphicsContext3D::UNSIGNED_INT_24_8:
-    case GraphicsContext3D::UNSIGNED_SHORT:
-        if (m_webglDepthTexture)
-            break;
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
-        return false;
-    default:
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
-        return false;
-    }
-    
-    // Verify that the combination of format and type is supported.
-    switch (format) {
-    case GraphicsContext3D::ALPHA:
-    case GraphicsContext3D::LUMINANCE:
-    case GraphicsContext3D::LUMINANCE_ALPHA:
-        if (type != GraphicsContext3D::UNSIGNED_BYTE
-            && type != GraphicsContext3D::FLOAT
-            && type != GraphicsContext3D::HALF_FLOAT_OES) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::RGB:
-    case Extensions3D::SRGB_EXT:
-        if (type != GraphicsContext3D::UNSIGNED_BYTE
-            && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
-            && type != GraphicsContext3D::FLOAT
-            && type != GraphicsContext3D::HALF_FLOAT_OES) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::RGBA:
-    case Extensions3D::SRGB_ALPHA_EXT:
-        if (type != GraphicsContext3D::UNSIGNED_BYTE
-            && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
-            && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
-            && type != GraphicsContext3D::FLOAT
-            && type != GraphicsContext3D::HALF_FLOAT_OES) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::DEPTH_COMPONENT:
-        if (!m_webglDepthTexture) {
-            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
-            return false;
-        }
-        if (type != GraphicsContext3D::UNSIGNED_SHORT
-            && type != GraphicsContext3D::UNSIGNED_INT) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
-            return false;
-        }
-        if (level > 0) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::DEPTH_STENCIL:
-        if (!m_webglDepthTexture) {
-            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
-            return false;
-        }
-        if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
-            return false;
-        }
-        if (level > 0) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
-            return false;
-        }
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    
-    return true;
-}
-
-bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, NullDisposition disposition)
-{
-    if (!pixels) {
-        if (disposition == NullAllowed)
-            return true;
-        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
-        return false;
-    }
-
-    if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level))
-        return false;
-    if (!validateSettableTexFormat(functionName, format))
-        return false;
-    
-    switch (type) {
-    case GraphicsContext3D::UNSIGNED_BYTE:
-        if (pixels->getType() != JSC::TypeUint8) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
-    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
-    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
-        if (pixels->getType() != JSC::TypeUint16) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::FLOAT: // OES_texture_float
-        if (pixels->getType() != JSC::TypeFloat32) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
-            return false;
-        }
-        break;
-    case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
-        // As per the specification, ArrayBufferView should be null when
-        // OES_texture_half_float is enabled.
-        if (pixels) {
-            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
-            return false;
-        }
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    
-    unsigned totalBytesRequired;
-    GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
-    if (error != GraphicsContext3D::NO_ERROR) {
-        synthesizeGLError(error, functionName, "invalid texture dimensions");
-        return false;
-    }
-    if (pixels->byteLength() < totalBytesRequired) {
-        if (m_unpackAlignment != 1) {
-            m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
-            if (pixels->byteLength() == totalBytesRequired) {
-                synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
-                return false;
-            }
-        }
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
-        return false;
-    }
-    return true;
-}
-
 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname)
 {
     if (isContextLostOrPending())
 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname)
 {
     if (isContextLostOrPending())
index 6709411..69c2e3f 100644 (file)
@@ -46,20 +46,12 @@ private:
     bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) final;
     void hint(GC3Denum target, GC3Denum mode) final;
     void clear(GC3Dbitfield mask) final;
     bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) final;
     void hint(GC3Denum target, GC3Denum mode) final;
     void clear(GC3Dbitfield mask) final;
-    void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) final;
-    void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels) final;
-    void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha) final;
-    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&) final;
-    ExceptionOr<void> texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Optional<TexImageSource>&&) final;
 
     GC3Dint getMaxDrawBuffers() final;
     GC3Dint getMaxColorAttachments() final;
     void initializeVertexArrayObjects() final;
     bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) final;
     bool validateBlendEquation(const char* functionName, GC3Denum mode) final;
 
     GC3Dint getMaxDrawBuffers() final;
     GC3Dint getMaxColorAttachments() final;
     void initializeVertexArrayObjects() final;
     bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) final;
     bool validateBlendEquation(const char* functionName, GC3Denum mode) final;
-    bool validateTexFuncParameters(const char* functionName, TexFuncValidationFunctionType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type) final;
-    bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level) final;
-    bool validateTexFuncData(const char* functionName, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, NullDisposition) final;
     bool validateCapability(const char* functionName, GC3Denum cap) final;
 };
     
     bool validateCapability(const char* functionName, GC3Denum cap) final;
 };
     
index 1a1f16a..2eb9281 100644 (file)
@@ -1309,13 +1309,22 @@ void WebGLRenderingContextBase::compressedTexSubImage2D(GC3Denum target, GC3Dint
     tex->setCompressed();
 }
 
     tex->setCompressed();
 }
 
-bool WebGLRenderingContextBase::validateSettableTexFormat(const char* functionName, GC3Denum format)
-{
-    if (GraphicsContext3D::getClearBitsByFormat(format) & (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
+bool WebGLRenderingContextBase::validateSettableTexInternalFormat(const char* functionName, GC3Denum internalFormat)
+{
+    switch (internalFormat) {
+    case GraphicsContext3D::DEPTH_COMPONENT:
+    case GraphicsContext3D::DEPTH_STENCIL:
+    case GraphicsContext3D::DEPTH_COMPONENT16:
+    case GraphicsContext3D::DEPTH_COMPONENT24:
+    case GraphicsContext3D::DEPTH_COMPONENT32F:
+    case GraphicsContext3D::DEPTH24_STENCIL8:
+    case GraphicsContext3D::DEPTH32F_STENCIL8:
+    case GraphicsContext3D::STENCIL_INDEX8:
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to");
         return false;
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to");
         return false;
+    default:
+        return true;
     }
     }
-    return true;
 }
 
 void WebGLRenderingContextBase::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
 }
 
 void WebGLRenderingContextBase::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
@@ -1338,10 +1347,10 @@ void WebGLRenderingContextBase::copyTexSubImage2D(GC3Denum target, GC3Dint level
         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range");
         return;
     }
         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range");
         return;
     }
-    GC3Denum internalformat = tex->getInternalFormat(target, level);
-    if (!validateSettableTexFormat("copyTexSubImage2D", internalformat))
+    GC3Denum internalFormat = tex->getInternalFormat(target, level);
+    if (!validateSettableTexInternalFormat("copyTexSubImage2D", internalFormat))
         return;
         return;
-    if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
+    if (!isTexInternalFormatColorBufferCombinationValid(internalFormat, getBoundFramebufferColorFormat())) {
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format");
         return;
     }
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format");
         return;
     }
@@ -1357,8 +1366,12 @@ void WebGLRenderingContextBase::copyTexSubImage2D(GC3Denum target, GC3Dint level
         GC3Dint clippedX, clippedY;
         GC3Dsizei clippedWidth, clippedHeight;
         if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
         GC3Dint clippedX, clippedY;
         GC3Dsizei clippedWidth, clippedHeight;
         if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
-            GC3Denum format = tex->getInternalFormat(target, level);
-            GC3Denum type = tex->getType(target, level);
+            GC3Denum format;
+            GC3Denum type;
+            if (!GraphicsContext3D::possibleFormatAndTypeForInternalFormat(tex->getInternalFormat(target, level), format, type)) {
+                synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "copyTexSubImage2D", "Texture has unknown internal format");
+                return;
+            }
             std::unique_ptr<unsigned char[]> zero;
             if (width && height) {
                 unsigned int size;
             std::unique_ptr<unsigned char[]> zero;
             if (width && height) {
                 unsigned int size;
@@ -2108,7 +2121,7 @@ void WebGLRenderingContextBase::generateMipmap(GC3Denum target)
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "trying to generate mipmaps from compressed texture");
         return;
     }
         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "trying to generate mipmaps from compressed texture");
         return;
     }
-    if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0)))
+    if (!validateSettableTexInternalFormat("generateMipmap", tex->getInternalFormat(target, 0)))
         return;
 
     // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
         return;
 
     // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR
@@ -2819,47 +2832,305 @@ void WebGLRenderingContextBase::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
     m_context->polygonOffset(factor, units);
 }
 
     m_context->polygonOffset(factor, units);
 }
 
-void WebGLRenderingContextBase::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView& pixels)
+enum class InternalFormatTheme {
+    None,
+    NormalizedFixedPoint,
+    Packed,
+    SignedNormalizedFixedPoint,
+    FloatingPoint,
+    SignedInteger,
+    UnsignedInteger
+};
+
+static InternalFormatTheme internalFormatTheme(GC3Denum internalFormat)
 {
 {
-    if (isContextLostOrPending())
-        return;
-    // Due to WebGL's same-origin restrictions, it is not possible to
-    // taint the origin using the WebGL API.
-    ASSERT(canvas().originClean());
-    // Validate input parameters.
-    switch (format) {
+    switch (internalFormat) {
+    case GraphicsContext3D::RGB:
+    case GraphicsContext3D::RGBA:
+    case GraphicsContext3D::LUMINANCE_ALPHA:
+    case GraphicsContext3D::LUMINANCE:
     case GraphicsContext3D::ALPHA:
     case GraphicsContext3D::ALPHA:
+    case GraphicsContext3D::R8:
+    case GraphicsContext3D::RG8:
+    case GraphicsContext3D::RGB8:
+    case GraphicsContext3D::SRGB8:
+    case GraphicsContext3D::RGBA8:
+    case GraphicsContext3D::SRGB8_ALPHA8:
+    case GraphicsContext3D::SRGB_ALPHA:
+        return InternalFormatTheme::NormalizedFixedPoint;
+    case GraphicsContext3D::RGB565:
+    case GraphicsContext3D::RGB5_A1:
+    case GraphicsContext3D::RGBA4:
+    case GraphicsContext3D::RGB9_E5:
+    case GraphicsContext3D::RGB10_A2:
+    case GraphicsContext3D::R11F_G11F_B10F:
+    case GraphicsContext3D::RGB10_A2UI:
+        return InternalFormatTheme::Packed;
+    case GraphicsContext3D::R8_SNORM:
+    case GraphicsContext3D::RG8_SNORM:
+    case GraphicsContext3D::RGB8_SNORM:
+    case GraphicsContext3D::RGBA8_SNORM:
+        return InternalFormatTheme::SignedNormalizedFixedPoint;
+    case GraphicsContext3D::R16F:
+    case GraphicsContext3D::R32F:
+    case GraphicsContext3D::RG16F:
+    case GraphicsContext3D::RG32F:
+    case GraphicsContext3D::RGB16F:
+    case GraphicsContext3D::RGB32F:
+    case GraphicsContext3D::RGBA16F:
+    case GraphicsContext3D::RGBA32F:
+        return InternalFormatTheme::FloatingPoint;
+    case GraphicsContext3D::R8I:
+    case GraphicsContext3D::R16I:
+    case GraphicsContext3D::R32I:
+    case GraphicsContext3D::RG8I:
+    case GraphicsContext3D::RG16I:
+    case GraphicsContext3D::RG32I:
+    case GraphicsContext3D::RGB8I:
+    case GraphicsContext3D::RGB16I:
+    case GraphicsContext3D::RGB32I:
+    case GraphicsContext3D::RGBA8I:
+    case GraphicsContext3D::RGBA16I:
+    case GraphicsContext3D::RGBA32I:
+        return InternalFormatTheme::SignedInteger;
+    case GraphicsContext3D::R8UI:
+    case GraphicsContext3D::R16UI:
+    case GraphicsContext3D::R32UI:
+    case GraphicsContext3D::RG8UI:
+    case GraphicsContext3D::RG16UI:
+    case GraphicsContext3D::RG32UI:
+    case GraphicsContext3D::RGB8UI:
+    case GraphicsContext3D::RGB16UI:
+    case GraphicsContext3D::RGB32UI:
+    case GraphicsContext3D::RGBA8UI:
+    case GraphicsContext3D::RGBA16UI:
+    case GraphicsContext3D::RGBA32UI:
+        return InternalFormatTheme::UnsignedInteger;
+    default:
+        return InternalFormatTheme::None;
+    }
+}
+
+static int numberOfComponentsForFormat(GC3Denum format)
+{
+    switch (format) {
+    case GraphicsContext3D::RED:
+    case GraphicsContext3D::RED_INTEGER:
+        return 1;
+    case GraphicsContext3D::RG:
+    case GraphicsContext3D::RG_INTEGER:
+        return 2;
     case GraphicsContext3D::RGB:
     case GraphicsContext3D::RGB:
+    case GraphicsContext3D::RGB_INTEGER:
+        return 3;
     case GraphicsContext3D::RGBA:
     case GraphicsContext3D::RGBA:
-        break;
+    case GraphicsContext3D::RGBA_INTEGER:
+        return 4;
     default:
     default:
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format");
-        return;
+        return 0;
     }
     }
-    switch (type) {
-    case GraphicsContext3D::UNSIGNED_BYTE:
-    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
-    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
-    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
-        break;
+}
+
+static int numberOfComponentsForInternalFormat(GC3Denum internalFormat)
+{
+    switch (internalFormat) {
+    case GraphicsContext3D::LUMINANCE:
+    case GraphicsContext3D::ALPHA:
+    case GraphicsContext3D::R8:
+    case GraphicsContext3D::R8_SNORM:
+    case GraphicsContext3D::R16F:
+    case GraphicsContext3D::R32F:
+    case GraphicsContext3D::R8UI:
+    case GraphicsContext3D::R8I:
+    case GraphicsContext3D::R16UI:
+    case GraphicsContext3D::R16I:
+    case GraphicsContext3D::R32UI:
+    case GraphicsContext3D::R32I:
+    case GraphicsContext3D::DEPTH_COMPONENT16:
+    case GraphicsContext3D::DEPTH_COMPONENT24:
+    case GraphicsContext3D::DEPTH_COMPONENT32F:
+        return 1;
+    case GraphicsContext3D::RG8:
+    case GraphicsContext3D::LUMINANCE_ALPHA:
+    case GraphicsContext3D::RG8_SNORM:
+    case GraphicsContext3D::RG16F:
+    case GraphicsContext3D::RG32F:
+    case GraphicsContext3D::RG8UI:
+    case GraphicsContext3D::RG8I:
+    case GraphicsContext3D::RG16UI:
+    case GraphicsContext3D::RG16I:
+    case GraphicsContext3D::RG32UI:
+    case GraphicsContext3D::RG32I:
+    case GraphicsContext3D::DEPTH24_STENCIL8:
+    case GraphicsContext3D::DEPTH32F_STENCIL8:
+        return 2;
+    case GraphicsContext3D::RGB:
+    case GraphicsContext3D::RGB8:
+    case GraphicsContext3D::SRGB8:
+    case GraphicsContext3D::RGB565:
+    case GraphicsContext3D::RGB8_SNORM:
+    case GraphicsContext3D::R11F_G11F_B10F:
+    case GraphicsContext3D::RGB9_E5:
+    case GraphicsContext3D::RGB16F:
+    case GraphicsContext3D::RGB32F:
+    case GraphicsContext3D::RGB8UI:
+    case GraphicsContext3D::RGB8I:
+    case GraphicsContext3D::RGB16UI:
+    case GraphicsContext3D::RGB16I:
+    case GraphicsContext3D::RGB32UI:
+    case GraphicsContext3D::RGB32I:
+        return 3;
+    case GraphicsContext3D::RGBA:
+    case GraphicsContext3D::RGBA8:
+    case GraphicsContext3D::SRGB_ALPHA:
+    case GraphicsContext3D::SRGB8_ALPHA8:
+    case GraphicsContext3D::RGBA8_SNORM:
+    case GraphicsContext3D::RGB5_A1:
+    case GraphicsContext3D::RGBA4:
+    case GraphicsContext3D::RGB10_A2:
+    case GraphicsContext3D::RGBA16F:
+    case GraphicsContext3D::RGBA32F:
+    case GraphicsContext3D::RGBA8UI:
+    case GraphicsContext3D::RGBA8I:
+    case GraphicsContext3D::RGB10_A2UI:
+    case GraphicsContext3D::RGBA16UI:
+    case GraphicsContext3D::RGBA16I:
+    case GraphicsContext3D::RGBA32UI:
+    case GraphicsContext3D::RGBA32I:
+        return 4;
     default:
     default:
-        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type");
-        return;
+        return 0;
     }
     }
-    if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE");
+}
+
+void WebGLRenderingContextBase::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView& pixels)
+{
+    if (isContextLostOrPending())
         return;
         return;
+    // Due to WebGL's same-origin restrictions, it is not possible to
+    // taint the origin using the WebGL API.
+    ASSERT(canvas().originClean());
+
+    GC3Denum internalFormat = 0;
+    if (m_framebufferBinding) {
+        const char* reason = "framebuffer incomplete";
+        if (!m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
+            synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
+            return;
+        }
+        // FIXME: readBuffer() should affect this
+        internalFormat = m_framebufferBinding->getColorBufferFormat();
+    } else {
+        if (m_attributes.alpha)
+            internalFormat = GraphicsContext3D::RGB8;
+        else
+            internalFormat = GraphicsContext3D::RGBA8;
     }
     }
-    // Validate array type against pixel type.
-    if (pixels.getType() != JSC::TypeUint8) {
-        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array");
+
+    if (!internalFormat) {
+        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Incorrect internal format");
         return;
     }
         return;
     }
-    const char* reason = "framebuffer incomplete";
-    if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
-        synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
+
+    if (isWebGL1()) {
+        switch (format) {
+        case GraphicsContext3D::ALPHA:
+        case GraphicsContext3D::RGB:
+        case GraphicsContext3D::RGBA:
+            break;
+        default:
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format");
+            return;
+        }
+        switch (type) {
+        case GraphicsContext3D::UNSIGNED_BYTE:
+        case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
+        case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
+        case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
+            break;
+        default:
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type");
+            return;
+        }
+        if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) {
+            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE");
+            return;
+        }
+    }
+
+    InternalFormatTheme internalFormatTheme = WebCore::internalFormatTheme(internalFormat);
+    int internalFormatComponentCount = numberOfComponentsForInternalFormat(internalFormat);
+    if (internalFormatTheme == InternalFormatTheme::None || !internalFormatComponentCount) {
+        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Incorrect internal format");
         return;
     }
         return;
     }
+
+#define INTERNAL_FORMAT_CHECK(themeMacro, typeMacro, pixelTypeMacro) case InternalFormatTheme::themeMacro: \
+        if (type != GraphicsContext3D::typeMacro || pixels.getType() != JSC::pixelTypeMacro) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "type does not match internal format"); \
+            return; \
+        } \
+        if (format != GraphicsContext3D::RED && format != GraphicsContext3D::RG && format != GraphicsContext3D::RGB && format != GraphicsContext3D::RGBA) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Unknown format"); \
+            return; \
+        } \
+        if (numberOfComponentsForFormat(format) < internalFormatComponentCount) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Not enough components in format"); \
+            return; \
+        } \
+        break;
+
+#define INTERNAL_FORMAT_INTEGER_CHECK(themeMacro, typeMacro, pixelTypeMacro) case InternalFormatTheme::themeMacro: \
+        if (type != GraphicsContext3D::typeMacro || pixels.getType() != JSC::pixelTypeMacro) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "type does not match internal format"); \
+            return; \
+        } \
+        if (format != GraphicsContext3D::RED_INTEGER && format != GraphicsContext3D::RG_INTEGER && format != GraphicsContext3D::RGB_INTEGER && format != GraphicsContext3D::RGBA_INTEGER) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Unknown format"); \
+            return; \
+        } \
+        if (numberOfComponentsForFormat(format) < internalFormatComponentCount) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Not enough components in format"); \
+            return; \
+        } \
+        break;
+
+#define PACKED_INTERNAL_FORMAT_CHECK(internalFormatMacro, formatMacro, type0Macro, pixelType0Macro, type1Macro, pixelType1Macro) case GraphicsContext3D::internalFormatMacro: \
+        if (!(type == GraphicsContext3D::type0Macro && pixels.getType() == JSC::pixelType0Macro) \
+            && !(type == GraphicsContext3D::type1Macro && pixels.getType() == JSC::pixelType1Macro)) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "type does not match internal format"); \
+            return; \
+        } \
+        if (format != GraphicsContext3D::formatMacro) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Invalid format"); \
+            return; \
+        } \
+        break;
+
+    switch (internalFormatTheme) {
+    INTERNAL_FORMAT_CHECK        (NormalizedFixedPoint      , UNSIGNED_BYTE, TypeUint8  );
+    INTERNAL_FORMAT_CHECK        (SignedNormalizedFixedPoint, BYTE         , TypeInt8   );
+    INTERNAL_FORMAT_CHECK        (FloatingPoint             , FLOAT        , TypeFloat32);
+    INTERNAL_FORMAT_INTEGER_CHECK(SignedInteger             , INT          , TypeInt32  );
+    INTERNAL_FORMAT_INTEGER_CHECK(UnsignedInteger           , UNSIGNED_INT , TypeUint32 );
+    case InternalFormatTheme::Packed:
+        switch (internalFormat) {
+        PACKED_INTERNAL_FORMAT_CHECK(RGB565        , RGB         , UNSIGNED_SHORT_5_6_5        , TypeUint16, UNSIGNED_BYTE              , TypeUint8  );
+        PACKED_INTERNAL_FORMAT_CHECK(RGB5_A1       , RGBA        , UNSIGNED_SHORT_5_5_5_1      , TypeUint16, UNSIGNED_BYTE              , TypeUint8  );
+        PACKED_INTERNAL_FORMAT_CHECK(RGBA4         , RGBA        , UNSIGNED_SHORT_4_4_4_4      , TypeUint16, UNSIGNED_BYTE              , TypeUint8  );
+        PACKED_INTERNAL_FORMAT_CHECK(RGB9_E5       , RGB         , UNSIGNED_INT_5_9_9_9_REV    , TypeUint32, UNSIGNED_INT_5_9_9_9_REV   , TypeUint32 );
+        PACKED_INTERNAL_FORMAT_CHECK(RGB10_A2      , RGBA        , UNSIGNED_INT_2_10_10_10_REV , TypeUint32, UNSIGNED_INT_2_10_10_10_REV, TypeUint32 );
+        PACKED_INTERNAL_FORMAT_CHECK(R11F_G11F_B10F, RGB         , UNSIGNED_INT_10F_11F_11F_REV, TypeUint32, FLOAT                      , TypeFloat32);
+        PACKED_INTERNAL_FORMAT_CHECK(RGB10_A2UI    , RGBA_INTEGER, UNSIGNED_INT_2_10_10_10_REV , TypeUint32, UNSIGNED_INT_2_10_10_10_REV, TypeUint32 );
+        }
+        break;
+    case InternalFormatTheme::None:
+        ASSERT_NOT_REACHED();
+    }
+#undef INTERNAL_FORMAT_CHECK
+#undef INTERNAL_FORMAT_INTEGER_CHECK
+#undef PACKED_INTERNAL_FORMAT_CHECK
+
     // Calculate array size, taking into consideration of PACK_ALIGNMENT.
     unsigned int totalBytesRequired = 0;
     unsigned int padding = 0;
     // Calculate array size, taking into consideration of PACK_ALIGNMENT.
     unsigned int totalBytesRequired = 0;
     unsigned int padding = 0;
@@ -2878,30 +3149,10 @@ void WebGLRenderingContextBase::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width
     clearIfComposited();
     void* data = pixels.baseAddress();
 
     clearIfComposited();
     void* data = pixels.baseAddress();
 
-    {
-        if (m_isRobustnessEXTSupported)
-            m_context->getExtensions()->readnPixelsEXT(x, y, width, height, format, type, pixels.byteLength(), data);
-        else
-            m_context->readPixels(x, y, width, height, format, type, data);
-    }
-
-#if OS(DARWIN)
-    if (m_isRobustnessEXTSupported) // we haven't computed padding
-        m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
-    // FIXME: remove this section when GL driver bug on Mac AND the GLES driver bug
-    // on QC is fixed, i.e., when alpha is off, readPixels should
-    // set alpha to 255 instead of 0.
-    if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) {
-        unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
-        for (GC3Dsizei iy = 0; iy < height; ++iy) {
-            for (GC3Dsizei ix = 0; ix < width; ++ix) {
-                pixels[3] = 255;
-                pixels += 4;
-            }
-            pixels += padding;
-        }
-    }
-#endif
+    if (m_isRobustnessEXTSupported)
+        m_context->getExtensions()->readnPixelsEXT(x, y, width, height, format, type, pixels.byteLength(), data);
+    else
+        m_context->readPixels(x, y, width, height, format, type, data);
 }
 
 void WebGLRenderingContextBase::releaseShaderCompiler()
 }
 
 void WebGLRenderingContextBase::releaseShaderCompiler()
@@ -3024,11 +3275,11 @@ void WebGLRenderingContextBase::stencilOpSeparate(GC3Denum face, GC3Denum fail,
     m_context->stencilOpSeparate(face, fail, zfail, zpass);
 }
 
     m_context->stencilOpSeparate(face, fail, zfail, zpass);
 }
 
-void WebGLRenderingContextBase::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
+void WebGLRenderingContextBase::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
 {
     // FIXME: For now we ignore any errors returned.
     WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
 {
     // FIXME: For now we ignore any errors returned.
     WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
-    ASSERT(validateTexFuncParameters("texImage2D", TexImage, target, level, internalformat, width, height, border, format, type));
+    ASSERT(validateTexFuncParameters("texImage2D", TexImage, target, level, internalFormat, width, height, border, format, type));
     ASSERT(tex);
     ASSERT(validateNPOTTextureLevel(width, height, level, "texImage2D"));
     if (!pixels) {
     ASSERT(tex);
     ASSERT(validateNPOTTextureLevel(width, height, level, "texImage2D"));
     if (!pixels) {
@@ -3037,17 +3288,17 @@ void WebGLRenderingContextBase::texImage2DBase(GC3Denum target, GC3Dint level, G
         // can not be cleared with texImage2D and must be cleared by binding to an fbo and calling
         // clear.
         if (isResourceSafe())
         // can not be cleared with texImage2D and must be cleared by binding to an fbo and calling
         // clear.
         if (isResourceSafe())
-            m_context->texImage2D(target, level, internalformat, width, height, border, format, type, nullptr);
+            m_context->texImage2D(target, level, internalFormat, width, height, border, format, type, nullptr);
         else {
         else {
-            bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height,
+            bool succeed = m_context->texImage2DResourceSafe(target, level, internalFormat, width, height,
                                                              border, format, type, m_unpackAlignment);
             if (!succeed)
                 return;
         }
     } else {
                                                              border, format, type, m_unpackAlignment);
             if (!succeed)
                 return;
         }
     } else {
-        ASSERT(validateSettableTexFormat("texImage2D", internalformat));
+        ASSERT(validateSettableTexInternalFormat("texImage2D", internalFormat));
         m_context->moveErrorsToSyntheticErrorList();
         m_context->moveErrorsToSyntheticErrorList();
-        m_context->texImage2D(target, level, internalformat, width, height,
+        m_context->texImage2D(target, level, internalFormat, width, height,
                               border, format, type, pixels);
         if (m_context->moveErrorsToSyntheticErrorList()) {
             // The texImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
                               border, format, type, pixels);
         if (m_context->moveErrorsToSyntheticErrorList()) {
             // The texImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level.
@@ -3055,7 +3306,7 @@ void WebGLRenderingContextBase::texImage2DBase(GC3Denum target, GC3Dint level, G
             return;
         }
     }
             return;
         }
     }
-    tex->setLevelInfo(target, level, internalformat, width, height, type);
+    tex->setLevelInfo(target, level, internalFormat, width, height, type);
 }
 
 void WebGLRenderingContextBase::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
 }
 
 void WebGLRenderingContextBase::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
@@ -3087,9 +3338,9 @@ void WebGLRenderingContextBase::texImage2DImpl(GC3Denum target, GC3Dint level, G
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 }
 
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 }
 
-bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset)
+bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset)
 {
 {
-    if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, border, format, type))
+    if (!validateTexFuncParameters(functionName, functionType, target, level, internalFormat, width, height, border, format, type))
         return false;
 
     WebGLTexture* texture = validateTextureBinding(functionName, target, true);
         return false;
 
     WebGLTexture* texture = validateTextureBinding(functionName, target, true);
@@ -3102,11 +3353,11 @@ bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexFun
         // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat
         // by checking if the ArrayBufferView is null or not.
         if (sourceType != SourceArrayBufferView) {
         // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat
         // by checking if the ArrayBufferView is null or not.
         if (sourceType != SourceArrayBufferView) {
-            if (!validateSettableTexFormat(functionName, format))
+            if (!validateSettableTexInternalFormat(functionName, internalFormat))
                 return false;
         }
     } else {
                 return false;
         }
     } else {
-        if (!validateSettableTexFormat(functionName, format))
+        if (!validateSettableTexInternalFormat(functionName, internalFormat))
             return false;
         if (!validateSize(functionName, xoffset, yoffset))
             return false;
             return false;
         if (!validateSize(functionName, xoffset, yoffset))
             return false;
@@ -3119,7 +3370,7 @@ bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexFun
             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "dimensions out of range");
             return false;
         }
             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "dimensions out of range");
             return false;
         }
-        if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) {
+        if (texture->getInternalFormat(target, level) != internalFormat || texture->getType(target, level) != type) {
             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type and format do not match texture");
             return false;
         }
             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type and format do not match texture");
             return false;
         }
@@ -3128,10 +3379,10 @@ bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexFun
     return true;
 }
 
     return true;
 }
 
-void WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels)
+void WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels)
 {
 {
-    if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, internalformat, format, type, pixels.get(), NullAllowed)
-        || !validateTexFunc("texImage2D", TexImage, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0))
+    if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, internalFormat, format, type, pixels.get(), NullAllowed)
+        || !validateTexFunc("texImage2D", TexImage, SourceArrayBufferView, target, level, internalFormat, width, height, border, format, type, 0, 0))
         return;
     void* data = pixels ? pixels->baseAddress() : 0;
     Vector<uint8_t> tempData;
         return;
     void* data = pixels ? pixels->baseAddress() : 0;
     Vector<uint8_t> tempData;
@@ -3148,11 +3399,609 @@ void WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3De
     }
     if (changeUnpackAlignment)
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
     }
     if (changeUnpackAlignment)
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-    texImage2DBase(target, level, internalformat, width, height, border, format, type, data);
+    texImage2DBase(target, level, internalFormat, width, height, border, format, type, data);
+    if (changeUnpackAlignment)
+        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
+}
+
+void WebGLRenderingContextBase::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
+{
+    Vector<uint8_t> data;
+    GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
+    if (!imageExtractor.extractSucceeded()) {
+        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
+        return;
+    }
+    GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
+    GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
+    const void* imagePixelData = imageExtractor.imagePixelData();
+    
+    bool needConversion = true;
+    if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
+        needConversion = false;
+    else {
+        if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
+            return;
+        }
+    }
+    
+    if (m_unpackAlignment != 1)
+        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
+
+    texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, format, type, needConversion ? data.data() : imagePixelData);
+
+    if (m_unpackAlignment != 1)
+        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
+}
+
+void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels)
+{
+    if (isContextLostOrPending())
+        return;
+
+    WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true);
+    if (!texture)
+        return;
+
+    GC3Denum internalFormat = texture->getInternalFormat(target, level);
+    if (!internalFormat) {
+        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level");
+        return;
+    }
+
+    if (!validateTexFuncData("texSubImage2D", level, width, height, internalFormat, format, type, pixels.get(), NullNotAllowed))
+        return;
+
+    if (!validateTexFunc("texSubImage2D", TexSubImage, SourceArrayBufferView, target, level, internalFormat, width, height, 0, format, type, xoffset, yoffset))
+        return;
+    
+    void* data = pixels->baseAddress();
+    Vector<uint8_t> tempData;
+    bool changeUnpackAlignment = false;
+    if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
+        if (!m_context->extractTextureData(width, height, format, type, m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData))
+            return;
+        data = tempData.data();
+        changeUnpackAlignment = true;
+    }
+    if (changeUnpackAlignment)
+        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
+
+    texSubImage2DBase(target, level, xoffset, yoffset, width, height, internalFormat, format, type, data);
+
     if (changeUnpackAlignment)
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 }
 
     if (changeUnpackAlignment)
         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
 }
 
+ExceptionOr<void> WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Optional<TexImageSource>&& source)
+{
+    if (!source) {
+        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "source is null");
+        return { };
+    }
+
+    if (isContextLostOrPending())
+        return { };
+
+    auto visitor = WTF::makeVisitor([&](const RefPtr<ImageData>& pixels) -> ExceptionOr<void> {
+        WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true);
+        if (!texture)
+            return { };
+
+        GC3Denum internalFormat = texture->getInternalFormat(target, level);
+        if (!internalFormat) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level");
+            return { };
+        }
+
+        if (!validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, internalFormat, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
+            return { };
+
+        Vector<uint8_t> data;
+        bool needConversion = true;
+        // The data from ImageData is always of format RGBA8.
+        // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
+        if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
+            needConversion = false;
+        else {
+            if (!m_context->extractImageData(pixels.get(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
+                synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
+                return { };
+            }
+        }
+        if (m_unpackAlignment != 1)
+            m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
+
+        texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, format, type, needConversion ? data.data() : pixels->data()->data());
+
+        if (m_unpackAlignment != 1)
+            m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
+
+        return { };
+    } , [&](const RefPtr<HTMLImageElement>& image) -> ExceptionOr<void> {
+        if (wouldTaintOrigin(image.get()))
+            return Exception { SECURITY_ERR };
+        if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image.get()))
+            return { };
+
+        RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
+        if (!imageForRender)
+            return { };
+
+        if (imageForRender->isSVGImage())
+            imageForRender = drawImageIntoBuffer(*imageForRender, image->width(), image->height(), 1);
+
+        WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true);
+        if (!texture)
+            return { };
+
+        GC3Denum internalFormat = texture->getInternalFormat(target, level);
+        if (!internalFormat) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level");
+            return { };
+        }
+
+        if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLImageElement, target, level, internalFormat, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
+            return { };
+
+        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
+        return { };
+    }, [&](const RefPtr<HTMLCanvasElement>& canvas) -> ExceptionOr<void> {
+        if (wouldTaintOrigin(canvas.get()))
+            return Exception { SECURITY_ERR };
+        if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas.get()))
+            return { };
+
+        WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true);
+        if (!texture)
+            return { };
+
+        GC3Denum internalFormat = texture->getInternalFormat(target, level);
+        if (!internalFormat) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level");
+            return { };
+        }
+
+        if (!validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLCanvasElement, target, level, internalFormat, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
+            return { };
+
+        RefPtr<ImageData> imageData = canvas->getImageData();
+        if (imageData)
+            texSubImage2D(target, level, xoffset, yoffset, format, type, TexImageSource(imageData.get()));
+        else
+            texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
+        return { };
+    }, [&](const RefPtr<HTMLVideoElement>& video) -> ExceptionOr<void> {
+        if (wouldTaintOrigin(video.get()))
+            return Exception { SECURITY_ERR };
+        if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video.get()))
+            return { };
+
+        WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true);
+        if (!texture)
+            return { };
+
+        GC3Denum internalFormat = texture->getInternalFormat(target, level);
+        if (!internalFormat) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level");
+            return { };
+        }
+
+        if (!validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, internalFormat, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
+            return { };
+
+        RefPtr<Image> image = videoFrameToImage(video.get(), ImageBuffer::fastCopyImageMode());
+        if (!image)
+            return { };
+        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
+        return { };
+    });
+
+    return WTF::visit(visitor, source.value());
+}
+
+bool WebGLRenderingContextBase::validateArrayBufferType(const char* functionName, GC3Denum type, Optional<JSC::TypedArrayType> arrayType)
+{
+#define TYPE_VALIDATION_CASE(arrayTypeMacro) if (arrayType && arrayType.value() != JSC::arrayTypeMacro) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not " #arrayTypeMacro); \
+            return false; \
+        } \
+        break;
+
+    switch (type) {
+    case GraphicsContext3D::UNSIGNED_BYTE:
+        TYPE_VALIDATION_CASE(TypeUint8);
+    case GraphicsContext3D::BYTE:
+        TYPE_VALIDATION_CASE(TypeInt8);
+    case GraphicsContext3D::UNSIGNED_SHORT:
+    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
+    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
+    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
+        TYPE_VALIDATION_CASE(TypeUint16);
+    case GraphicsContext3D::SHORT:
+        TYPE_VALIDATION_CASE(TypeInt16);
+    case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
+    case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
+    case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV:
+    case GraphicsContext3D::UNSIGNED_INT_24_8:
+    case GraphicsContext3D::UNSIGNED_INT:
+        TYPE_VALIDATION_CASE(TypeUint32);
+    case GraphicsContext3D::INT:
+        TYPE_VALIDATION_CASE(TypeInt32);
+    case GraphicsContext3D::FLOAT: // OES_texture_float
+        TYPE_VALIDATION_CASE(TypeFloat32);
+    case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
+    case GraphicsContext3D::HALF_FLOAT:
+    case GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV:
+        // As per the specification, ArrayBufferView should be null when
+        // OES_texture_half_float is enabled.
+        if (arrayType) {
+            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
+            return false;
+        }
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+#undef TYPE_VALIDATION_CASE
+    return true;
+}
+
+bool WebGLRenderingContextBase::validateTexFuncData(const char* functionName, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum internalFormat, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, NullDisposition disposition)
+{
+    if (!pixels) {
+        if (disposition == NullAllowed)
+            return true;
+        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
+        return false;
+    }
+
+    if (!validateTexFuncFormatAndType(functionName, internalFormat, format, type, level))
+        return false;
+    if (!validateSettableTexInternalFormat(functionName, internalFormat))
+        return false;
+    if (!validateArrayBufferType(functionName, type, pixels ? Optional<JSC::TypedArrayType>(pixels->getType()) : Nullopt))
+        return false;
+    
+    unsigned totalBytesRequired;
+    GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
+    if (error != GraphicsContext3D::NO_ERROR) {
+        synthesizeGLError(error, functionName, "invalid texture dimensions");
+        return false;
+    }
+    if (pixels->byteLength() < totalBytesRequired) {
+        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
+        return false;
+    }
+    return true;
+}
+
+bool WebGLRenderingContextBase::validateTexFuncParameters(const char* functionName,
+    TexFuncValidationFunctionType functionType,
+    GC3Denum target, GC3Dint level,
+    GC3Denum internalformat,
+    GC3Dsizei width, GC3Dsizei height, GC3Dint border,
+    GC3Denum format, GC3Denum type)
+{
+    // We absolutely have to validate the format and type combination.
+    // The texImage2D entry points taking HTMLImage, etc. will produce
+    // temporary data based on this combination, so it must be legal.
+    if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level) || !validateTexFuncLevel(functionName, target, level))
+        return false;
+    
+    if (width < 0 || height < 0) {
+        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
+        return false;
+    }
+    
+    GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
+    switch (target) {
+    case GraphicsContext3D::TEXTURE_2D:
+        if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
+            return false;
+        }
+        break;
+    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
+    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
+    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
+    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
+    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
+    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
+        if (functionType != TexSubImage && width != height) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
+            return false;
+        }
+        // No need to check height here. For texImage width == height.
+        // For texSubImage that will be checked when checking yoffset + height is in range.
+        if (width > maxTextureSizeForLevel) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
+            return false;
+        }
+        break;
+    default:
+        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
+        return false;
+    }
+    
+    if (border) {
+        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
+        return false;
+    }
+    
+    return true;
+}
+
+bool WebGLRenderingContextBase::validateTexFuncFormatAndType(const char* functionName, GC3Denum internalFormat, GC3Denum format, GC3Denum type, GC3Dint level)
+{
+    switch (format) {
+    case GraphicsContext3D::ALPHA:
+    case GraphicsContext3D::LUMINANCE:
+    case GraphicsContext3D::LUMINANCE_ALPHA:
+    case GraphicsContext3D::RGB:
+    case GraphicsContext3D::RGBA:
+        break;
+    case GraphicsContext3D::DEPTH_STENCIL:
+    case GraphicsContext3D::DEPTH_COMPONENT:
+        if (!m_webglDepthTexture && isWebGL1()) {
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
+            return false;
+        }
+        if (level > 0) {
+            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for depth formats");
+            return false;
+        }
+        break;
+    case Extensions3D::SRGB_EXT:
+    case Extensions3D::SRGB_ALPHA_EXT:
+        if (!m_extsRGB) {
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "sRGB texture formats not enabled");
+            return false;
+        }
+        break;
+    default:
+#if ENABLE(WEBGL2)
+        if (!isWebGL1()) {
+            switch (format) {
+            case GraphicsContext3D::RED:
+            case GraphicsContext3D::RED_INTEGER:
+            case GraphicsContext3D::RG:
+            case GraphicsContext3D::RG_INTEGER:
+            case GraphicsContext3D::RGB_INTEGER:
+            case GraphicsContext3D::RGBA_INTEGER:
+                break;
+            default:
+                synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
+                return false;
+            }
+        } else
+#endif
+        {
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
+            return false;
+        }
+    }
+
+    switch (type) {
+    case GraphicsContext3D::UNSIGNED_BYTE:
+    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
+    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
+    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
+        break;
+    case GraphicsContext3D::FLOAT:
+        if (!m_oesTextureFloat && isWebGL1()) {
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
+            return false;
+        }
+        break;
+    case GraphicsContext3D::HALF_FLOAT:
+    case GraphicsContext3D::HALF_FLOAT_OES:
+        if (!m_oesTextureHalfFloat && isWebGL1()) {
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
+            return false;
+        }
+        break;
+    case GraphicsContext3D::UNSIGNED_INT:
+    case GraphicsContext3D::UNSIGNED_INT_24_8:
+    case GraphicsContext3D::UNSIGNED_SHORT:
+        if (!m_webglDepthTexture && isWebGL1()) {
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
+            return false;
+        }
+        break;
+    default:
+#if ENABLE(WEBGL2)
+        if (!isWebGL1()) {
+            switch (type) {
+            case GraphicsContext3D::BYTE:
+            case GraphicsContext3D::SHORT:
+            case GraphicsContext3D::INT:
+            case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
+            case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
+            case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV:
+            case GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV:
+                break;
+            default:
+                synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
+                return false;
+            }
+        } else
+#endif
+        {
+            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
+            return false;
+        }
+    }
+    
+    // Verify that the combination of internalformat, format, and type is supported.
+#define INTERNAL_FORMAT_CASE(internalFormatMacro, formatMacro, type0, type1, type2, type3, type4) case GraphicsContext3D::internalFormatMacro: \
+    if (format != GraphicsContext3D::formatMacro) { \
+        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format for internalformat"); \
+        return false; \
+    } \
+    if (type != type0 && type != type1 && type != type2 && type != type3 && type != type4) { \
+        if (type != GraphicsContext3D::HALF_FLOAT_OES || (type0 != GraphicsContext3D::HALF_FLOAT && type1 != GraphicsContext3D::HALF_FLOAT && type2 != GraphicsContext3D::HALF_FLOAT && type3 != GraphicsContext3D::HALF_FLOAT)) { \
+            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for internalformat"); \
+            return false; \
+        } \
+    } \
+    break;
+    switch (internalFormat) {
+    INTERNAL_FORMAT_CASE(RGB               , RGB            , GraphicsContext3D::UNSIGNED_BYTE                 , GraphicsContext3D::UNSIGNED_SHORT_5_6_5  , GraphicsContext3D::HALF_FLOAT                  , GraphicsContext3D::FLOAT     , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA              , RGBA           , GraphicsContext3D::UNSIGNED_BYTE                 , GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4, GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1      , GraphicsContext3D::HALF_FLOAT, GraphicsContext3D::FLOAT);
+    INTERNAL_FORMAT_CASE(LUMINANCE_ALPHA   , LUMINANCE_ALPHA, GraphicsContext3D::UNSIGNED_BYTE                 , GraphicsContext3D::HALF_FLOAT            , GraphicsContext3D::FLOAT                       , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(LUMINANCE         , LUMINANCE      , GraphicsContext3D::UNSIGNED_BYTE                 , GraphicsContext3D::HALF_FLOAT            , GraphicsContext3D::FLOAT                       , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(ALPHA             , ALPHA          , GraphicsContext3D::UNSIGNED_BYTE                 , GraphicsContext3D::HALF_FLOAT            , GraphicsContext3D::FLOAT                       , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R8                , RED            , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R8_SNORM          , RED            , GraphicsContext3D::BYTE                          , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R16F              , RED            , GraphicsContext3D::HALF_FLOAT                    , GraphicsContext3D::FLOAT                 , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R32F              , RED            , GraphicsContext3D::FLOAT                         , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R8UI              , RED_INTEGER    , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R8I               , RED_INTEGER    , GraphicsContext3D::BYTE                          , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R16UI             , RED_INTEGER    , GraphicsContext3D::UNSIGNED_SHORT                , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R16I              , RED_INTEGER    , GraphicsContext3D::SHORT                         , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R32UI             , RED_INTEGER    , GraphicsContext3D::UNSIGNED_INT                  , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R32I              , RED_INTEGER    , GraphicsContext3D::INT                           , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG8               , RG             , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG8_SNORM         , RG             , GraphicsContext3D::BYTE                          , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG16F             , RG             , GraphicsContext3D::HALF_FLOAT                    , GraphicsContext3D::FLOAT                 , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG32F             , RG             , GraphicsContext3D::FLOAT                         , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG8UI             , RG_INTEGER     , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG8I              , RG_INTEGER     , GraphicsContext3D::BYTE                          , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG16UI            , RG_INTEGER     , GraphicsContext3D::UNSIGNED_SHORT                , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG16I             , RG_INTEGER     , GraphicsContext3D::SHORT                         , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG32UI            , RG_INTEGER     , GraphicsContext3D::UNSIGNED_INT                  , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RG32I             , RG_INTEGER     , GraphicsContext3D::INT                           , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB8              , RGB            , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(SRGB8             , RGB            , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB565            , RGB            , GraphicsContext3D::UNSIGNED_BYTE                 , GraphicsContext3D::UNSIGNED_SHORT_5_6_5  , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB8_SNORM        , RGB            , GraphicsContext3D::BYTE                          , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(R11F_G11F_B10F    , RGB            , GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV  , GraphicsContext3D::HALF_FLOAT            , GraphicsContext3D::FLOAT                       , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB9_E5           , RGB            , GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV      , GraphicsContext3D::HALF_FLOAT            , GraphicsContext3D::FLOAT                       , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB16F            , RGB            , GraphicsContext3D::HALF_FLOAT                    , GraphicsContext3D::FLOAT                 , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB32F            , RGB            , GraphicsContext3D::FLOAT                         , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB8UI            , RGB_INTEGER    , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB8I             , RGB_INTEGER    , GraphicsContext3D::BYTE                          , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB16UI           , RGB_INTEGER    , GraphicsContext3D::UNSIGNED_SHORT                , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB16I            , RGB_INTEGER    , GraphicsContext3D::SHORT                         , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB32UI           , RGB_INTEGER    , GraphicsContext3D::UNSIGNED_INT                  , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB32I            , RGB_INTEGER    , GraphicsContext3D::INT                           , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA8             , RGBA           , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(SRGB8_ALPHA8      , RGBA           , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA8_SNORM       , RGBA           , GraphicsContext3D::BYTE                          , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB5_A1           , RGBA           , GraphicsContext3D::UNSIGNED_BYTE                 , GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1, GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA4             , RGBA           , GraphicsContext3D::UNSIGNED_BYTE                 , GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4, 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB10_A2          , RGBA           , GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV   , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA16F           , RGBA           , GraphicsContext3D::HALF_FLOAT                    , GraphicsContext3D::FLOAT                 , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA32F           , RGBA           , GraphicsContext3D::FLOAT                         , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA8UI           , RGBA_INTEGER   , GraphicsContext3D::UNSIGNED_BYTE                 , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA8I            , RGBA_INTEGER   , GraphicsContext3D::BYTE                          , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGB10_A2UI        , RGBA_INTEGER   , GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV   , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA16UI          , RGBA_INTEGER   , GraphicsContext3D::UNSIGNED_SHORT                , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA16I           , RGBA_INTEGER   , GraphicsContext3D::SHORT                         , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA32I           , RGBA_INTEGER   , GraphicsContext3D::INT                           , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(RGBA32UI          , RGBA_INTEGER   , GraphicsContext3D::UNSIGNED_INT                  , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(DEPTH_COMPONENT   , DEPTH_COMPONENT, GraphicsContext3D::UNSIGNED_SHORT                , GraphicsContext3D::UNSIGNED_INT          , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(DEPTH_COMPONENT16 , DEPTH_COMPONENT, GraphicsContext3D::UNSIGNED_SHORT                , GraphicsContext3D::UNSIGNED_INT          , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(DEPTH_COMPONENT24 , DEPTH_COMPONENT, GraphicsContext3D::UNSIGNED_INT                  , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(DEPTH_COMPONENT32F, DEPTH_COMPONENT, GraphicsContext3D::FLOAT                         , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(DEPTH_STENCIL     , DEPTH_STENCIL  , GraphicsContext3D::UNSIGNED_INT_24_8             , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(DEPTH24_STENCIL8  , DEPTH_STENCIL  , GraphicsContext3D::UNSIGNED_INT_24_8             , 0                                        , 0                                              , 0                            , 0                       );
+    INTERNAL_FORMAT_CASE(DEPTH32F_STENCIL8 , DEPTH_STENCIL  , GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV, 0                                        , 0                                              , 0                            , 0                       );
+    case Extensions3D::SRGB_EXT:
+        if (format != internalFormat) {
+            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format and internalformat must match");
+            return false;
+        }
+        if (type != GraphicsContext3D::UNSIGNED_BYTE && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5 && type != GraphicsContext3D::FLOAT && type != GraphicsContext3D::HALF_FLOAT_OES && type != GraphicsContext3D::HALF_FLOAT) {
+            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for internal format");
+            return false;
+        }
+        break;
+    case Extensions3D::SRGB_ALPHA_EXT:
+        if (format != internalFormat) {
+            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format and internalformat must match");
+            return false;
+        }
+        if (type != GraphicsContext3D::UNSIGNED_BYTE && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1 && type != GraphicsContext3D::FLOAT && type != GraphicsContext3D::HALF_FLOAT_OES && type != GraphicsContext3D::HALF_FLOAT) {
+            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for internal format");
+            return false;
+        }
+        break;
+    default:
+        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "Unknown internal format");
+        return false;
+    }
+#undef INTERNAL_FORMAT_CASE
+    
+    return true;
+}
+
+void WebGLRenderingContextBase::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalFormat, GC3Denum format, GC3Denum type, const void* pixels)
+{
+    ASSERT(!isContextLost());
+    ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage, target, level, internalFormat, width, height, 0, format, type));
+    ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
+    ASSERT(validateSettableTexInternalFormat("texSubImage2D", internalFormat));
+    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
+    if (!tex) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+    ASSERT((xoffset + width) >= 0);
+    ASSERT((yoffset + height) >= 0);
+    ASSERT(tex->getWidth(target, level) >= (xoffset + width));
+    ASSERT(tex->getHeight(target, level) >= (yoffset + height));
+    ASSERT_UNUSED(internalFormat, tex->getInternalFormat(target, level) == internalFormat);
+    m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+
+void WebGLRenderingContextBase::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
+{
+    if (isContextLostOrPending())
+        return;
+    if (!validateTexFuncParameters("copyTexImage2D", CopyTexImage, target, level, internalFormat, width, height, border, internalFormat, GraphicsContext3D::UNSIGNED_BYTE))
+        return;
+    if (!validateSettableTexInternalFormat("copyTexImage2D", internalFormat))
+        return;
+    WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
+    if (!tex)
+        return;
+    if (!isTexInternalFormatColorBufferCombinationValid(internalFormat, getBoundFramebufferColorFormat())) {
+        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
+        return;
+    }
+    if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
+        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
+        return;
+    }
+    const char* reason = "framebuffer incomplete";
+    if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
+        synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
+        return;
+    }
+    clearIfComposited();
+    if (isResourceSafe())
+        m_context->copyTexImage2D(target, level, internalFormat, x, y, width, height, border);
+    else {
+        GC3Dint clippedX, clippedY;
+        GC3Dsizei clippedWidth, clippedHeight;
+        if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
+            m_context->texImage2DResourceSafe(target, level, internalFormat, width, height, border,
+                internalFormat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
+            if (clippedWidth > 0 && clippedHeight > 0) {
+                m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
+                    clippedX, clippedY, clippedWidth, clippedHeight);
+            }
+        } else
+            m_context->copyTexImage2D(target, level, internalFormat, x, y, width, height, border);
+    }
+    // FIXME: if the framebuffer is not complete, none of the below should be executed.
+    tex->setLevelInfo(target, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+}
+
 ExceptionOr<void> WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Optional<TexImageSource> source)
 {
     if (!source) {
 ExceptionOr<void> WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Optional<TexImageSource> source)
 {
     if (!source) {
index d9b16f8..66dc0d1 100644 (file)
@@ -150,7 +150,7 @@ public:
     void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, ArrayBufferView& data);
     void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& data);
 
     void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, ArrayBufferView& data);
     void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& data);
 
-    virtual void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) = 0;
+    void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
     void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
 
     RefPtr<WebGLBuffer> createBuffer();
     void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
 
     RefPtr<WebGLBuffer> createBuffer();
@@ -246,8 +246,8 @@ public:
     void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
     void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
 
     void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
     void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
 
-    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&) = 0;
-    virtual ExceptionOr<void> texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Optional<TexImageSource>&&) = 0;
+    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&);
+    ExceptionOr<void> texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Optional<TexImageSource>&&);
 
     void uniform1f(const WebGLUniformLocation*, GC3Dfloat x);
     void uniform1fv(const WebGLUniformLocation*, Float32Array& v);
 
     void uniform1f(const WebGLUniformLocation*, GC3Dfloat x);
     void uniform1fv(const WebGLUniformLocation*, Float32Array& v);
@@ -594,8 +594,8 @@ protected:
 
     void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels);
     void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha);
 
     void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels);
     void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha);
-    virtual void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels) = 0;
-    virtual void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha) = 0;
+    void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels);
+    void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha);
 
     bool checkTextureCompleteness(const char*, bool);
 
 
     bool checkTextureCompleteness(const char*, bool);
 
@@ -634,7 +634,7 @@ protected:
 
     // Helper function to check input format/type for functions {copy}Tex{Sub}Image.
     // Generates GL error and returns false if parameters are invalid.
 
     // Helper function to check input format/type for functions {copy}Tex{Sub}Image.
     // Generates GL error and returns false if parameters are invalid.
-    virtual bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level) = 0;
+    bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level);
 
     // Helper function to check input level for functions {copy}Tex{Sub}Image.
     // Generates GL error and returns false if level is invalid.
 
     // Helper function to check input level for functions {copy}Tex{Sub}Image.
     // Generates GL error and returns false if level is invalid.
@@ -661,12 +661,12 @@ protected:
 
     // Helper function to check input parameters for functions {copy}Tex{Sub}Image.
     // Generates GL error and returns false if parameters are invalid.
 
     // Helper function to check input parameters for functions {copy}Tex{Sub}Image.
     // Generates GL error and returns false if parameters are invalid.
-    virtual bool validateTexFuncParameters(const char* functionName,
+    bool validateTexFuncParameters(const char* functionName,
         TexFuncValidationFunctionType,
         GC3Denum target, GC3Dint level,
         GC3Denum internalformat,
         GC3Dsizei width, GC3Dsizei height, GC3Dint border,
         TexFuncValidationFunctionType,
         GC3Denum target, GC3Dint level,
         GC3Denum internalformat,
         GC3Dsizei width, GC3Dsizei height, GC3Dint border,
-        GC3Denum format, GC3Denum type) = 0;
+        GC3Denum format, GC3Denum type);
 
     enum NullDisposition {
         NullAllowed,
 
     enum NullDisposition {
         NullAllowed,
@@ -676,17 +676,17 @@ protected:
     // Helper function to validate that the given ArrayBufferView
     // is of the correct type and contains enough data for the texImage call.
     // Generates GL error and returns false if parameters are invalid.
     // Helper function to validate that the given ArrayBufferView
     // is of the correct type and contains enough data for the texImage call.
     // Generates GL error and returns false if parameters are invalid.
-    virtual bool validateTexFuncData(const char* functionName, GC3Dint level,
+    bool validateTexFuncData(const char* functionName, GC3Dint level,
         GC3Dsizei width, GC3Dsizei height,
         GC3Denum internalformat, GC3Denum format, GC3Denum type,
         ArrayBufferView* pixels,
         GC3Dsizei width, GC3Dsizei height,
         GC3Denum internalformat, GC3Denum format, GC3Denum type,
         ArrayBufferView* pixels,
-        NullDisposition) = 0;
+        NullDisposition);
 
     // Helper function to validate a given texture format is settable as in
     // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and
     // copyTexSubImage2D.
     // Generates GL error and returns false if the format is not settable.
 
     // Helper function to validate a given texture format is settable as in
     // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and
     // copyTexSubImage2D.
     // Generates GL error and returns false if the format is not settable.
-    bool validateSettableTexFormat(const char* functionName, GC3Denum format);
+    bool validateSettableTexInternalFormat(const char* functionName, GC3Denum format);
 
     // Helper function to validate compressed texture data is correct size
     // for the given format and dimensions.
 
     // Helper function to validate compressed texture data is correct size
     // for the given format and dimensions.
@@ -804,6 +804,9 @@ protected:
 
     // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements.
     bool supportsDrawBuffers();
 
     // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements.
     bool supportsDrawBuffers();
+
+private:
+    bool validateArrayBufferType(const char* functionName, GC3Denum type, Optional<JSC::TypedArrayType>);
 };
 
 } // namespace WebCore
 };
 
 } // namespace WebCore
index 4ce484e..6edf7ae 100644 (file)
@@ -167,20 +167,26 @@ bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, G
 bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format, GC3Denum type, unsigned int* componentsPerPixel, unsigned int* bytesPerComponent)
 {
     switch (format) {
 bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format, GC3Denum type, unsigned int* componentsPerPixel, unsigned int* bytesPerComponent)
 {
     switch (format) {
+    case GraphicsContext3D::RED:
+    case GraphicsContext3D::RED_INTEGER:
     case GraphicsContext3D::ALPHA:
     case GraphicsContext3D::LUMINANCE:
     case GraphicsContext3D::DEPTH_COMPONENT:
     case GraphicsContext3D::DEPTH_STENCIL:
         *componentsPerPixel = 1;
         break;
     case GraphicsContext3D::ALPHA:
     case GraphicsContext3D::LUMINANCE:
     case GraphicsContext3D::DEPTH_COMPONENT:
     case GraphicsContext3D::DEPTH_STENCIL:
         *componentsPerPixel = 1;
         break;
+    case GraphicsContext3D::RG:
+    case GraphicsContext3D::RG_INTEGER:
     case GraphicsContext3D::LUMINANCE_ALPHA:
         *componentsPerPixel = 2;
         break;
     case GraphicsContext3D::RGB:
     case GraphicsContext3D::LUMINANCE_ALPHA:
         *componentsPerPixel = 2;
         break;
     case GraphicsContext3D::RGB:
+    case GraphicsContext3D::RGB_INTEGER:
     case Extensions3D::SRGB_EXT:
         *componentsPerPixel = 3;
         break;
     case GraphicsContext3D::RGBA:
     case Extensions3D::SRGB_EXT:
         *componentsPerPixel = 3;
         break;
     case GraphicsContext3D::RGBA:
+    case GraphicsContext3D::RGBA_INTEGER:
     case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888
     case Extensions3D::SRGB_ALPHA_EXT:
         *componentsPerPixel = 4;
     case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888
     case Extensions3D::SRGB_ALPHA_EXT:
         *componentsPerPixel = 4;
@@ -188,13 +194,20 @@ bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format, GC3Denum
     default:
         return false;
     }
     default:
         return false;
     }
+
     switch (type) {
     case GraphicsContext3D::UNSIGNED_BYTE:
         *bytesPerComponent = sizeof(GC3Dubyte);
         break;
     switch (type) {
     case GraphicsContext3D::UNSIGNED_BYTE:
         *bytesPerComponent = sizeof(GC3Dubyte);
         break;
+    case GraphicsContext3D::BYTE:
+        *bytesPerComponent = sizeof(GC3Dbyte);
+        break;
     case GraphicsContext3D::UNSIGNED_SHORT:
         *bytesPerComponent = sizeof(GC3Dushort);
         break;
     case GraphicsContext3D::UNSIGNED_SHORT:
         *bytesPerComponent = sizeof(GC3Dushort);
         break;
+    case GraphicsContext3D::SHORT:
+        *bytesPerComponent = sizeof(GC3Dshort);
+        break;
     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
@@ -202,21 +215,113 @@ bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format, GC3Denum
         *bytesPerComponent = sizeof(GC3Dushort);
         break;
     case GraphicsContext3D::UNSIGNED_INT_24_8:
         *bytesPerComponent = sizeof(GC3Dushort);
         break;
     case GraphicsContext3D::UNSIGNED_INT_24_8:
+    case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
+    case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
+    case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV:
+        *componentsPerPixel = 1;
+        *bytesPerComponent = sizeof(GC3Duint);
+        break;
     case GraphicsContext3D::UNSIGNED_INT:
         *bytesPerComponent = sizeof(GC3Duint);
         break;
     case GraphicsContext3D::UNSIGNED_INT:
         *bytesPerComponent = sizeof(GC3Duint);
         break;
+    case GraphicsContext3D::INT:
+        *bytesPerComponent = sizeof(GC3Dint);
+        break;
     case GraphicsContext3D::FLOAT: // OES_texture_float
         *bytesPerComponent = sizeof(GC3Dfloat);
         break;
     case GraphicsContext3D::FLOAT: // OES_texture_float
         *bytesPerComponent = sizeof(GC3Dfloat);
         break;
+    case GraphicsContext3D::HALF_FLOAT:
     case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
         *bytesPerComponent = sizeof(GC3Dhalffloat);
         break;
     case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
         *bytesPerComponent = sizeof(GC3Dhalffloat);
         break;
+    case GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV:
+        *bytesPerComponent = sizeof(GC3Dfloat) + sizeof(GC3Duint);
+        break;
     default:
         return false;
     }
     return true;
 }
 
     default:
         return false;
     }
     return true;
 }
 
+bool GraphicsContext3D::possibleFormatAndTypeForInternalFormat(GC3Denum internalFormat, GC3Denum& format, GC3Denum& type)
+{
+#define POSSIBLE_FORMAT_TYPE_CASE(internalFormatMacro, formatMacro, typeMacro) case internalFormatMacro: \
+        format = formatMacro; \
+        type = GraphicsContext3D::typeMacro; \
+        break;
+
+    switch (internalFormat) {
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB               , GraphicsContext3D::RGB            , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA              , GraphicsContext3D::RGBA           , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::LUMINANCE_ALPHA   , GraphicsContext3D::LUMINANCE_ALPHA, UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::LUMINANCE         , GraphicsContext3D::LUMINANCE      , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::ALPHA             , GraphicsContext3D::ALPHA          , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8                , GraphicsContext3D::RED            , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8_SNORM          , GraphicsContext3D::RED            , BYTE                          );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R16F              , GraphicsContext3D::RED            , HALF_FLOAT                    );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R32F              , GraphicsContext3D::RED            , FLOAT                         );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8UI              , GraphicsContext3D::RED_INTEGER    , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8I               , GraphicsContext3D::RED_INTEGER    , BYTE                          );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R16UI             , GraphicsContext3D::RED_INTEGER    , UNSIGNED_SHORT                );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R16I              , GraphicsContext3D::RED_INTEGER    , SHORT                         );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R32UI             , GraphicsContext3D::RED_INTEGER    , UNSIGNED_INT                  );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R32I              , GraphicsContext3D::RED_INTEGER    , INT                           );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8               , GraphicsContext3D::RG             , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8_SNORM         , GraphicsContext3D::RG             , BYTE                          );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG16F             , GraphicsContext3D::RG             , HALF_FLOAT                    );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG32F             , GraphicsContext3D::RG             , FLOAT                         );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8UI             , GraphicsContext3D::RG_INTEGER     , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8I              , GraphicsContext3D::RG_INTEGER     , BYTE                          );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG16UI            , GraphicsContext3D::RG_INTEGER     , UNSIGNED_SHORT                );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG16I             , GraphicsContext3D::RG_INTEGER     , SHORT                         );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG32UI            , GraphicsContext3D::RG_INTEGER     , UNSIGNED_INT                  );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG32I             , GraphicsContext3D::RG_INTEGER     , INT                           );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8              , GraphicsContext3D::RGB            , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::SRGB8             , GraphicsContext3D::RGB            , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB565            , GraphicsContext3D::RGB            , UNSIGNED_SHORT_5_6_5          );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8_SNORM        , GraphicsContext3D::RGB            , BYTE                          );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R11F_G11F_B10F    , GraphicsContext3D::RGB            , UNSIGNED_INT_10F_11F_11F_REV  );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB9_E5           , GraphicsContext3D::RGB            , UNSIGNED_INT_5_9_9_9_REV      );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB16F            , GraphicsContext3D::RGB            , HALF_FLOAT                    );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB32F            , GraphicsContext3D::RGB            , FLOAT                         );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8UI            , GraphicsContext3D::RGB_INTEGER    , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8I             , GraphicsContext3D::RGB_INTEGER    , BYTE                          );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB16UI           , GraphicsContext3D::RGB_INTEGER    , UNSIGNED_SHORT                );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB16I            , GraphicsContext3D::RGB_INTEGER    , SHORT                         );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB32UI           , GraphicsContext3D::RGB_INTEGER    , UNSIGNED_INT                  );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB32I            , GraphicsContext3D::RGB_INTEGER    , INT                           );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8             , GraphicsContext3D::RGBA           , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::SRGB8_ALPHA8      , GraphicsContext3D::RGBA           , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8_SNORM       , GraphicsContext3D::RGBA           , BYTE                          );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB5_A1           , GraphicsContext3D::RGBA           , UNSIGNED_SHORT_5_5_5_1        );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA4             , GraphicsContext3D::RGBA           , UNSIGNED_SHORT_4_4_4_4        );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB10_A2          , GraphicsContext3D::RGBA           , UNSIGNED_INT_2_10_10_10_REV   );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA16F           , GraphicsContext3D::RGBA           , HALF_FLOAT                    );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA32F           , GraphicsContext3D::RGBA           , FLOAT                         );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8UI           , GraphicsContext3D::RGBA_INTEGER   , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8I            , GraphicsContext3D::RGBA_INTEGER   , BYTE                          );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB10_A2UI        , GraphicsContext3D::RGBA_INTEGER   , UNSIGNED_INT_2_10_10_10_REV   );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA16UI          , GraphicsContext3D::RGBA_INTEGER   , UNSIGNED_SHORT                );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA16I           , GraphicsContext3D::RGBA_INTEGER   , SHORT                         );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA32I           , GraphicsContext3D::RGBA_INTEGER   , INT                           );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA32UI          , GraphicsContext3D::RGBA_INTEGER   , UNSIGNED_INT                  );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT16 , GraphicsContext3D::DEPTH_COMPONENT, UNSIGNED_SHORT                );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT   , GraphicsContext3D::DEPTH_COMPONENT, UNSIGNED_SHORT                );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT24 , GraphicsContext3D::DEPTH_COMPONENT, UNSIGNED_INT                  );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT32F, GraphicsContext3D::DEPTH_COMPONENT, FLOAT                         );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_STENCIL     , GraphicsContext3D::DEPTH_STENCIL  , UNSIGNED_INT_24_8             );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH24_STENCIL8  , GraphicsContext3D::DEPTH_STENCIL  , UNSIGNED_INT_24_8             );
+    POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH32F_STENCIL8 , GraphicsContext3D::DEPTH_STENCIL  , FLOAT_32_UNSIGNED_INT_24_8_REV);
+    POSSIBLE_FORMAT_TYPE_CASE(Extensions3D::SRGB_EXT               , Extensions3D::SRGB_EXT            , UNSIGNED_BYTE                 );
+    POSSIBLE_FORMAT_TYPE_CASE(Extensions3D::SRGB_ALPHA_EXT         , Extensions3D::SRGB_ALPHA_EXT      , UNSIGNED_BYTE                 );
+    default:
+        return false;
+    }
+#undef POSSIBLE_FORMAT_TYPE_CASE
+
+    return true;
+}
+
 GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment, unsigned int* imageSizeInBytes, unsigned int* paddingInBytes)
 {
     ASSERT(imageSizeInBytes);
 GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment, unsigned int* imageSizeInBytes, unsigned int* paddingInBytes)
 {
     ASSERT(imageSizeInBytes);
@@ -261,7 +366,7 @@ GraphicsContext3D::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomSour
     m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile);
 }
 
     m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile);
 }
 
-bool GraphicsContext3D::packImageData( Image* image, const void* pixels, GC3Denum format, GC3Denum type, bool flipY, AlphaOp alphaOp, DataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector<uint8_t>& data)
+bool GraphicsContext3D::packImageData(Image* image, const void* pixels, GC3Denum format, GC3Denum type, bool flipY, AlphaOp alphaOp, DataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector<uint8_t>& data)
 {
     if (!pixels)
         return false;
 {
     if (!pixels)
         return false;
@@ -361,6 +466,29 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, DataFormat sourceD
     int remainder = sourceUnpackAlignment ? (validSrc % sourceUnpackAlignment) : 0;
     int srcStride = remainder ? (validSrc + sourceUnpackAlignment - remainder) : validSrc;
 
     int remainder = sourceUnpackAlignment ? (validSrc % sourceUnpackAlignment) : 0;
     int srcStride = remainder ? (validSrc + sourceUnpackAlignment - remainder) : validSrc;
 
+    // FIXME: Implement packing pixels to WebGL 2 formats
+    switch (destinationFormat) {
+    case GraphicsContext3D::RED:
+    case GraphicsContext3D::RED_INTEGER:
+    case GraphicsContext3D::RG:
+    case GraphicsContext3D::RG_INTEGER:
+    case GraphicsContext3D::RGB_INTEGER:
+    case GraphicsContext3D::RGBA_INTEGER:
+    case GraphicsContext3D::DEPTH_COMPONENT:
+    case GraphicsContext3D::DEPTH_STENCIL:
+        return false;
+    }
+    switch (destinationType) {
+    case GraphicsContext3D::BYTE:
+    case GraphicsContext3D::SHORT:
+    case GraphicsContext3D::INT:
+    case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
+    case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
+    case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV:
+    case GraphicsContext3D::UNSIGNED_INT_24_8:
+        return false;
+    }
+
     DataFormat dstDataFormat = getDataFormat(destinationFormat, destinationType);
     int dstStride = width * TexelBytesForFormat(dstDataFormat);
     if (flipY) {
     DataFormat dstDataFormat = getDataFormat(destinationFormat, destinationType);
     int dstStride = width * TexelBytesForFormat(dstDataFormat);
     if (flipY) {
@@ -424,24 +552,73 @@ unsigned GraphicsContext3D::getClearBitsByAttachmentType(GC3Denum attachment)
 unsigned GraphicsContext3D::getClearBitsByFormat(GC3Denum format)
 {
     switch (format) {
 unsigned GraphicsContext3D::getClearBitsByFormat(GC3Denum format)
 {
     switch (format) {
-    case GraphicsContext3D::ALPHA:
-    case GraphicsContext3D::LUMINANCE:
-    case GraphicsContext3D::LUMINANCE_ALPHA:
     case GraphicsContext3D::RGB:
     case GraphicsContext3D::RGB:
-    case GraphicsContext3D::RGB565:
     case GraphicsContext3D::RGBA:
     case GraphicsContext3D::RGBA:
-    case GraphicsContext3D::RGBA4:
+    case GraphicsContext3D::LUMINANCE_ALPHA:
+    case GraphicsContext3D::LUMINANCE:
+    case GraphicsContext3D::ALPHA:
+    case GraphicsContext3D::R8:
+    case GraphicsContext3D::R8_SNORM:
+    case GraphicsContext3D::R16F:
+    case GraphicsContext3D::R32F:
+    case GraphicsContext3D::R8UI:
+    case GraphicsContext3D::R8I:
+    case GraphicsContext3D::R16UI:
+    case GraphicsContext3D::R16I:
+    case GraphicsContext3D::R32UI:
+    case GraphicsContext3D::R32I:
+    case GraphicsContext3D::RG8:
+    case GraphicsContext3D::RG8_SNORM:
+    case GraphicsContext3D::RG16F:
+    case GraphicsContext3D::RG32F:
+    case GraphicsContext3D::RG8UI:
+    case GraphicsContext3D::RG8I:
+    case GraphicsContext3D::RG16UI:
+    case GraphicsContext3D::RG16I:
+    case GraphicsContext3D::RG32UI:
+    case GraphicsContext3D::RG32I:
+    case GraphicsContext3D::RGB8:
+    case GraphicsContext3D::SRGB8:
+    case GraphicsContext3D::RGB565:
+    case GraphicsContext3D::RGB8_SNORM:
+    case GraphicsContext3D::R11F_G11F_B10F:
+    case GraphicsContext3D::RGB9_E5:
+    case GraphicsContext3D::RGB16F:
+    case GraphicsContext3D::RGB32F:
+    case GraphicsContext3D::RGB8UI:
+    case GraphicsContext3D::RGB8I:
+    case GraphicsContext3D::RGB16UI:
+    case GraphicsContext3D::RGB16I:
+    case GraphicsContext3D::RGB32UI:
+    case GraphicsContext3D::RGB32I:
+    case GraphicsContext3D::RGBA8:
+    case GraphicsContext3D::SRGB8_ALPHA8:
+    case GraphicsContext3D::RGBA8_SNORM:
     case GraphicsContext3D::RGB5_A1:
     case GraphicsContext3D::RGB5_A1:
+    case GraphicsContext3D::RGBA4:
+    case GraphicsContext3D::RGB10_A2:
+    case GraphicsContext3D::RGBA16F:
+    case GraphicsContext3D::RGBA32F:
+    case GraphicsContext3D::RGBA8UI:
+    case GraphicsContext3D::RGBA8I:
+    case GraphicsContext3D::RGB10_A2UI:
+    case GraphicsContext3D::RGBA16UI:
+    case GraphicsContext3D::RGBA16I:
+    case GraphicsContext3D::RGBA32I:
+    case GraphicsContext3D::RGBA32UI:
     case Extensions3D::SRGB_EXT:
     case Extensions3D::SRGB_ALPHA_EXT:
     case Extensions3D::SRGB_EXT:
     case Extensions3D::SRGB_ALPHA_EXT:
-    case Extensions3D::SRGB8_ALPHA8_EXT:
         return GraphicsContext3D::COLOR_BUFFER_BIT;
     case GraphicsContext3D::DEPTH_COMPONENT16:
         return GraphicsContext3D::COLOR_BUFFER_BIT;
     case GraphicsContext3D::DEPTH_COMPONENT16:
+    case GraphicsContext3D::DEPTH_COMPONENT24:
+    case GraphicsContext3D::DEPTH_COMPONENT32F:
     case GraphicsContext3D::DEPTH_COMPONENT:
         return GraphicsContext3D::DEPTH_BUFFER_BIT;
     case GraphicsContext3D::STENCIL_INDEX8:
         return GraphicsContext3D::STENCIL_BUFFER_BIT;
     case GraphicsContext3D::DEPTH_STENCIL:
     case GraphicsContext3D::DEPTH_COMPONENT:
         return GraphicsContext3D::DEPTH_BUFFER_BIT;
     case GraphicsContext3D::STENCIL_INDEX8:
         return GraphicsContext3D::STENCIL_BUFFER_BIT;
     case GraphicsContext3D::DEPTH_STENCIL:
+    case GraphicsContext3D::DEPTH24_STENCIL8:
+    case GraphicsContext3D::DEPTH32F_STENCIL8:
         return GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT;
     default:
         return 0;
         return GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT;
     default:
         return 0;
index 5418eb7..4106617 100644 (file)
@@ -811,6 +811,8 @@ public:
                                      unsigned int* imageSizeInBytes,
                                      unsigned int* paddingInBytes);
 
                                      unsigned int* imageSizeInBytes,
                                      unsigned int* paddingInBytes);
 
+    static bool possibleFormatAndTypeForInternalFormat(GC3Denum internalFormat, GC3Denum& format, GC3Denum& type);
+
     // Extracts the contents of the given ImageData into the passed Vector,
     // packing the pixel data according to the given format and type,
     // and obeying the flipY and premultiplyAlpha flags. Returns true
     // Extracts the contents of the given ImageData into the passed Vector,
     // packing the pixel data according to the given format and type,
     // and obeying the flipY and premultiplyAlpha flags. Returns true
@@ -884,45 +886,55 @@ public:
 
     ALWAYS_INLINE static bool hasAlpha(DataFormat format)
     {
 
     ALWAYS_INLINE static bool hasAlpha(DataFormat format)
     {
-        return format == GraphicsContext3D::DataFormatA8
-            || format == GraphicsContext3D::DataFormatA16F
-            || format == GraphicsContext3D::DataFormatA32F
-            || format == GraphicsContext3D::DataFormatRA8
-            || format == GraphicsContext3D::DataFormatAR8
-            || format == GraphicsContext3D::DataFormatRA16F
-            || format == GraphicsContext3D::DataFormatRA32F
-            || format == GraphicsContext3D::DataFormatRGBA8
-            || format == GraphicsContext3D::DataFormatBGRA8
-            || format == GraphicsContext3D::DataFormatARGB8
-            || format == GraphicsContext3D::DataFormatABGR8
-            || format == GraphicsContext3D::DataFormatRGBA16F
-            || format == GraphicsContext3D::DataFormatRGBA32F
-            || format == GraphicsContext3D::DataFormatRGBA4444
-            || format == GraphicsContext3D::DataFormatRGBA5551;
+        switch (format) {
+        case GraphicsContext3D::DataFormatA8:
+        case GraphicsContext3D::DataFormatA16F:
+        case GraphicsContext3D::DataFormatA32F:
+        case GraphicsContext3D::DataFormatRA8:
+        case GraphicsContext3D::DataFormatAR8:
+        case GraphicsContext3D::DataFormatRA16F:
+        case GraphicsContext3D::DataFormatRA32F:
+        case GraphicsContext3D::DataFormatRGBA8:
+        case GraphicsContext3D::DataFormatBGRA8:
+        case GraphicsContext3D::DataFormatARGB8:
+        case GraphicsContext3D::DataFormatABGR8:
+        case GraphicsContext3D::DataFormatRGBA16F:
+        case GraphicsContext3D::DataFormatRGBA32F:
+        case GraphicsContext3D::DataFormatRGBA4444:
+        case GraphicsContext3D::DataFormatRGBA5551:
+            return true;
+        default:
+            return false;
+        }
     }
 
     ALWAYS_INLINE static bool hasColor(DataFormat format)
     {
     }
 
     ALWAYS_INLINE static bool hasColor(DataFormat format)
     {
-        return format == GraphicsContext3D::DataFormatRGBA8
-            || format == GraphicsContext3D::DataFormatRGBA16F
-            || format == GraphicsContext3D::DataFormatRGBA32F
-            || format == GraphicsContext3D::DataFormatRGB8
-            || format == GraphicsContext3D::DataFormatRGB16F
-            || format == GraphicsContext3D::DataFormatRGB32F
-            || format == GraphicsContext3D::DataFormatBGR8
-            || format == GraphicsContext3D::DataFormatBGRA8
-            || format == GraphicsContext3D::DataFormatARGB8
-            || format == GraphicsContext3D::DataFormatABGR8
-            || format == GraphicsContext3D::DataFormatRGBA5551
-            || format == GraphicsContext3D::DataFormatRGBA4444
-            || format == GraphicsContext3D::DataFormatRGB565
-            || format == GraphicsContext3D::DataFormatR8
-            || format == GraphicsContext3D::DataFormatR16F
-            || format == GraphicsContext3D::DataFormatR32F
-            || format == GraphicsContext3D::DataFormatRA8
-            || format == GraphicsContext3D::DataFormatRA16F
-            || format == GraphicsContext3D::DataFormatRA32F
-            || format == GraphicsContext3D::DataFormatAR8;
+        switch (format) {
+        case GraphicsContext3D::DataFormatRGBA8:
+        case GraphicsContext3D::DataFormatRGBA16F:
+        case GraphicsContext3D::DataFormatRGBA32F:
+        case GraphicsContext3D::DataFormatRGB8:
+        case GraphicsContext3D::DataFormatRGB16F:
+        case GraphicsContext3D::DataFormatRGB32F:
+        case GraphicsContext3D::DataFormatBGR8:
+        case GraphicsContext3D::DataFormatBGRA8:
+        case GraphicsContext3D::DataFormatARGB8:
+        case GraphicsContext3D::DataFormatABGR8:
+        case GraphicsContext3D::DataFormatRGBA5551:
+        case GraphicsContext3D::DataFormatRGBA4444:
+        case GraphicsContext3D::DataFormatRGB565:
+        case GraphicsContext3D::DataFormatR8:
+        case GraphicsContext3D::DataFormatR16F:
+        case GraphicsContext3D::DataFormatR32F:
+        case GraphicsContext3D::DataFormatRA8:
+        case GraphicsContext3D::DataFormatRA16F:
+        case GraphicsContext3D::DataFormatRA32F:
+        case GraphicsContext3D::DataFormatAR8:
+            return true;
+        default:
+            return false;
+        }
     }
 
     // Check if the format is one of the formats from the ImageData or DOM elements.
     }
 
     // Check if the format is one of the formats from the ImageData or DOM elements.