Title: [179842] trunk/Source/WebCore
Revision
179842
Author
[email protected]
Date
2015-02-09 12:50:15 -0800 (Mon, 09 Feb 2015)

Log Message

WebGL 2: Texture call format, internal format, and type validation.
https://bugs.webkit.org/show_bug.cgi?id=141318.
<rdar://problem/19733828>

Reviewed by Brent Fulgham.

Tests will be covered by WebGL2 conformance tests.

* html/canvas/WebGL2RenderingContext.cpp:
(WebCore::WebGL2RenderingContext::getFramebufferAttachmentParameter): Add missing ExceptionCode argument.
(WebCore::WebGL2RenderingContext::copyTexImage2D): Validate texture formats based on GLES3 spec.
(WebCore::WebGL2RenderingContext::texSubImage2DBase): Validate using internal format from texture target.
(WebCore::WebGL2RenderingContext::texSubImage2DImpl): Validate using internal format from texture target.
(WebCore::WebGL2RenderingContext::texSubImage2D): Validate using internal format from texture target.
(WebCore::WebGL2RenderingContext::validateTexFuncParameters): Do extra validation for copyTexImage2D.
(WebCore::WebGL2RenderingContext::validateTexFuncFormatAndType): Validate internal format, format and type combination.
(WebCore::WebGL2RenderingContext::validateTexFuncData): Validate new data types.
This method now accepts an internal format argument.
(WebCore::WebGL2RenderingContext::baseInternalFormatFromInternalFormat):
Helper method to convert internal format to base internal format.
* html/canvas/WebGL2RenderingContext.h:

* html/canvas/WebGLRenderingContext.cpp:
(WebCore::WebGLRenderingContext::copyTexImage2D): Moved from WebGLRenderingContextBase.
(WebCore::WebGLRenderingContext::texSubImage2DBase): Ditto.
(WebCore::WebGLRenderingContext::texSubImage2DImpl): Ditto.
(WebCore::WebGLRenderingContext::texSubImage2D): Ditto.
(WebCore::WebGLRenderingContext::validateTexFuncParameters): Ditto.
(WebCore::WebGLRenderingContext::validateTexFuncFormatAndType): Ditto.
(WebCore::WebGLRenderingContext::validateTexFuncData): Ditto.
* html/canvas/WebGLRenderingContext.h:

* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::texImage2DBase):
(WebCore::WebGLRenderingContextBase::validateTexFunc):
(WebCore::WebGLRenderingContextBase::texImage2D):
(WebCore::WebGLRenderingContextBase::copyTexImage2D): Deleted.
(WebCore::WebGLRenderingContextBase::texSubImage2DBase): Deleted.
(WebCore::WebGLRenderingContextBase::texSubImage2DImpl): Deleted.
(WebCore::WebGLRenderingContextBase::texSubImage2D): Deleted.
(WebCore::WebGLRenderingContextBase::validateTexFuncFormatAndType): Deleted.
(WebCore::WebGLRenderingContextBase::validateTexFuncParameters): Deleted.
(WebCore::WebGLRenderingContextBase::validateTexFuncData): Deleted.
* html/canvas/WebGLRenderingContextBase.h: Modify validation type enums to differentiate between CopyImage, TexImage and TexSubImage calls.
(WebCore::ScopedDrawingBufferBinder::ScopedDrawingBufferBinder):  Moved from WebGLRenderingContextBase.
(WebCore::ScopedDrawingBufferBinder::~ScopedDrawingBufferBinder): Ditto.
(WebCore::clip1D): Ditto.
(WebCore::clip2D): Ditto.
* platform/graphics/GraphicsContext3D.h: Rename a typo'ed enum.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (179841 => 179842)


--- trunk/Source/WebCore/ChangeLog	2015-02-09 20:27:51 UTC (rev 179841)
+++ trunk/Source/WebCore/ChangeLog	2015-02-09 20:50:15 UTC (rev 179842)
@@ -1,3 +1,55 @@
+2015-02-07  Roger Fong  <[email protected]>
+
+        WebGL 2: Texture call format, internal format, and type validation.
+        https://bugs.webkit.org/show_bug.cgi?id=141318.
+        <rdar://problem/19733828>
+
+        Reviewed by Brent Fulgham.
+
+        Tests will be covered by WebGL2 conformance tests.
+
+        * html/canvas/WebGL2RenderingContext.cpp:
+        (WebCore::WebGL2RenderingContext::getFramebufferAttachmentParameter): Add missing ExceptionCode argument.
+        (WebCore::WebGL2RenderingContext::copyTexImage2D): Validate texture formats based on GLES3 spec.
+        (WebCore::WebGL2RenderingContext::texSubImage2DBase): Validate using internal format from texture target.
+        (WebCore::WebGL2RenderingContext::texSubImage2DImpl): Validate using internal format from texture target.
+        (WebCore::WebGL2RenderingContext::texSubImage2D): Validate using internal format from texture target.
+        (WebCore::WebGL2RenderingContext::validateTexFuncParameters): Do extra validation for copyTexImage2D.
+        (WebCore::WebGL2RenderingContext::validateTexFuncFormatAndType): Validate internal format, format and type combination.
+        (WebCore::WebGL2RenderingContext::validateTexFuncData): Validate new data types.
+        This method now accepts an internal format argument.
+        (WebCore::WebGL2RenderingContext::baseInternalFormatFromInternalFormat):
+        Helper method to convert internal format to base internal format.
+        * html/canvas/WebGL2RenderingContext.h:
+
+        * html/canvas/WebGLRenderingContext.cpp:
+        (WebCore::WebGLRenderingContext::copyTexImage2D): Moved from WebGLRenderingContextBase.
+        (WebCore::WebGLRenderingContext::texSubImage2DBase): Ditto.
+        (WebCore::WebGLRenderingContext::texSubImage2DImpl): Ditto.
+        (WebCore::WebGLRenderingContext::texSubImage2D): Ditto.
+        (WebCore::WebGLRenderingContext::validateTexFuncParameters): Ditto.
+        (WebCore::WebGLRenderingContext::validateTexFuncFormatAndType): Ditto.
+        (WebCore::WebGLRenderingContext::validateTexFuncData): Ditto.
+        * html/canvas/WebGLRenderingContext.h:
+
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::texImage2DBase):
+        (WebCore::WebGLRenderingContextBase::validateTexFunc):
+        (WebCore::WebGLRenderingContextBase::texImage2D):
+        (WebCore::WebGLRenderingContextBase::copyTexImage2D): Deleted.
+        (WebCore::WebGLRenderingContextBase::texSubImage2DBase): Deleted.
+        (WebCore::WebGLRenderingContextBase::texSubImage2DImpl): Deleted.
+        (WebCore::WebGLRenderingContextBase::texSubImage2D): Deleted.
+        (WebCore::WebGLRenderingContextBase::validateTexFuncFormatAndType): Deleted.
+        (WebCore::WebGLRenderingContextBase::validateTexFuncParameters): Deleted.
+        (WebCore::WebGLRenderingContextBase::validateTexFuncData): Deleted.
+        * html/canvas/WebGLRenderingContextBase.h: Modify validation type enums to differentiate between CopyImage, TexImage and TexSubImage calls.
+        (WebCore::ScopedDrawingBufferBinder::ScopedDrawingBufferBinder):  Moved from WebGLRenderingContextBase.
+        (WebCore::ScopedDrawingBufferBinder::~ScopedDrawingBufferBinder): Ditto.
+        (WebCore::clip1D): Ditto.
+        (WebCore::clip2D): Ditto.
+        * platform/graphics/GraphicsContext3D.h: Rename a typo'ed enum.
+
 2015-02-09  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r179494.

Modified: trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp (179841 => 179842)


--- trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp	2015-02-09 20:27:51 UTC (rev 179841)
+++ trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp	2015-02-09 20:50:15 UTC (rev 179842)
@@ -28,16 +28,23 @@
 #if ENABLE(WEBGL)
 #include "WebGL2RenderingContext.h"
 
+#include "CachedImage.h"
 #include "EXTTextureFilterAnisotropic.h"
 #include "Extensions3D.h"
+#include "HTMLCanvasElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLVideoElement.h"
+#include "ImageData.h"
 #include "OESTextureFloat.h"
 #include "OESTextureFloatLinear.h"
 #include "OESTextureHalfFloat.h"
 #include "OESTextureHalfFloatLinear.h"
+#include "RenderBox.h"
 #include "WebGLActiveInfo.h"
 #include "WebGLCompressedTextureATC.h"
 #include "WebGLCompressedTexturePVRTC.h"
 #include "WebGLCompressedTextureS3TC.h"
+#include "WebGLContextAttributes.h"
 #include "WebGLDebugRendererInfo.h"
 #include "WebGLDebugShaders.h"
 #include "WebGLDepthTexture.h"
@@ -82,11 +89,12 @@
     UNUSED_PARAM(returnedData);
 }
 
-WebGLGetInfo WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname)
+WebGLGetInfo WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
 {
     UNUSED_PARAM(target);
     UNUSED_PARAM(attachment);
     UNUSED_PARAM(pname);
+    UNUSED_PARAM(ec);
     return WebGLGetInfo();
 }
 
@@ -900,6 +908,812 @@
     return result;
 }
 
+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()) {
+        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
+        m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+    } else {
+        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
+        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, ExceptionCode& ec)
+{
+    ec = 0;
+    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, ExceptionCode& ec)
+{
+    ec = 0;
+    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, ec);
+    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, ArrayBufferView* pixels, ExceptionCode& ec)
+{
+    if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, GraphicsContext3D::NONE, format, type, pixels, NullNotAllowed) || !validateTexFunc("texSubImage2D", TexSubImage, SourceArrayBufferView, target, level, GraphicsContext3D::NONE, width, height, 0, format, type, xoffset, yoffset))
+        return;
+    
+    void* data = ""
+    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 = ""
+        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, ec);
+    if (changeUnpackAlignment)
+        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
+}
+
+void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
+{
+    ec = 0;
+    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, 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(), ec);
+    if (m_unpackAlignment != 1)
+        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
+}
+
+void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
+{
+    ec = 0;
+    if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
+        return;
+    
+    RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
+    if (imageForRender->isSVGImage())
+        imageForRender = drawImageIntoBuffer(imageForRender.get(), 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, ec);
+}
+
+void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+    GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
+{
+    ec = 0;
+    if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
+        || !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, imageData.get(), ec);
+    else
+        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
+}
+
+#if ENABLE(VIDEO)
+void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
+{
+    ec = 0;
+    if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
+        || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, GraphicsContext3D::NONE, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
+        return;
+    
+    RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
+    if (!image)
+        return;
+    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
+}
+#endif
+
+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;
+        }
+
+        ExceptionCode ec;
+        bool isSRGB = (getFramebufferAttachmentParameter(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, ec).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::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) {
+            error = 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.
+    switch (internalformat) {
+    case GraphicsContext3D::R8:
+    case GraphicsContext3D::R8_SNORM:
+    case GraphicsContext3D::R16F:
+    case GraphicsContext3D::R32F:
+    case GraphicsContext3D::R8I:
+    case GraphicsContext3D::R8UI:
+    case GraphicsContext3D::R16I:
+    case GraphicsContext3D::R16UI:
+    case GraphicsContext3D::R32I:
+    case GraphicsContext3D::R32UI:
+    case GraphicsContext3D::COMPRESSED_R11_EAC:
+    case GraphicsContext3D::COMPRESSED_SIGNED_R11_EAC:
+        return GraphicsContext3D::RED;
+    case GraphicsContext3D::RG8:
+    case GraphicsContext3D::RG8_SNORM:
+    case GraphicsContext3D::RG16F:
+    case GraphicsContext3D::RG32F:
+    case GraphicsContext3D::RG8I:
+    case GraphicsContext3D::RG8UI:
+    case GraphicsContext3D::RG16I:
+    case GraphicsContext3D::RG16UI:
+    case GraphicsContext3D::RG32I:
+    case GraphicsContext3D::RG32UI:
+    case GraphicsContext3D::COMPRESSED_RG11_EAC:
+    case GraphicsContext3D::COMPRESSED_SIGNED_RG11_EAC:
+        return GraphicsContext3D::RG;
+    case GraphicsContext3D::RGB8:
+    case GraphicsContext3D::RGB8_SNORM:
+    case GraphicsContext3D::RGB565:
+    case GraphicsContext3D::SRGB8:
+    case GraphicsContext3D::RGB16F:
+    case GraphicsContext3D::RGB32F:
+    case GraphicsContext3D::RGB8I:
+    case GraphicsContext3D::RGB8UI:
+    case GraphicsContext3D::RGB16I:
+    case GraphicsContext3D::RGB16UI:
+    case GraphicsContext3D::RGB32I:
+    case GraphicsContext3D::RGB32UI:
+    case GraphicsContext3D::RGB:
+    case GraphicsContext3D::COMPRESSED_RGB8_ETC2:
+    case GraphicsContext3D::COMPRESSED_SRGB8_ETC2:
+        return GraphicsContext3D::RGB;
+    case GraphicsContext3D::RGBA4:
+    case GraphicsContext3D::RGB5_A1:
+    case GraphicsContext3D::RGBA8:
+    case GraphicsContext3D::RGBA8_SNORM:
+    case GraphicsContext3D::RGB10_A2:
+    case GraphicsContext3D::RGB10_A2UI:
+    case GraphicsContext3D::SRGB8_ALPHA8:
+    case GraphicsContext3D::RGBA16F:
+    case GraphicsContext3D::RGBA32F:
+    case GraphicsContext3D::RGBA8I:
+    case GraphicsContext3D::RGBA8UI:
+    case GraphicsContext3D::RGBA16I:
+    case GraphicsContext3D::RGBA16UI:
+    case GraphicsContext3D::RGBA32I:
+    case GraphicsContext3D::RGBA32UI:
+    case GraphicsContext3D::RGBA:
+    case GraphicsContext3D::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case GraphicsContext3D::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case GraphicsContext3D::COMPRESSED_RGBA8_ETC2_EAC:
+    case GraphicsContext3D::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+        return GraphicsContext3D::RGBA;
+    case GraphicsContext3D::DEPTH_COMPONENT16:
+    case GraphicsContext3D::DEPTH_COMPONENT24:
+    case GraphicsContext3D::DEPTH_COMPONENT32F:
+        return GraphicsContext3D::DEPTH_COMPONENT;
+    case GraphicsContext3D::DEPTH24_STENCIL8:
+    case GraphicsContext3D::DEPTH32F_STENCIL8:
+        return GraphicsContext3D::DEPTH_STENCIL;
+    case GraphicsContext3D::LUMINANCE:
+    case GraphicsContext3D::LUMINANCE_ALPHA:
+    case GraphicsContext3D::ALPHA:
+        return internalformat;
+    default:
+        ASSERT_NOT_REACHED();
+        return GraphicsContext3D::NONE;
+    }
+}
+
 WebGLGetInfo WebGL2RenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec)
 {
     UNUSED_PARAM(ec);

Modified: trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h (179841 => 179842)


--- trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h	2015-02-09 20:27:51 UTC (rev 179841)
+++ trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h	2015-02-09 20:50:15 UTC (rev 179842)
@@ -48,7 +48,7 @@
     void getBufferSubData(GC3Denum target, GC3Dint64 offset, ArrayBuffer* returnedData);
     
     /* Framebuffer objects */
-    WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname);
+    WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode&);
     void blitFramebuffer(GC3Dint srcX0, GC3Dint srcY0, GC3Dint srcX1, GC3Dint srcY1, GC3Dint dstX0, GC3Dint dstY0, GC3Dint dstX1, GC3Dint dstY1, GC3Dbitfield mask, GC3Denum filter);
     void framebufferTextureLayer(GC3Denum target, GC3Denum attachment, GC3Duint texture, GC3Dint level, GC3Dint layer);
     WebGLGetInfo getInternalformatParameter(GC3Denum target, GC3Denum internalformat, GC3Denum pname);
@@ -169,7 +169,41 @@
     virtual Vector<String> getSupportedExtensions() override;
 
     virtual WebGLGetInfo getParameter(GC3Denum pname, ExceptionCode&) override;
-    bool validateCapability(const char* functionName, GC3Denum cap) override;
+    
+    virtual void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) override;
+    virtual void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&) override;
+    virtual void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&) override;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Dsizei width, GC3Dsizei height,
+        GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&) override;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&) override;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&) override;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&) override;
+#if ENABLE(VIDEO)
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&) override;
+#endif
+
+protected:
+    virtual bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level) override;
+    virtual bool validateTexFuncParameters(const char* functionName,
+        TexFuncValidationFunctionType,
+        GC3Denum target, GC3Dint level,
+        GC3Denum internalformat,
+        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
+        GC3Denum format, GC3Denum type) override;
+    virtual bool validateTexFuncData(const char* functionName, GC3Dint level,
+        GC3Dsizei width, GC3Dsizei height,
+        GC3Denum internalformat, GC3Denum format, GC3Denum type,
+        ArrayBufferView* pixels,
+        NullDisposition) override;
+    virtual bool validateCapability(const char* functionName, GC3Denum cap) override;
+    
+private:
+    GC3Denum baseInternalFormatFromInternalFormat(GC3Denum internalformat);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp (179841 => 179842)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp	2015-02-09 20:27:51 UTC (rev 179841)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp	2015-02-09 20:50:15 UTC (rev 179842)
@@ -29,12 +29,17 @@
 #include "WebGLRenderingContext.h"
 
 #include "ANGLEInstancedArrays.h"
+#include "CachedImage.h"
 #include "EXTBlendMinMax.h"
 #include "EXTFragDepth.h"
 #include "EXTShaderTextureLOD.h"
 #include "EXTTextureFilterAnisotropic.h"
 #include "EXTsRGB.h"
 #include "Extensions3D.h"
+#include "HTMLCanvasElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLVideoElement.h"
+#include "ImageData.h"
 #include "OESElementIndexUint.h"
 #include "OESStandardDerivatives.h"
 #include "OESTextureFloat.h"
@@ -42,6 +47,7 @@
 #include "OESTextureHalfFloat.h"
 #include "OESTextureHalfFloatLinear.h"
 #include "OESVertexArrayObject.h"
+#include "RenderBox.h"
 #include "WebGLCompressedTextureATC.h"
 #include "WebGLCompressedTexturePVRTC.h"
 #include "WebGLCompressedTextureS3TC.h"
@@ -281,6 +287,454 @@
     return result;
 }
 
+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()) {
+        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
+        m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+    } else {
+        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
+        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, ExceptionCode& ec)
+{
+    UNUSED_PARAM(internalformat);
+    // FIXME: For now we ignore any errors returned
+    ec = 0;
+    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, ExceptionCode& ec)
+{
+    ec = 0;
+    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, ec);
+    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, ArrayBufferView* pixels, ExceptionCode& ec)
+{
+    if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, format, type, pixels, NullNotAllowed) || !validateTexFunc("texSubImage2D", TexSubImage, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
+        return;
+    
+    void* data = ""
+    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 = ""
+        changeUnpackAlignment = true;
+    }
+    if (changeUnpackAlignment)
+        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
+
+    texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, format, type, data, ec);
+    if (changeUnpackAlignment)
+        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
+}
+
+void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
+{
+    ec = 0;
+    if (isContextLostOrPending() || !pixels || !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, 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(), ec);
+    if (m_unpackAlignment != 1)
+        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
+}
+
+void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
+{
+    ec = 0;
+    if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
+        return;
+    
+    RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
+    if (imageForRender->isSVGImage())
+        imageForRender = drawImageIntoBuffer(imageForRender.get(), 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, ec);
+}
+
+void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
+{
+    ec = 0;
+    if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
+        || !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, imageData.get(), ec);
+    else
+        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
+}
+
+#if ENABLE(VIDEO)
+void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
+{
+    ec = 0;
+    if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
+        || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
+        return;
+    
+    RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
+    if (!image)
+        return;
+    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
+}
+#endif
+
+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) {
+            error = 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, ExceptionCode& ec)
 {
     UNUSED_PARAM(ec);

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h (179841 => 179842)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h	2015-02-09 20:27:51 UTC (rev 179841)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h	2015-02-09 20:50:15 UTC (rev 179842)
@@ -39,7 +39,38 @@
     virtual WebGLExtension* getExtension(const String&) override;
     virtual WebGLGetInfo getParameter(GC3Denum pname, ExceptionCode&) override;
     virtual Vector<String> getSupportedExtensions() override;
-    bool validateCapability(const char* functionName, GC3Denum cap) override;
+
+    virtual void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) override;
+    virtual void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&) override;
+    virtual void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&) override;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Dsizei width, GC3Dsizei height,
+        GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&) override;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&) override;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&) override;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&) override;
+#if ENABLE(VIDEO)
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&) override;
+#endif
+
+protected:
+    virtual bool validateTexFuncParameters(const char* functionName,
+        TexFuncValidationFunctionType,
+        GC3Denum target, GC3Dint level,
+        GC3Denum internalformat,
+        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
+        GC3Denum format, GC3Denum type) override;
+    virtual bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level) override;
+    virtual bool validateTexFuncData(const char* functionName, GC3Dint level,
+        GC3Dsizei width, GC3Dsizei height,
+        GC3Denum internalformat, GC3Denum format, GC3Denum type,
+        ArrayBufferView* pixels,
+        NullDisposition) override;
+    virtual bool validateCapability(const char* functionName, GC3Denum cap) override;
 };
     
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (179841 => 179842)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2015-02-09 20:27:51 UTC (rev 179841)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2015-02-09 20:50:15 UTC (rev 179842)
@@ -99,60 +99,12 @@
 const int maxGLErrorsAllowedToConsole = 256;
 
 namespace {
-
-    class ScopedDrawingBufferBinder {
-    public:
-        ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding)
-            : m_drawingBuffer(drawingBuffer)
-            , m_framebufferBinding(framebufferBinding)
-        {
-            // Commit DrawingBuffer if needed (e.g., for multisampling)
-            if (!m_framebufferBinding && m_drawingBuffer)
-                m_drawingBuffer->commit();
-        }
-
-        ~ScopedDrawingBufferBinder()
-        {
-            // Restore DrawingBuffer if needed
-            if (!m_framebufferBinding && m_drawingBuffer)
-                m_drawingBuffer->bind();
-        }
-
-    private:
-        DrawingBuffer* m_drawingBuffer;
-        WebGLFramebuffer* m_framebufferBinding;
-    };
-
+    
     Platform3DObject objectOrZero(WebGLObject* object)
     {
         return object ? object->object() : 0;
     }
 
-    void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
-    {
-        ASSERT(clippedStart && clippedRange);
-        if (start < 0) {
-            range += start;
-            start = 0;
-        }
-        GC3Dint end = start + range;
-        if (end > sourceRange)
-            range -= end - sourceRange;
-        *clippedStart = start;
-        *clippedRange = range;
-    }
-
-    // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
-    bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
-                GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
-                GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
-    {
-        ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
-        clip1D(x, width, sourceWidth, clippedX, clippedWidth);
-        clip1D(y, height, sourceHeight, clippedY, clippedHeight);
-        return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
-    }
-
     GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max)
     {
         if (value < min)
@@ -1442,52 +1394,6 @@
     return true;
 }
 
-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", NotTexSubImage2D, 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()) {
-        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
-        m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
-    } else {
-        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
-        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 WebGLRenderingContextBase::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
 {
     if (isContextLostOrPending())
@@ -3547,7 +3453,7 @@
     // FIXME: For now we ignore any errors returned.
     ec = 0;
     WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
-    ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type));
+    ASSERT(validateTexFuncParameters("texImage2D", TexImage, target, level, internalformat, width, height, border, format, type));
     ASSERT(tex);
     ASSERT(!level || !WebGLTexture::isNPOT(width, height));
     if (!pixels) {
@@ -3616,7 +3522,7 @@
     if (!texture)
         return false;
 
-    if (functionType == NotTexSubImage2D) {
+    if (functionType != TexSubImage) {
         if (level && WebGLTexture::isNPOT(width, height)) {
             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level > 0 not power of 2");
             return false;
@@ -3654,8 +3560,8 @@
                                        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
                                        GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
 {
-    if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed)
-        || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0))
+    if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, internalformat, format, type, pixels, NullAllowed)
+        || !validateTexFunc("texImage2D", TexImage, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0))
         return;
     void* data = "" ? pixels->baseAddress() : 0;
     Vector<uint8_t> tempData;
@@ -3682,7 +3588,7 @@
                                        GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
 {
     ec = 0;
-    if (isContextLostOrPending() || !pixels || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0))
+    if (isContextLostOrPending() || !pixels || !validateTexFunc("texImage2D", TexImage, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0))
         return;
     Vector<uint8_t> data;
     bool needConversion = true;
@@ -3730,7 +3636,7 @@
     if (imageForRender->isSVGImage())
         imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
 
-    if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0))
+    if (!imageForRender || !validateTexFunc("texImage2D", TexImage, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0))
         return;
 
     texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
@@ -3740,7 +3646,7 @@
                                        GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
 {
     ec = 0;
-    if (isContextLostOrPending() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0))
+    if (isContextLostOrPending() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", TexImage, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0))
         return;
 
     WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
@@ -3785,7 +3691,7 @@
 {
     ec = 0;
     if (isContextLostOrPending() || !validateHTMLVideoElement("texImage2D", video, ec)
-        || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0))
+        || !validateTexFunc("texImage2D", TexImage, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0))
         return;
 
     // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible.
@@ -3860,159 +3766,6 @@
     texParameter(target, pname, 0, param, false);
 }
 
-void WebGLRenderingContextBase::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
-{
-    // FIXME: For now we ignore any errors returned
-    ec = 0;
-    ASSERT(!isContextLost());
-    ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, 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 WebGLRenderingContextBase::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
-{
-    ec = 0;
-    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, type,  needConversion ? data.data() : imagePixelData, ec);
-    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, ArrayBufferView* pixels, ExceptionCode& ec)
-{
-    if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed)
-        || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
-        return;
-    void* data = ""
-    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 = ""
-        changeUnpackAlignment = true;
-    }
-    if (changeUnpackAlignment)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
-    texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
-    if (changeUnpackAlignment)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
-}
-
-void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                                          GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
-{
-    ec = 0;
-    if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage2D, 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, 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, type, needConversion ? data.data() : pixels->data()->data(), ec);
-    if (m_unpackAlignment != 1)
-        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
-}
-
-void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                                          GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
-{
-    ec = 0;
-    if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
-        return;
-
-    RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
-    if (imageForRender->isSVGImage())
-        imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
-
-    if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, 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, ec);
-}
-
-void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                                          GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
-{
-    ec = 0;
-    if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
-        || !validateTexFunc("texSubImage2D", TexSubImage2D, 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, imageData.get(), ec);
-    else
-        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
-}
-
-#if ENABLE(VIDEO)
-void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                                          GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
-{
-    ec = 0;
-    if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
-        || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
-        return;
-
-    RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
-    if (!image)
-        return;
-    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
-}
-#endif
-
 void WebGLRenderingContextBase::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
 {
     UNUSED_PARAM(ec);
@@ -4863,128 +4616,6 @@
     return true;
 }
 
-bool WebGLRenderingContextBase::validateTexFuncFormatAndType(const char* functionName, 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)
-            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 WebGLRenderingContextBase::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level)
 {
     if (level < 0) {
@@ -5015,138 +4646,6 @@
     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, 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 != TexSubImage2D && 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 WebGLRenderingContextBase::validateTexFuncData(const char* functionName, GC3Dint level,
-                                                GC3Dsizei width, GC3Dsizei height,
-                                                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, 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 int 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) {
-          error = 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;
-}
-
 bool WebGLRenderingContextBase::validateCompressedTexFormat(GC3Denum format)
 {
     return m_compressedTextureFormats.contains(format);

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h (179841 => 179842)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2015-02-09 20:27:51 UTC (rev 179841)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2015-02-09 20:50:15 UTC (rev 179842)
@@ -33,6 +33,7 @@
 #include "ImageBuffer.h"
 #include "Timer.h"
 #include "WebGLGetInfo.h"
+#include "WebGLObject.h"
 #include <memory>
 #include <runtime/Float32Array.h>
 #include <runtime/Int32Array.h>
@@ -85,6 +86,54 @@
 
 typedef int ExceptionCode;
 
+class ScopedDrawingBufferBinder {
+public:
+    ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding)
+        : m_drawingBuffer(drawingBuffer)
+        , m_framebufferBinding(framebufferBinding)
+    {
+        // Commit DrawingBuffer if needed (e.g., for multisampling)
+        if (!m_framebufferBinding && m_drawingBuffer)
+            m_drawingBuffer->commit();
+    }
+    
+    ~ScopedDrawingBufferBinder()
+    {
+        // Restore DrawingBuffer if needed
+        if (!m_framebufferBinding && m_drawingBuffer)
+            m_drawingBuffer->bind();
+    }
+    
+private:
+    DrawingBuffer* m_drawingBuffer;
+    WebGLFramebuffer* m_framebufferBinding;
+};
+
+inline void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
+{
+    ASSERT(clippedStart && clippedRange);
+    if (start < 0) {
+        range += start;
+        start = 0;
+    }
+    GC3Dint end = start + range;
+    if (end > sourceRange)
+        range -= end - sourceRange;
+    *clippedStart = start;
+    *clippedRange = range;
+}
+
+// Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
+inline bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
+    GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
+    GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
+{
+    ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
+    clip1D(x, width, sourceWidth, clippedX, clippedWidth);
+    clip1D(y, height, sourceHeight, clippedY, clippedHeight);
+    return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
+}
+
 class WebGLRenderingContextBase : public CanvasRenderingContext, public ActiveDOMObject {
 public:
     static std::unique_ptr<WebGLRenderingContextBase> create(HTMLCanvasElement*, WebGLContextAttributes*, const String&);
@@ -132,7 +181,7 @@
     void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
                                  GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data);
 
-    void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
+    virtual void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) = 0;
     void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
 
     PassRefPtr<WebGLBuffer> createBuffer();
@@ -237,18 +286,18 @@
     void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
     void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
 
-    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                       GC3Dsizei width, GC3Dsizei height,
-                       GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
-    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                       GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
-    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                       GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
-    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                       GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Dsizei width, GC3Dsizei height,
+        GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&) = 0;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&) = 0;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&) = 0;
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&) = 0;
 #if ENABLE(VIDEO)
-    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
-                       GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
+    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
+        GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&) = 0;
 #endif
 
     void uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode&);
@@ -584,8 +633,8 @@
 
     void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
     void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
-    void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
-    void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
+    virtual void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&) = 0;
+    virtual void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&) = 0;
 
     void checkTextureCompleteness(const char*, bool);
 
@@ -624,15 +673,16 @@
 
     // Helper function to check input format/type for functions {copy}Tex{Sub}Image.
     // Generates GL error and returns false if parameters are invalid.
-    bool validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level);
+    virtual bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level) = 0;
 
     // Helper function to check input level for functions {copy}Tex{Sub}Image.
     // Generates GL error and returns false if level is invalid.
     bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level);
 
     enum TexFuncValidationFunctionType {
-        NotTexSubImage2D,
-        TexSubImage2D,
+        TexImage,
+        TexSubImage,
+        CopyTexImage
     };
 
     enum TexFuncValidationSourceType {
@@ -650,12 +700,12 @@
 
     // Helper function to check input parameters for functions {copy}Tex{Sub}Image.
     // Generates GL error and returns false if parameters are invalid.
-    bool validateTexFuncParameters(const char* functionName,
-                                   TexFuncValidationFunctionType,
-                                   GC3Denum target, GC3Dint level,
-                                   GC3Denum internalformat,
-                                   GC3Dsizei width, GC3Dsizei height, GC3Dint border,
-                                   GC3Denum format, GC3Denum type);
+    virtual bool validateTexFuncParameters(const char* functionName,
+        TexFuncValidationFunctionType,
+        GC3Denum target, GC3Dint level,
+        GC3Denum internalformat,
+        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
+        GC3Denum format, GC3Denum type) = 0;
 
     enum NullDisposition {
         NullAllowed,
@@ -665,11 +715,11 @@
     // 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.
-    bool validateTexFuncData(const char* functionName, GC3Dint level,
-                             GC3Dsizei width, GC3Dsizei height,
-                             GC3Denum format, GC3Denum type,
-                             ArrayBufferView* pixels,
-                             NullDisposition);
+    virtual bool validateTexFuncData(const char* functionName, GC3Dint level,
+        GC3Dsizei width, GC3Dsizei height,
+        GC3Denum internalformat, GC3Denum format, GC3Denum type,
+        ArrayBufferView* pixels,
+        NullDisposition) = 0;
 
     // Helper function to validate a given texture format is settable as in
     // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h (179841 => 179842)


--- trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h	2015-02-09 20:27:51 UTC (rev 179841)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h	2015-02-09 20:50:15 UTC (rev 179842)
@@ -508,7 +508,7 @@
         COMPARE_REF_TO_TEXTURE = 0x884E,
         RGBA32F = 0x8814,
         RGB32F = 0x8815,
-        RGBA16 = 0x881A,
+        RGBA16F = 0x881A,
         RGB16F = 0x881B,
         VERTEX_ATTRIB_ARRAY_INTEGER = 0x88FD,
         MAX_ARRAY_TEXTURE_LAYERS = 0x88FF,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to