⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 179842 in webkit


Ignore:
Timestamp:
Feb 9, 2015, 12:50:15 PM (12 years ago)
Author:
roger_fong@apple.com
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.
Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r179839 r179842  
     12015-02-07  Roger Fong  <roger_fong@apple.com>
     2
     3        WebGL 2: Texture call format, internal format, and type validation.
     4        https://bugs.webkit.org/show_bug.cgi?id=141318.
     5        <rdar://problem/19733828>
     6
     7        Reviewed by Brent Fulgham.
     8
     9        Tests will be covered by WebGL2 conformance tests.
     10
     11        * html/canvas/WebGL2RenderingContext.cpp:
     12        (WebCore::WebGL2RenderingContext::getFramebufferAttachmentParameter): Add missing ExceptionCode argument.
     13        (WebCore::WebGL2RenderingContext::copyTexImage2D): Validate texture formats based on GLES3 spec.
     14        (WebCore::WebGL2RenderingContext::texSubImage2DBase): Validate using internal format from texture target.
     15        (WebCore::WebGL2RenderingContext::texSubImage2DImpl): Validate using internal format from texture target.
     16        (WebCore::WebGL2RenderingContext::texSubImage2D): Validate using internal format from texture target.
     17        (WebCore::WebGL2RenderingContext::validateTexFuncParameters): Do extra validation for copyTexImage2D.
     18        (WebCore::WebGL2RenderingContext::validateTexFuncFormatAndType): Validate internal format, format and type combination.
     19        (WebCore::WebGL2RenderingContext::validateTexFuncData): Validate new data types.
     20        This method now accepts an internal format argument.
     21        (WebCore::WebGL2RenderingContext::baseInternalFormatFromInternalFormat):
     22        Helper method to convert internal format to base internal format.
     23        * html/canvas/WebGL2RenderingContext.h:
     24
     25        * html/canvas/WebGLRenderingContext.cpp:
     26        (WebCore::WebGLRenderingContext::copyTexImage2D): Moved from WebGLRenderingContextBase.
     27        (WebCore::WebGLRenderingContext::texSubImage2DBase): Ditto.
     28        (WebCore::WebGLRenderingContext::texSubImage2DImpl): Ditto.
     29        (WebCore::WebGLRenderingContext::texSubImage2D): Ditto.
     30        (WebCore::WebGLRenderingContext::validateTexFuncParameters): Ditto.
     31        (WebCore::WebGLRenderingContext::validateTexFuncFormatAndType): Ditto.
     32        (WebCore::WebGLRenderingContext::validateTexFuncData): Ditto.
     33        * html/canvas/WebGLRenderingContext.h:
     34
     35        * html/canvas/WebGLRenderingContextBase.cpp:
     36        (WebCore::WebGLRenderingContextBase::texImage2DBase):
     37        (WebCore::WebGLRenderingContextBase::validateTexFunc):
     38        (WebCore::WebGLRenderingContextBase::texImage2D):
     39        (WebCore::WebGLRenderingContextBase::copyTexImage2D): Deleted.
     40        (WebCore::WebGLRenderingContextBase::texSubImage2DBase): Deleted.
     41        (WebCore::WebGLRenderingContextBase::texSubImage2DImpl): Deleted.
     42        (WebCore::WebGLRenderingContextBase::texSubImage2D): Deleted.
     43        (WebCore::WebGLRenderingContextBase::validateTexFuncFormatAndType): Deleted.
     44        (WebCore::WebGLRenderingContextBase::validateTexFuncParameters): Deleted.
     45        (WebCore::WebGLRenderingContextBase::validateTexFuncData): Deleted.
     46        * html/canvas/WebGLRenderingContextBase.h: Modify validation type enums to differentiate between CopyImage, TexImage and TexSubImage calls.
     47        (WebCore::ScopedDrawingBufferBinder::ScopedDrawingBufferBinder):  Moved from WebGLRenderingContextBase.
     48        (WebCore::ScopedDrawingBufferBinder::~ScopedDrawingBufferBinder): Ditto.
     49        (WebCore::clip1D): Ditto.
     50        (WebCore::clip2D): Ditto.
     51        * platform/graphics/GraphicsContext3D.h: Rename a typo'ed enum.
     52
    1532015-02-09  Commit Queue  <commit-queue@webkit.org>
    254
  • trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp

    r179530 r179842  
    2929#include "WebGL2RenderingContext.h"
    3030
     31#include "CachedImage.h"
    3132#include "EXTTextureFilterAnisotropic.h"
    3233#include "Extensions3D.h"
     34#include "HTMLCanvasElement.h"
     35#include "HTMLImageElement.h"
     36#include "HTMLVideoElement.h"
     37#include "ImageData.h"
    3338#include "OESTextureFloat.h"
    3439#include "OESTextureFloatLinear.h"
    3540#include "OESTextureHalfFloat.h"
    3641#include "OESTextureHalfFloatLinear.h"
     42#include "RenderBox.h"
    3743#include "WebGLActiveInfo.h"
    3844#include "WebGLCompressedTextureATC.h"
    3945#include "WebGLCompressedTexturePVRTC.h"
    4046#include "WebGLCompressedTextureS3TC.h"
     47#include "WebGLContextAttributes.h"
    4148#include "WebGLDebugRendererInfo.h"
    4249#include "WebGLDebugShaders.h"
     
    8390}
    8491
    85 WebGLGetInfo WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname)
     92WebGLGetInfo WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec)
    8693{
    8794    UNUSED_PARAM(target);
    8895    UNUSED_PARAM(attachment);
    8996    UNUSED_PARAM(pname);
     97    UNUSED_PARAM(ec);
    9098    return WebGLGetInfo();
    9199}
     
    899907   
    900908    return result;
     909}
     910
     911void WebGL2RenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
     912{
     913    if (isContextLostOrPending())
     914        return;
     915    RefPtr<WebGLContextAttributes> attributes = getContextAttributes();
     916    GC3Denum bufferFormat = attributes->alpha() ? GraphicsContext3D::RGBA : GraphicsContext3D::RGB;
     917    if (!validateTexFuncParameters("copyTexImage2D", CopyTexImage, target, level, internalformat, width, height, border, bufferFormat, GraphicsContext3D::UNSIGNED_BYTE))
     918        return;
     919    if (!validateSettableTexFormat("copyTexImage2D", internalformat))
     920        return;
     921    WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
     922    if (!tex)
     923        return;
     924    if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
     925        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
     926        return;
     927    }
     928    if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
     929        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
     930        return;
     931    }
     932    const char* reason = "framebuffer incomplete";
     933    if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
     934        synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
     935        return;
     936    }
     937    clearIfComposited();
     938    if (isResourceSafe()) {
     939        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
     940        m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
     941    } else {
     942        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
     943        GC3Dint clippedX, clippedY;
     944        GC3Dsizei clippedWidth, clippedHeight;
     945        if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
     946            m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
     947                internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
     948            if (clippedWidth > 0 && clippedHeight > 0) {
     949                m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
     950                    clippedX, clippedY, clippedWidth, clippedHeight);
     951            }
     952        } else
     953            m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
     954    }
     955    // FIXME: if the framebuffer is not complete, none of the below should be executed.
     956    tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
     957}
     958
     959void 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)
     960{
     961    ec = 0;
     962    ASSERT(!isContextLost());
     963    if (!validateTexFuncParameters("texSubImage2D", TexSubImage, target, level, internalformat, width, height, 0, format, type))
     964        return;
     965    ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
     966    ASSERT(validateSettableTexFormat("texSubImage2D", format));
     967    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
     968    if (!tex) {
     969        ASSERT_NOT_REACHED();
     970        return;
     971    }
     972    ASSERT((xoffset + width) >= 0);
     973    ASSERT((yoffset + height) >= 0);
     974    ASSERT(tex->getWidth(target, level) >= (xoffset + width));
     975    ASSERT(tex->getHeight(target, level) >= (yoffset + height));
     976    ASSERT(tex->getInternalFormat(target, level) == format);
     977    ASSERT(tex->getType(target, level) == type);
     978    m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
     979}
     980
     981void 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)
     982{
     983    ec = 0;
     984    Vector<uint8_t> data;
     985    GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
     986    if (!imageExtractor.extractSucceeded()) {
     987        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
     988        return;
     989    }
     990    GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
     991    GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
     992    const void* imagePixelData = imageExtractor.imagePixelData();
     993   
     994    bool needConversion = true;
     995    if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
     996        needConversion = false;
     997    else {
     998        if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
     999            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
     1000            return;
     1001        }
     1002    }
     1003   
     1004    if (m_unpackAlignment != 1)
     1005        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
     1006   
     1007    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
     1008    GC3Denum internalformat = tex->getInternalFormat(target, level);
     1009    texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), internalformat, format, type,  needConversion ? data.data() : imagePixelData, ec);
     1010    if (m_unpackAlignment != 1)
     1011        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
     1012}
     1013
     1014void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
     1015{
     1016    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))
     1017        return;
     1018   
     1019    void* data = pixels->baseAddress();
     1020    Vector<uint8_t> tempData;
     1021    bool changeUnpackAlignment = false;
     1022    if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
     1023        if (!m_context->extractTextureData(width, height, format, type,
     1024            m_unpackAlignment,
     1025            m_unpackFlipY, m_unpackPremultiplyAlpha,
     1026            data,
     1027            tempData))
     1028            return;
     1029        data = tempData.data();
     1030        changeUnpackAlignment = true;
     1031    }
     1032    if (changeUnpackAlignment)
     1033        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
     1034    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
     1035    GC3Denum internalformat = tex->getInternalFormat(target, level);
     1036    texSubImage2DBase(target, level, xoffset, yoffset, width, height, internalformat, format, type, data, ec);
     1037    if (changeUnpackAlignment)
     1038        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
     1039}
     1040
     1041void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
     1042{
     1043    ec = 0;
     1044    if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, GraphicsContext3D::NONE,  pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
     1045        return;
     1046   
     1047    Vector<uint8_t> data;
     1048    bool needConversion = true;
     1049    // The data from ImageData is always of format RGBA8.
     1050    // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
     1051    if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
     1052        needConversion = false;
     1053    else {
     1054        if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
     1055            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
     1056            return;
     1057        }
     1058    }
     1059    if (m_unpackAlignment != 1)
     1060        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
     1061   
     1062    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
     1063    GC3Denum internalformat = tex->getInternalFormat(target, level);
     1064    texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), internalformat, format, type, needConversion ? data.data() : pixels->data()->data(), ec);
     1065    if (m_unpackAlignment != 1)
     1066        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
     1067}
     1068
     1069void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
     1070{
     1071    ec = 0;
     1072    if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
     1073        return;
     1074   
     1075    RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
     1076    if (imageForRender->isSVGImage())
     1077        imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
     1078   
     1079    if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLImageElement, target, level, GraphicsContext3D::NONE, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
     1080        return;
     1081   
     1082    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
     1083}
     1084
     1085void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     1086    GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
     1087{
     1088    ec = 0;
     1089    if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
     1090        || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLCanvasElement, target, level, GraphicsContext3D::NONE, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
     1091        return;
     1092   
     1093    RefPtr<ImageData> imageData = canvas->getImageData();
     1094    if (imageData)
     1095        texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
     1096    else
     1097        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
     1098}
     1099
     1100#if ENABLE(VIDEO)
     1101void WebGL2RenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
     1102{
     1103    ec = 0;
     1104    if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
     1105        || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, GraphicsContext3D::NONE, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
     1106        return;
     1107   
     1108    RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
     1109    if (!image)
     1110        return;
     1111    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
     1112}
     1113#endif
     1114
     1115bool WebGL2RenderingContext::validateTexFuncParameters(const char* functionName, TexFuncValidationFunctionType functionType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type)
     1116{
     1117    if (functionType == CopyTexImage) {
     1118        GC3Denum framebufferInternalFormat = 0;
     1119        WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(GraphicsContext3D::COLOR_ATTACHMENT0);
     1120        if (object->isTexture()) {
     1121            WebGLTexture* texture = reinterpret_cast<WebGLTexture*>(object);
     1122            framebufferInternalFormat = baseInternalFormatFromInternalFormat(texture->getInternalFormat(GraphicsContext3D::TEXTURE_2D, 0));
     1123        } else if (object->isRenderbuffer()) {
     1124            WebGLRenderbuffer* renderBuffer = reinterpret_cast<WebGLRenderbuffer*>(object);
     1125            framebufferInternalFormat = baseInternalFormatFromInternalFormat(renderBuffer->getInternalFormat());
     1126        }
     1127       
     1128        GC3Denum baseTextureInternalFormat = baseInternalFormatFromInternalFormat(internalformat);
     1129        bool validFormatCombination = true;
     1130        switch (framebufferInternalFormat) {
     1131        case GraphicsContext3D::RED:
     1132            if (baseTextureInternalFormat != GraphicsContext3D::LUMINANCE && baseTextureInternalFormat != GraphicsContext3D::RED)
     1133                validFormatCombination = false;
     1134            break;
     1135        case GraphicsContext3D::RG:
     1136            if (baseTextureInternalFormat != GraphicsContext3D::LUMINANCE && baseTextureInternalFormat != GraphicsContext3D::RED && baseTextureInternalFormat != GraphicsContext3D::RG)
     1137                validFormatCombination = false;
     1138            break;
     1139        case GraphicsContext3D::RGB:
     1140            if (baseTextureInternalFormat != GraphicsContext3D::LUMINANCE && baseTextureInternalFormat != GraphicsContext3D::RED && baseTextureInternalFormat != GraphicsContext3D::RG && baseTextureInternalFormat != GraphicsContext3D::RGB)
     1141                validFormatCombination = false;
     1142            break;
     1143        case GraphicsContext3D::RGBA:
     1144            if (baseTextureInternalFormat != GraphicsContext3D::ALPHA && baseTextureInternalFormat != GraphicsContext3D::LUMINANCE && baseTextureInternalFormat != GraphicsContext3D::LUMINANCE_ALPHA && baseTextureInternalFormat != GraphicsContext3D::RED && baseTextureInternalFormat != GraphicsContext3D::RG && baseTextureInternalFormat != GraphicsContext3D::RGB && baseTextureInternalFormat != GraphicsContext3D::RGBA)
     1145                validFormatCombination = false;
     1146            break;
     1147        case GraphicsContext3D::DEPTH_COMPONENT:
     1148            validFormatCombination = false;
     1149            break;
     1150        case GraphicsContext3D::DEPTH_STENCIL:
     1151            validFormatCombination = false;
     1152            break;
     1153        }
     1154       
     1155        if (!validFormatCombination) {
     1156            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "copyTexImage: invalid combination of framebuffer and texture formats");
     1157            return false;
     1158        }
     1159
     1160        ExceptionCode ec;
     1161        bool isSRGB = (getFramebufferAttachmentParameter(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, ec).getInt() == GraphicsContext3D::SRGB);
     1162        if (isSRGB != (framebufferInternalFormat == GraphicsContext3D::SRGB8 || framebufferInternalFormat == GraphicsContext3D::SRGB8_ALPHA8)) {
     1163            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "framebuffer attachment color encoding and internal format do not match");
     1164        return false;
     1165        }
     1166    }
     1167   
     1168    // We absolutely have to validate the format and type combination.
     1169    // The texImage2D entry points taking HTMLImage, etc. will produce
     1170    // temporary data based on this combination, so it must be legal.
     1171    if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level) || !validateTexFuncLevel(functionName, target, level))
     1172        return false;
     1173   
     1174    if (width < 0 || height < 0) {
     1175        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
     1176        return false;
     1177    }
     1178   
     1179    GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
     1180    switch (target) {
     1181    case GraphicsContext3D::TEXTURE_2D:
     1182        if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
     1183            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
     1184            return false;
     1185        }
     1186        break;
     1187    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
     1188    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
     1189    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
     1190    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
     1191    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
     1192    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
     1193        if (functionType != TexSubImage && width != height) {
     1194            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
     1195            return false;
     1196        }
     1197        // No need to check height here. For texImage width == height.
     1198        // For texSubImage that will be checked when checking yoffset + height is in range.
     1199        if (width > maxTextureSizeForLevel) {
     1200            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
     1201            return false;
     1202        }
     1203        break;
     1204    default:
     1205        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
     1206        return false;
     1207    }
     1208   
     1209    if (border) {
     1210        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
     1211        return false;
     1212    }
     1213   
     1214    return true;
     1215}
     1216   
     1217bool WebGL2RenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level)
     1218{
     1219    // Verify that a valid format has been provided.
     1220    switch (format) {
     1221    case GraphicsContext3D::ALPHA:
     1222    case GraphicsContext3D::LUMINANCE:
     1223    case GraphicsContext3D::LUMINANCE_ALPHA:
     1224    case GraphicsContext3D::RGB:
     1225    case GraphicsContext3D::RGBA:
     1226    case GraphicsContext3D::RGBA_INTEGER:
     1227    case GraphicsContext3D::RG:
     1228    case GraphicsContext3D::RG_INTEGER:
     1229    case GraphicsContext3D::RED_INTEGER:
     1230        break;
     1231    case GraphicsContext3D::DEPTH_STENCIL:
     1232    case GraphicsContext3D::DEPTH_COMPONENT:
     1233        if (m_webglDepthTexture)
     1234            break;
     1235        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
     1236        return false;
     1237    default:
     1238        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
     1239        return false;
     1240    }
     1241   
     1242    // Verify that a valid type has been provided.
     1243    switch (type) {
     1244    case GraphicsContext3D::UNSIGNED_BYTE:
     1245    case GraphicsContext3D::BYTE:
     1246    case GraphicsContext3D::UNSIGNED_SHORT:
     1247    case GraphicsContext3D::SHORT:
     1248    case GraphicsContext3D::UNSIGNED_INT:
     1249    case GraphicsContext3D::INT:
     1250    case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
     1251    case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
     1252    case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV:
     1253    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
     1254    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
     1255    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
     1256        break;
     1257    case GraphicsContext3D::FLOAT:
     1258        if (m_oesTextureFloat)
     1259            break;
     1260        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
     1261        return false;
     1262    case GraphicsContext3D::HALF_FLOAT:
     1263    case GraphicsContext3D::HALF_FLOAT_OES:
     1264        if (m_oesTextureHalfFloat)
     1265            break;
     1266        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
     1267        return false;
     1268    case GraphicsContext3D::UNSIGNED_INT_24_8:
     1269    case GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV:
     1270        if (isDepthStencilSupported())
     1271            break;
     1272        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
     1273        return false;
     1274    default:
     1275        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
     1276        return false;
     1277    }
     1278   
     1279    // Veryify that a valid internal format has been provided.
     1280    switch (internalformat) {
     1281    case GraphicsContext3D::RGBA:
     1282    case GraphicsContext3D::RGB:
     1283    case GraphicsContext3D::LUMINANCE_ALPHA:
     1284    case GraphicsContext3D::LUMINANCE:
     1285    case GraphicsContext3D::ALPHA:
     1286    case GraphicsContext3D::RGBA32I:
     1287    case GraphicsContext3D::RGBA32UI:
     1288    case GraphicsContext3D::RGBA16I:
     1289    case GraphicsContext3D::RGBA16UI:
     1290    case GraphicsContext3D::RGBA8:
     1291    case GraphicsContext3D::RGBA8I:
     1292    case GraphicsContext3D::RGBA8UI:
     1293    case GraphicsContext3D::RGB10_A2:
     1294    case GraphicsContext3D::RGB10_A2UI:
     1295    case GraphicsContext3D::RGBA4:
     1296    case GraphicsContext3D::RG32I:
     1297    case GraphicsContext3D::RG32UI:
     1298    case GraphicsContext3D::RG16I:
     1299    case GraphicsContext3D::RG16UI:
     1300    case GraphicsContext3D::RG8:
     1301    case GraphicsContext3D::RG8I:
     1302    case GraphicsContext3D::RG8UI:
     1303    case GraphicsContext3D::R32I:
     1304    case GraphicsContext3D::R32UI:
     1305    case GraphicsContext3D::R16I:
     1306    case GraphicsContext3D::R16UI:
     1307    case GraphicsContext3D::R8:
     1308    case GraphicsContext3D::R8I:
     1309    case GraphicsContext3D::R8UI:
     1310    case GraphicsContext3D::RGB5_A1:
     1311    case GraphicsContext3D::RGB8:
     1312    case GraphicsContext3D::RGB565:
     1313    case GraphicsContext3D::RGBA32F:
     1314    case GraphicsContext3D::RGBA16F:
     1315    case GraphicsContext3D::RGBA8_SNORM:
     1316    case GraphicsContext3D::RGB32F:
     1317    case GraphicsContext3D::RGB32I:
     1318    case GraphicsContext3D::RGB32UI:
     1319    case GraphicsContext3D::RGB16F:
     1320    case GraphicsContext3D::RGB16I:
     1321    case GraphicsContext3D::RGB16UI:
     1322    case GraphicsContext3D::RGB8_SNORM:
     1323    case GraphicsContext3D::RGB8I:
     1324    case GraphicsContext3D::RGB8UI:
     1325    case GraphicsContext3D::SRGB8:
     1326    case GraphicsContext3D::R11F_G11F_B10F:
     1327    case GraphicsContext3D::RGB9_E5:
     1328    case GraphicsContext3D::RG32F:
     1329    case GraphicsContext3D::RG16F:
     1330    case GraphicsContext3D::RG8_SNORM:
     1331    case GraphicsContext3D::R32F:
     1332    case GraphicsContext3D::R16F:
     1333    case GraphicsContext3D::R8_SNORM:
     1334    case GraphicsContext3D::STENCIL_INDEX8:
     1335        break;
     1336    case GraphicsContext3D::DEPTH_COMPONENT16:
     1337    case GraphicsContext3D::DEPTH_COMPONENT32F:
     1338    case GraphicsContext3D::DEPTH_COMPONENT24:
     1339        if (m_webglDepthTexture)
     1340            break;
     1341        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
     1342        return false;
     1343    case GraphicsContext3D::DEPTH32F_STENCIL8:
     1344    case GraphicsContext3D::DEPTH24_STENCIL8:
     1345        if (isDepthStencilSupported())
     1346            break;
     1347        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture internal format");
     1348        return false;
     1349    case GraphicsContext3D::NONE:
     1350        // When calling validateTexFuncFormatAndType with internalformat == GraphicsContext3D::NONE, the intent is
     1351        // only to check for whether or not the format and type are valid types, which we have already done at this point.
     1352        return true;
     1353        break;
     1354    default:
     1355        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture internal format");
     1356        return false;
     1357    }
     1358
     1359    // Verify that the combination of format, internalformat and type is supported.
     1360    switch (format) {
     1361    case GraphicsContext3D::RGBA:
     1362        if (type == GraphicsContext3D::UNSIGNED_BYTE
     1363            && (internalformat == GraphicsContext3D::RGBA || internalformat == GraphicsContext3D::RGBA8 || internalformat == GraphicsContext3D::RGB5_A1 || internalformat == GraphicsContext3D::RGBA4 || internalformat == GraphicsContext3D::SRGB8_ALPHA8))
     1364            break;
     1365        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RGBA8_SNORM)
     1366            break;
     1367        if (type == GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
     1368            && (internalformat == GraphicsContext3D::RGBA || internalformat == GraphicsContext3D::RGBA4))
     1369            break;
     1370        if (type == GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
     1371            && (internalformat == GraphicsContext3D::RGBA || internalformat == GraphicsContext3D::RGB5_A1))
     1372            break;
     1373        if (type == GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV
     1374            && (internalformat == GraphicsContext3D::RGB10_A2 || internalformat == GraphicsContext3D::RGB5_A1))
     1375            break;
     1376        if ((type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::HALF_FLOAT_OES) && internalformat == GraphicsContext3D::RGBA16F)
     1377            break;
     1378        if (type == GraphicsContext3D::FLOAT
     1379            && (internalformat == GraphicsContext3D::RGBA32F || internalformat == GraphicsContext3D::RGBA16F))
     1380            break;
     1381        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1382        return false;
     1383    case GraphicsContext3D::RGBA_INTEGER:
     1384        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::RGBA8UI)
     1385        break;
     1386        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RGBA8I)
     1387        break;
     1388        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::RGBA16UI)
     1389        break;
     1390        if (type == GraphicsContext3D::SHORT && internalformat == GraphicsContext3D::RGBA16I)
     1391        break;
     1392        if (type == GraphicsContext3D::UNSIGNED_INT && internalformat == GraphicsContext3D::RGBA32UI)
     1393        break;
     1394        if (type == GraphicsContext3D::INT && internalformat == GraphicsContext3D::RGBA32I)
     1395        break;
     1396        if (type == GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV && internalformat == GraphicsContext3D::RGB10_A2UI)
     1397            break;
     1398        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1399        return false;
     1400    case GraphicsContext3D::RGB:
     1401        if (type == GraphicsContext3D::UNSIGNED_BYTE
     1402            && (internalformat == GraphicsContext3D::RGB || internalformat == GraphicsContext3D::RGB8 || internalformat == GraphicsContext3D::RGB565
     1403            || internalformat == GraphicsContext3D::SRGB8))
     1404            break;
     1405        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RGB8_SNORM)
     1406            break;
     1407        if (type == GraphicsContext3D::UNSIGNED_SHORT_5_6_5
     1408            && (internalformat == GraphicsContext3D::RGB || internalformat == GraphicsContext3D::RGB565))
     1409            break;
     1410        if (type == GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV && internalformat == GraphicsContext3D::R11F_G11F_B10F)
     1411            break;
     1412        if (type == GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV && internalformat == GraphicsContext3D::RGB9_E5)
     1413            break;
     1414        if ((type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::HALF_FLOAT_OES)
     1415            && (internalformat == GraphicsContext3D::RGB16F || internalformat == GraphicsContext3D::R11F_G11F_B10F || internalformat == GraphicsContext3D::RGB9_E5))
     1416            break;
     1417        if (type == GraphicsContext3D::FLOAT
     1418            && (internalformat == GraphicsContext3D::RGB32F || internalformat == GraphicsContext3D::RGB16F || internalformat == GraphicsContext3D::R11F_G11F_B10F || internalformat == GraphicsContext3D::RGB9_E5))
     1419            break;
     1420        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1421        return false;
     1422    case GraphicsContext3D::RGB_INTEGER:
     1423        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::RGB8UI)
     1424            break;
     1425        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RGB8I)
     1426            break;
     1427        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::RGB16UI)
     1428            break;
     1429        if (type == GraphicsContext3D::SHORT && internalformat == GraphicsContext3D::RGB16I)
     1430            break;
     1431        if (type == GraphicsContext3D::UNSIGNED_INT && internalformat == GraphicsContext3D::RGB32UI)
     1432            break;
     1433        if (type == GraphicsContext3D::INT && internalformat == GraphicsContext3D::RGB32I)
     1434            break;
     1435        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1436        return false;
     1437    case GraphicsContext3D::RG:
     1438        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::RG8)
     1439            break;
     1440        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RG8_SNORM)
     1441            break;
     1442        if ((type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::HALF_FLOAT_OES) && internalformat == GraphicsContext3D::RG16F)
     1443            break;
     1444        if (type == GraphicsContext3D::FLOAT
     1445            && (internalformat == GraphicsContext3D::RG32F || internalformat == GraphicsContext3D::RG16F))
     1446            break;
     1447        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1448        return false;
     1449    case GraphicsContext3D::RG_INTEGER:
     1450        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::RG8UI)
     1451            break;
     1452        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::RG8I)
     1453            break;
     1454        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::RG16UI)
     1455            break;
     1456        if (type == GraphicsContext3D::SHORT && internalformat == GraphicsContext3D::RG16I)
     1457            break;
     1458        if (type == GraphicsContext3D::UNSIGNED_INT && internalformat == GraphicsContext3D::RG32UI)
     1459            break;
     1460        if (type == GraphicsContext3D::INT && internalformat == GraphicsContext3D::RG32I)
     1461            break;
     1462        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1463        return false;
     1464    case GraphicsContext3D::RED:
     1465        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::R8)
     1466            break;
     1467        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::R8_SNORM)
     1468            break;
     1469        if ((type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::HALF_FLOAT_OES) && internalformat == GraphicsContext3D::R16F)
     1470            break;
     1471        if (type == GraphicsContext3D::FLOAT
     1472            && (internalformat == GraphicsContext3D::R32F || internalformat == GraphicsContext3D::R16F))
     1473            break;
     1474        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1475        return false;
     1476    case GraphicsContext3D::RED_INTEGER:
     1477        if (type == GraphicsContext3D::UNSIGNED_BYTE && internalformat == GraphicsContext3D::R8UI)
     1478            break;
     1479        if (type == GraphicsContext3D::BYTE && internalformat == GraphicsContext3D::R8I)
     1480            break;
     1481        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::R16UI)
     1482            break;
     1483        if (type == GraphicsContext3D::SHORT && internalformat == GraphicsContext3D::R16I)
     1484            break;
     1485        if (type == GraphicsContext3D::UNSIGNED_INT && internalformat == GraphicsContext3D::R32UI)
     1486            break;
     1487        if (type == GraphicsContext3D::INT && internalformat == GraphicsContext3D::R32I)
     1488            break;
     1489        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1490        return false;
     1491    case GraphicsContext3D::DEPTH_COMPONENT:
     1492        if (!m_webglDepthTexture) {
     1493            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
     1494            return false;
     1495        }
     1496        if (type == GraphicsContext3D::UNSIGNED_SHORT && internalformat == GraphicsContext3D::DEPTH_COMPONENT16)
     1497            break;
     1498        if (type == GraphicsContext3D::UNSIGNED_INT
     1499            && (internalformat == GraphicsContext3D::DEPTH_COMPONENT24 || internalformat == GraphicsContext3D::DEPTH_COMPONENT16))
     1500            break;
     1501        if (type == GraphicsContext3D::FLOAT && internalformat == GraphicsContext3D::DEPTH_COMPONENT32F)
     1502            break;
     1503        if (level > 0) {
     1504            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
     1505            return false;
     1506        }
     1507        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1508        return false;
     1509    case GraphicsContext3D::DEPTH_STENCIL:
     1510        if (!m_webglDepthTexture || !isDepthStencilSupported()) {
     1511            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
     1512            return false;
     1513        }
     1514        if (type == GraphicsContext3D::UNSIGNED_INT_24_8 && internalformat == GraphicsContext3D::DEPTH24_STENCIL8)
     1515            break;
     1516        if (type == GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV && internalformat == GraphicsContext3D::DEPTH32F_STENCIL8)
     1517            break;
     1518        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1519        return false;
     1520    case GraphicsContext3D::ALPHA:
     1521    case GraphicsContext3D::LUMINANCE:
     1522    case GraphicsContext3D::LUMINANCE_ALPHA:
     1523        if ((type == GraphicsContext3D::UNSIGNED_BYTE || type == GraphicsContext3D::HALF_FLOAT_OES || type == GraphicsContext3D::HALF_FLOAT || type == GraphicsContext3D::FLOAT) && internalformat == format)
     1524            break;
     1525        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format, internalformat, and type combination");
     1526        return false;
     1527    default:
     1528        ASSERT_NOT_REACHED();
     1529    }
     1530
     1531    return true;
     1532}
     1533
     1534bool WebGL2RenderingContext::validateTexFuncData(const char* functionName, GC3Dint level,
     1535    GC3Dsizei width, GC3Dsizei height,
     1536    GC3Denum internalformat, GC3Denum format, GC3Denum type,
     1537    ArrayBufferView* pixels,
     1538    NullDisposition disposition)
     1539{
     1540    if (!pixels) {
     1541        if (disposition == NullAllowed)
     1542            return true;
     1543        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
     1544        return false;
     1545    }
     1546
     1547    if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level))
     1548        return false;
     1549    if (!validateSettableTexFormat(functionName, format))
     1550        return false;
     1551   
     1552    switch (type) {
     1553    case GraphicsContext3D::BYTE:
     1554        if (pixels->getType() != JSC::TypeInt8) {
     1555            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type BYTE but ArrayBufferView not Int8Array");
     1556            return false;
     1557        }
     1558        break;
     1559    case GraphicsContext3D::UNSIGNED_BYTE:
     1560        if (pixels->getType() != JSC::TypeUint8) {
     1561            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
     1562            return false;
     1563        }
     1564        break;
     1565    case GraphicsContext3D::SHORT:
     1566        if (pixels->getType() != JSC::TypeInt16) {
     1567            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type SHORT but ArrayBufferView not Int16Array");
     1568            return false;
     1569        }
     1570        break;
     1571    case GraphicsContext3D::UNSIGNED_SHORT:
     1572    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
     1573    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
     1574    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
     1575        if (pixels->getType() != JSC::TypeUint16) {
     1576            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
     1577            return false;
     1578        }
     1579        break;
     1580    case GraphicsContext3D::INT:
     1581        if (pixels->getType() != JSC::TypeInt32) {
     1582            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type INT but ArrayBufferView not Int32Array");
     1583            return false;
     1584        }
     1585        break;
     1586    case GraphicsContext3D::UNSIGNED_INT:
     1587    case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
     1588    case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
     1589        if (pixels->getType() != JSC::TypeUint32) {
     1590            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_INT but ArrayBufferView not Uint32Array");
     1591            return false;
     1592        }
     1593        break;
     1594    case GraphicsContext3D::HALF_FLOAT:
     1595    case GraphicsContext3D::FLOAT:
     1596        if (pixels->getType() != JSC::TypeFloat32) {
     1597            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
     1598            return false;
     1599        }
     1600        break;
     1601    case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
     1602        // As per the specification, ArrayBufferView should be null when
     1603        // OES_texture_half_float is enabled.
     1604        if (pixels) {
     1605            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
     1606            return false;
     1607        }
     1608        break;
     1609    default:
     1610        ASSERT_NOT_REACHED();
     1611    }
     1612   
     1613    unsigned totalBytesRequired;
     1614    GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
     1615    if (error != GraphicsContext3D::NO_ERROR) {
     1616        synthesizeGLError(error, functionName, "invalid texture dimensions");
     1617        return false;
     1618    }
     1619    if (pixels->byteLength() < totalBytesRequired) {
     1620        if (m_unpackAlignment != 1) {
     1621            error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
     1622            if (pixels->byteLength() == totalBytesRequired) {
     1623                synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
     1624                return false;
     1625            }
     1626        }
     1627        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
     1628        return false;
     1629    }
     1630    return true;
     1631}
     1632
     1633GC3Denum WebGL2RenderingContext::baseInternalFormatFromInternalFormat(GC3Denum internalformat)
     1634{
     1635    // Handles sized, unsized, and compressed internal formats.
     1636    switch (internalformat) {
     1637    case GraphicsContext3D::R8:
     1638    case GraphicsContext3D::R8_SNORM:
     1639    case GraphicsContext3D::R16F:
     1640    case GraphicsContext3D::R32F:
     1641    case GraphicsContext3D::R8I:
     1642    case GraphicsContext3D::R8UI:
     1643    case GraphicsContext3D::R16I:
     1644    case GraphicsContext3D::R16UI:
     1645    case GraphicsContext3D::R32I:
     1646    case GraphicsContext3D::R32UI:
     1647    case GraphicsContext3D::COMPRESSED_R11_EAC:
     1648    case GraphicsContext3D::COMPRESSED_SIGNED_R11_EAC:
     1649        return GraphicsContext3D::RED;
     1650    case GraphicsContext3D::RG8:
     1651    case GraphicsContext3D::RG8_SNORM:
     1652    case GraphicsContext3D::RG16F:
     1653    case GraphicsContext3D::RG32F:
     1654    case GraphicsContext3D::RG8I:
     1655    case GraphicsContext3D::RG8UI:
     1656    case GraphicsContext3D::RG16I:
     1657    case GraphicsContext3D::RG16UI:
     1658    case GraphicsContext3D::RG32I:
     1659    case GraphicsContext3D::RG32UI:
     1660    case GraphicsContext3D::COMPRESSED_RG11_EAC:
     1661    case GraphicsContext3D::COMPRESSED_SIGNED_RG11_EAC:
     1662        return GraphicsContext3D::RG;
     1663    case GraphicsContext3D::RGB8:
     1664    case GraphicsContext3D::RGB8_SNORM:
     1665    case GraphicsContext3D::RGB565:
     1666    case GraphicsContext3D::SRGB8:
     1667    case GraphicsContext3D::RGB16F:
     1668    case GraphicsContext3D::RGB32F:
     1669    case GraphicsContext3D::RGB8I:
     1670    case GraphicsContext3D::RGB8UI:
     1671    case GraphicsContext3D::RGB16I:
     1672    case GraphicsContext3D::RGB16UI:
     1673    case GraphicsContext3D::RGB32I:
     1674    case GraphicsContext3D::RGB32UI:
     1675    case GraphicsContext3D::RGB:
     1676    case GraphicsContext3D::COMPRESSED_RGB8_ETC2:
     1677    case GraphicsContext3D::COMPRESSED_SRGB8_ETC2:
     1678        return GraphicsContext3D::RGB;
     1679    case GraphicsContext3D::RGBA4:
     1680    case GraphicsContext3D::RGB5_A1:
     1681    case GraphicsContext3D::RGBA8:
     1682    case GraphicsContext3D::RGBA8_SNORM:
     1683    case GraphicsContext3D::RGB10_A2:
     1684    case GraphicsContext3D::RGB10_A2UI:
     1685    case GraphicsContext3D::SRGB8_ALPHA8:
     1686    case GraphicsContext3D::RGBA16F:
     1687    case GraphicsContext3D::RGBA32F:
     1688    case GraphicsContext3D::RGBA8I:
     1689    case GraphicsContext3D::RGBA8UI:
     1690    case GraphicsContext3D::RGBA16I:
     1691    case GraphicsContext3D::RGBA16UI:
     1692    case GraphicsContext3D::RGBA32I:
     1693    case GraphicsContext3D::RGBA32UI:
     1694    case GraphicsContext3D::RGBA:
     1695    case GraphicsContext3D::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
     1696    case GraphicsContext3D::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
     1697    case GraphicsContext3D::COMPRESSED_RGBA8_ETC2_EAC:
     1698    case GraphicsContext3D::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
     1699        return GraphicsContext3D::RGBA;
     1700    case GraphicsContext3D::DEPTH_COMPONENT16:
     1701    case GraphicsContext3D::DEPTH_COMPONENT24:
     1702    case GraphicsContext3D::DEPTH_COMPONENT32F:
     1703        return GraphicsContext3D::DEPTH_COMPONENT;
     1704    case GraphicsContext3D::DEPTH24_STENCIL8:
     1705    case GraphicsContext3D::DEPTH32F_STENCIL8:
     1706        return GraphicsContext3D::DEPTH_STENCIL;
     1707    case GraphicsContext3D::LUMINANCE:
     1708    case GraphicsContext3D::LUMINANCE_ALPHA:
     1709    case GraphicsContext3D::ALPHA:
     1710        return internalformat;
     1711    default:
     1712        ASSERT_NOT_REACHED();
     1713        return GraphicsContext3D::NONE;
     1714    }
    9011715}
    9021716
  • trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h

    r179482 r179842  
    4949   
    5050    /* Framebuffer objects */
    51     WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname);
     51    WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode&);
    5252    void blitFramebuffer(GC3Dint srcX0, GC3Dint srcY0, GC3Dint srcX1, GC3Dint srcY1, GC3Dint dstX0, GC3Dint dstY0, GC3Dint dstX1, GC3Dint dstY1, GC3Dbitfield mask, GC3Denum filter);
    5353    void framebufferTextureLayer(GC3Denum target, GC3Denum attachment, GC3Duint texture, GC3Dint level, GC3Dint layer);
     
    170170
    171171    virtual WebGLGetInfo getParameter(GC3Denum pname, ExceptionCode&) override;
    172     bool validateCapability(const char* functionName, GC3Denum cap) override;
     172   
     173    virtual void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) override;
     174    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;
     175    virtual void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&) override;
     176    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     177        GC3Dsizei width, GC3Dsizei height,
     178        GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&) override;
     179    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     180        GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&) override;
     181    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     182        GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&) override;
     183    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     184        GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&) override;
     185#if ENABLE(VIDEO)
     186    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     187        GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&) override;
     188#endif
     189
     190protected:
     191    virtual bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level) override;
     192    virtual bool validateTexFuncParameters(const char* functionName,
     193        TexFuncValidationFunctionType,
     194        GC3Denum target, GC3Dint level,
     195        GC3Denum internalformat,
     196        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
     197        GC3Denum format, GC3Denum type) override;
     198    virtual bool validateTexFuncData(const char* functionName, GC3Dint level,
     199        GC3Dsizei width, GC3Dsizei height,
     200        GC3Denum internalformat, GC3Denum format, GC3Denum type,
     201        ArrayBufferView* pixels,
     202        NullDisposition) override;
     203    virtual bool validateCapability(const char* functionName, GC3Denum cap) override;
     204   
     205private:
     206    GC3Denum baseInternalFormatFromInternalFormat(GC3Denum internalformat);
    173207};
    174208
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp

    r179482 r179842  
    3030
    3131#include "ANGLEInstancedArrays.h"
     32#include "CachedImage.h"
    3233#include "EXTBlendMinMax.h"
    3334#include "EXTFragDepth.h"
     
    3637#include "EXTsRGB.h"
    3738#include "Extensions3D.h"
     39#include "HTMLCanvasElement.h"
     40#include "HTMLImageElement.h"
     41#include "HTMLVideoElement.h"
     42#include "ImageData.h"
    3843#include "OESElementIndexUint.h"
    3944#include "OESStandardDerivatives.h"
     
    4348#include "OESTextureHalfFloatLinear.h"
    4449#include "OESVertexArrayObject.h"
     50#include "RenderBox.h"
    4551#include "WebGLCompressedTextureATC.h"
    4652#include "WebGLCompressedTexturePVRTC.h"
     
    282288}
    283289
     290void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
     291{
     292    if (isContextLostOrPending())
     293        return;
     294    if (!validateTexFuncParameters("copyTexImage2D", CopyTexImage, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
     295        return;
     296    if (!validateSettableTexFormat("copyTexImage2D", internalformat))
     297        return;
     298    WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
     299    if (!tex)
     300        return;
     301    if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
     302        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
     303        return;
     304    }
     305    if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
     306        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
     307        return;
     308    }
     309    const char* reason = "framebuffer incomplete";
     310    if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
     311        synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
     312        return;
     313    }
     314    clearIfComposited();
     315    if (isResourceSafe()) {
     316        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
     317        m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
     318    } else {
     319        ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
     320        GC3Dint clippedX, clippedY;
     321        GC3Dsizei clippedWidth, clippedHeight;
     322        if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
     323            m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
     324                internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
     325            if (clippedWidth > 0 && clippedHeight > 0) {
     326                m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
     327                    clippedX, clippedY, clippedWidth, clippedHeight);
     328            }
     329        } else
     330            m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
     331    }
     332    // FIXME: if the framebuffer is not complete, none of the below should be executed.
     333    tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
     334}
     335
     336void 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)
     337{
     338    UNUSED_PARAM(internalformat);
     339    // FIXME: For now we ignore any errors returned
     340    ec = 0;
     341    ASSERT(!isContextLost());
     342    ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage, target, level, format, width, height, 0, format, type));
     343    ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
     344    ASSERT(validateSettableTexFormat("texSubImage2D", format));
     345    WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
     346    if (!tex) {
     347        ASSERT_NOT_REACHED();
     348        return;
     349    }
     350    ASSERT((xoffset + width) >= 0);
     351    ASSERT((yoffset + height) >= 0);
     352    ASSERT(tex->getWidth(target, level) >= (xoffset + width));
     353    ASSERT(tex->getHeight(target, level) >= (yoffset + height));
     354    ASSERT(tex->getInternalFormat(target, level) == format);
     355    ASSERT(tex->getType(target, level) == type);
     356    m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
     357}
     358
     359void 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)
     360{
     361    ec = 0;
     362    Vector<uint8_t> data;
     363    GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
     364    if (!imageExtractor.extractSucceeded()) {
     365        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
     366        return;
     367    }
     368    GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
     369    GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
     370    const void* imagePixelData = imageExtractor.imagePixelData();
     371   
     372    bool needConversion = true;
     373    if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
     374        needConversion = false;
     375    else {
     376        if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
     377            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
     378            return;
     379        }
     380    }
     381   
     382    if (m_unpackAlignment != 1)
     383        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
     384
     385    texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, format, type, needConversion ? data.data() : imagePixelData, ec);
     386    if (m_unpackAlignment != 1)
     387        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
     388}
     389
     390void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
     391{
     392    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))
     393        return;
     394   
     395    void* data = pixels->baseAddress();
     396    Vector<uint8_t> tempData;
     397    bool changeUnpackAlignment = false;
     398    if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
     399        if (!m_context->extractTextureData(width, height, format, type,
     400            m_unpackAlignment,
     401            m_unpackFlipY, m_unpackPremultiplyAlpha,
     402            data,
     403            tempData))
     404            return;
     405        data = tempData.data();
     406        changeUnpackAlignment = true;
     407    }
     408    if (changeUnpackAlignment)
     409        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
     410
     411    texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, format, type, data, ec);
     412    if (changeUnpackAlignment)
     413        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
     414}
     415
     416void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
     417{
     418    ec = 0;
     419    if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, format,  pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
     420        return;
     421   
     422    Vector<uint8_t> data;
     423    bool needConversion = true;
     424    // The data from ImageData is always of format RGBA8.
     425    // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
     426    if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
     427        needConversion = false;
     428    else {
     429        if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
     430            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
     431            return;
     432        }
     433    }
     434    if (m_unpackAlignment != 1)
     435        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
     436   
     437    texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, format, type, needConversion ? data.data() : pixels->data()->data(), ec);
     438    if (m_unpackAlignment != 1)
     439        m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
     440}
     441
     442void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
     443{
     444    ec = 0;
     445    if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
     446        return;
     447   
     448    RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
     449    if (imageForRender->isSVGImage())
     450        imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
     451   
     452    if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
     453        return;
     454   
     455    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
     456}
     457
     458void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
     459{
     460    ec = 0;
     461    if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
     462        || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
     463        return;
     464   
     465    RefPtr<ImageData> imageData = canvas->getImageData();
     466    if (imageData)
     467        texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
     468    else
     469        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
     470}
     471
     472#if ENABLE(VIDEO)
     473void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
     474{
     475    ec = 0;
     476    if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
     477        || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
     478        return;
     479   
     480    RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
     481    if (!image)
     482        return;
     483    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
     484}
     485#endif
     486
     487bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName,
     488    TexFuncValidationFunctionType functionType,
     489    GC3Denum target, GC3Dint level,
     490    GC3Denum internalformat,
     491    GC3Dsizei width, GC3Dsizei height, GC3Dint border,
     492    GC3Denum format, GC3Denum type)
     493{
     494    // We absolutely have to validate the format and type combination.
     495    // The texImage2D entry points taking HTMLImage, etc. will produce
     496    // temporary data based on this combination, so it must be legal.
     497    if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level) || !validateTexFuncLevel(functionName, target, level))
     498        return false;
     499   
     500    if (width < 0 || height < 0) {
     501        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
     502        return false;
     503    }
     504   
     505    GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
     506    switch (target) {
     507    case GraphicsContext3D::TEXTURE_2D:
     508        if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
     509            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
     510            return false;
     511        }
     512        break;
     513    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
     514    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
     515    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
     516    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
     517    case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
     518    case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
     519        if (functionType != TexSubImage && width != height) {
     520            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
     521            return false;
     522        }
     523        // No need to check height here. For texImage width == height.
     524        // For texSubImage that will be checked when checking yoffset + height is in range.
     525        if (width > maxTextureSizeForLevel) {
     526            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
     527            return false;
     528        }
     529        break;
     530    default:
     531        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
     532        return false;
     533    }
     534
     535    if (format != internalformat) {
     536        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
     537        return false;
     538    }
     539   
     540    if (border) {
     541        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
     542        return false;
     543    }
     544   
     545    return true;
     546}
     547
     548bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level)
     549{
     550    UNUSED_PARAM(internalformat);
     551    switch (format) {
     552    case GraphicsContext3D::ALPHA:
     553    case GraphicsContext3D::LUMINANCE:
     554    case GraphicsContext3D::LUMINANCE_ALPHA:
     555    case GraphicsContext3D::RGB:
     556    case GraphicsContext3D::RGBA:
     557        break;
     558    case GraphicsContext3D::DEPTH_STENCIL:
     559    case GraphicsContext3D::DEPTH_COMPONENT:
     560        if (m_webglDepthTexture)
     561            break;
     562        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
     563        return false;
     564    case Extensions3D::SRGB_EXT:
     565    case Extensions3D::SRGB_ALPHA_EXT:
     566    default:
     567        if ((format == Extensions3D::SRGB_EXT || format == Extensions3D::SRGB_ALPHA_EXT)
     568            && m_extsRGB)
     569            break;
     570        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
     571        return false;
     572    }
     573   
     574    switch (type) {
     575    case GraphicsContext3D::UNSIGNED_BYTE:
     576    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
     577    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
     578    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
     579        break;
     580    case GraphicsContext3D::FLOAT:
     581        if (m_oesTextureFloat)
     582            break;
     583        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
     584        return false;
     585    case GraphicsContext3D::HALF_FLOAT_OES:
     586        if (m_oesTextureHalfFloat)
     587            break;
     588        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
     589        return false;
     590    case GraphicsContext3D::UNSIGNED_INT:
     591    case GraphicsContext3D::UNSIGNED_INT_24_8:
     592    case GraphicsContext3D::UNSIGNED_SHORT:
     593        if (m_webglDepthTexture)
     594            break;
     595        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
     596        return false;
     597    default:
     598        synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
     599        return false;
     600    }
     601   
     602    // Verify that the combination of format and type is supported.
     603    switch (format) {
     604    case GraphicsContext3D::ALPHA:
     605    case GraphicsContext3D::LUMINANCE:
     606    case GraphicsContext3D::LUMINANCE_ALPHA:
     607        if (type != GraphicsContext3D::UNSIGNED_BYTE
     608            && type != GraphicsContext3D::FLOAT
     609            && type != GraphicsContext3D::HALF_FLOAT_OES) {
     610            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
     611            return false;
     612        }
     613        break;
     614    case GraphicsContext3D::RGB:
     615    case Extensions3D::SRGB_EXT:
     616        if (type != GraphicsContext3D::UNSIGNED_BYTE
     617            && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
     618            && type != GraphicsContext3D::FLOAT
     619            && type != GraphicsContext3D::HALF_FLOAT_OES) {
     620            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
     621            return false;
     622        }
     623        break;
     624    case GraphicsContext3D::RGBA:
     625    case Extensions3D::SRGB_ALPHA_EXT:
     626        if (type != GraphicsContext3D::UNSIGNED_BYTE
     627            && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
     628            && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
     629            && type != GraphicsContext3D::FLOAT
     630            && type != GraphicsContext3D::HALF_FLOAT_OES) {
     631            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
     632            return false;
     633        }
     634        break;
     635    case GraphicsContext3D::DEPTH_COMPONENT:
     636        if (!m_webglDepthTexture) {
     637            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
     638            return false;
     639        }
     640        if (type != GraphicsContext3D::UNSIGNED_SHORT
     641            && type != GraphicsContext3D::UNSIGNED_INT) {
     642            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
     643            return false;
     644        }
     645        if (level > 0) {
     646            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
     647            return false;
     648        }
     649        break;
     650    case GraphicsContext3D::DEPTH_STENCIL:
     651        if (!m_webglDepthTexture) {
     652            synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
     653            return false;
     654        }
     655        if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
     656            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
     657            return false;
     658        }
     659        if (level > 0) {
     660            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
     661            return false;
     662        }
     663        break;
     664    default:
     665        ASSERT_NOT_REACHED();
     666    }
     667   
     668    return true;
     669}
     670
     671bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, NullDisposition disposition)
     672{
     673    if (!pixels) {
     674        if (disposition == NullAllowed)
     675            return true;
     676        synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
     677        return false;
     678    }
     679
     680    if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level))
     681        return false;
     682    if (!validateSettableTexFormat(functionName, format))
     683        return false;
     684   
     685    switch (type) {
     686    case GraphicsContext3D::UNSIGNED_BYTE:
     687        if (pixels->getType() != JSC::TypeUint8) {
     688            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
     689            return false;
     690        }
     691        break;
     692    case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
     693    case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
     694    case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
     695        if (pixels->getType() != JSC::TypeUint16) {
     696            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
     697            return false;
     698        }
     699        break;
     700    case GraphicsContext3D::FLOAT: // OES_texture_float
     701        if (pixels->getType() != JSC::TypeFloat32) {
     702            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
     703            return false;
     704        }
     705        break;
     706    case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
     707        // As per the specification, ArrayBufferView should be null when
     708        // OES_texture_half_float is enabled.
     709        if (pixels) {
     710            synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
     711            return false;
     712        }
     713        break;
     714    default:
     715        ASSERT_NOT_REACHED();
     716    }
     717   
     718    unsigned totalBytesRequired;
     719    GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
     720    if (error != GraphicsContext3D::NO_ERROR) {
     721        synthesizeGLError(error, functionName, "invalid texture dimensions");
     722        return false;
     723    }
     724    if (pixels->byteLength() < totalBytesRequired) {
     725        if (m_unpackAlignment != 1) {
     726            error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
     727            if (pixels->byteLength() == totalBytesRequired) {
     728                synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
     729                return false;
     730            }
     731        }
     732        synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
     733        return false;
     734    }
     735    return true;
     736}
     737
    284738WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec)
    285739{
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContext.h

    r179482 r179842  
    4040    virtual WebGLGetInfo getParameter(GC3Denum pname, ExceptionCode&) override;
    4141    virtual Vector<String> getSupportedExtensions() override;
    42     bool validateCapability(const char* functionName, GC3Denum cap) override;
     42
     43    virtual void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) override;
     44    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;
     45    virtual void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&) override;
     46    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     47        GC3Dsizei width, GC3Dsizei height,
     48        GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&) override;
     49    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     50        GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&) override;
     51    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     52        GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&) override;
     53    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     54        GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&) override;
     55#if ENABLE(VIDEO)
     56    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     57        GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&) override;
     58#endif
     59
     60protected:
     61    virtual bool validateTexFuncParameters(const char* functionName,
     62        TexFuncValidationFunctionType,
     63        GC3Denum target, GC3Dint level,
     64        GC3Denum internalformat,
     65        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
     66        GC3Denum format, GC3Denum type) override;
     67    virtual bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level) override;
     68    virtual bool validateTexFuncData(const char* functionName, GC3Dint level,
     69        GC3Dsizei width, GC3Dsizei height,
     70        GC3Denum internalformat, GC3Denum format, GC3Denum type,
     71        ArrayBufferView* pixels,
     72        NullDisposition) override;
     73    virtual bool validateCapability(const char* functionName, GC3Denum cap) override;
    4374};
    4475   
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp

    r179530 r179842  
    100100
    101101namespace {
    102 
    103     class ScopedDrawingBufferBinder {
    104     public:
    105         ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding)
    106             : m_drawingBuffer(drawingBuffer)
    107             , m_framebufferBinding(framebufferBinding)
    108         {
    109             // Commit DrawingBuffer if needed (e.g., for multisampling)
    110             if (!m_framebufferBinding && m_drawingBuffer)
    111                 m_drawingBuffer->commit();
    112         }
    113 
    114         ~ScopedDrawingBufferBinder()
    115         {
    116             // Restore DrawingBuffer if needed
    117             if (!m_framebufferBinding && m_drawingBuffer)
    118                 m_drawingBuffer->bind();
    119         }
    120 
    121     private:
    122         DrawingBuffer* m_drawingBuffer;
    123         WebGLFramebuffer* m_framebufferBinding;
    124     };
    125 
     102   
    126103    Platform3DObject objectOrZero(WebGLObject* object)
    127104    {
    128105        return object ? object->object() : 0;
    129     }
    130 
    131     void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
    132     {
    133         ASSERT(clippedStart && clippedRange);
    134         if (start < 0) {
    135             range += start;
    136             start = 0;
    137         }
    138         GC3Dint end = start + range;
    139         if (end > sourceRange)
    140             range -= end - sourceRange;
    141         *clippedStart = start;
    142         *clippedRange = range;
    143     }
    144 
    145     // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
    146     bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
    147                 GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
    148                 GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
    149     {
    150         ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
    151         clip1D(x, width, sourceWidth, clippedX, clippedWidth);
    152         clip1D(y, height, sourceHeight, clippedY, clippedHeight);
    153         return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
    154106    }
    155107
     
    14411393    }
    14421394    return true;
    1443 }
    1444 
    1445 void WebGLRenderingContextBase::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
    1446 {
    1447     if (isContextLostOrPending())
    1448         return;
    1449     if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
    1450         return;
    1451     if (!validateSettableTexFormat("copyTexImage2D", internalformat))
    1452         return;
    1453     WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
    1454     if (!tex)
    1455         return;
    1456     if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
    1457         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
    1458         return;
    1459     }
    1460     if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
    1461         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
    1462         return;
    1463     }
    1464     const char* reason = "framebuffer incomplete";
    1465     if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
    1466         synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
    1467         return;
    1468     }
    1469     clearIfComposited();
    1470     if (isResourceSafe()) {
    1471         ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
    1472         m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
    1473     } else {
    1474         ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get());
    1475         GC3Dint clippedX, clippedY;
    1476         GC3Dsizei clippedWidth, clippedHeight;
    1477         if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
    1478             m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
    1479                                               internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
    1480             if (clippedWidth > 0 && clippedHeight > 0) {
    1481                 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
    1482                                              clippedX, clippedY, clippedWidth, clippedHeight);
    1483             }
    1484         } else
    1485             m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
    1486     }
    1487     // FIXME: if the framebuffer is not complete, none of the below should be executed.
    1488     tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
    14891395}
    14901396
     
    35483454    ec = 0;
    35493455    WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
    3550     ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type));
     3456    ASSERT(validateTexFuncParameters("texImage2D", TexImage, target, level, internalformat, width, height, border, format, type));
    35513457    ASSERT(tex);
    35523458    ASSERT(!level || !WebGLTexture::isNPOT(width, height));
     
    36173523        return false;
    36183524
    3619     if (functionType == NotTexSubImage2D) {
     3525    if (functionType != TexSubImage) {
    36203526        if (level && WebGLTexture::isNPOT(width, height)) {
    36213527            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level > 0 not power of 2");
     
    36553561                                       GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
    36563562{
    3657     if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed)
    3658         || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0))
     3563    if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, internalformat, format, type, pixels, NullAllowed)
     3564        || !validateTexFunc("texImage2D", TexImage, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0))
    36593565        return;
    36603566    void* data = pixels ? pixels->baseAddress() : 0;
     
    36833589{
    36843590    ec = 0;
    3685     if (isContextLostOrPending() || !pixels || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0))
     3591    if (isContextLostOrPending() || !pixels || !validateTexFunc("texImage2D", TexImage, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0))
    36863592        return;
    36873593    Vector<uint8_t> data;
     
    37313637        imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
    37323638
    3733     if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0))
     3639    if (!imageForRender || !validateTexFunc("texImage2D", TexImage, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0))
    37343640        return;
    37353641
     
    37413647{
    37423648    ec = 0;
    3743     if (isContextLostOrPending() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0))
     3649    if (isContextLostOrPending() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", TexImage, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0))
    37443650        return;
    37453651
     
    37863692    ec = 0;
    37873693    if (isContextLostOrPending() || !validateHTMLVideoElement("texImage2D", video, ec)
    3788         || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0))
     3694        || !validateTexFunc("texImage2D", TexImage, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0))
    37893695        return;
    37903696
     
    38603766    texParameter(target, pname, 0, param, false);
    38613767}
    3862 
    3863 void WebGLRenderingContextBase::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec)
    3864 {
    3865     // FIXME: For now we ignore any errors returned
    3866     ec = 0;
    3867     ASSERT(!isContextLost());
    3868     ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type));
    3869     ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
    3870     ASSERT(validateSettableTexFormat("texSubImage2D", format));
    3871     WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
    3872     if (!tex) {
    3873         ASSERT_NOT_REACHED();
    3874         return;
    3875     }
    3876     ASSERT((xoffset + width) >= 0);
    3877     ASSERT((yoffset + height) >= 0);
    3878     ASSERT(tex->getWidth(target, level) >= (xoffset + width));
    3879     ASSERT(tex->getHeight(target, level) >= (yoffset + height));
    3880     ASSERT(tex->getInternalFormat(target, level) == format);
    3881     ASSERT(tex->getType(target, level) == type);
    3882     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
    3883 }
    3884 
    3885 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)
    3886 {
    3887     ec = 0;
    3888     Vector<uint8_t> data;
    3889     GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE); 
    3890     if (!imageExtractor.extractSucceeded()) {
    3891         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
    3892         return;
    3893     }
    3894     GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
    3895     GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
    3896     const void* imagePixelData = imageExtractor.imagePixelData();
    3897 
    3898     bool needConversion = true;
    3899     if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
    3900         needConversion = false;
    3901     else {
    3902         if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
    3903             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
    3904             return;
    3905         }
    3906     }
    3907 
    3908     if (m_unpackAlignment != 1)
    3909         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
    3910     texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, type,  needConversion ? data.data() : imagePixelData, ec);
    3911     if (m_unpackAlignment != 1)
    3912         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
    3913 }
    3914 
    3915 void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    3916                                           GC3Dsizei width, GC3Dsizei height,
    3917                                           GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
    3918 {
    3919     if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed)
    3920         || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
    3921         return;
    3922     void* data = pixels->baseAddress();
    3923     Vector<uint8_t> tempData;
    3924     bool changeUnpackAlignment = false;
    3925     if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
    3926         if (!m_context->extractTextureData(width, height, format, type,
    3927                                            m_unpackAlignment,
    3928                                            m_unpackFlipY, m_unpackPremultiplyAlpha,
    3929                                            data,
    3930                                            tempData))
    3931             return;
    3932         data = tempData.data();
    3933         changeUnpackAlignment = true;
    3934     }
    3935     if (changeUnpackAlignment)
    3936         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
    3937     texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
    3938     if (changeUnpackAlignment)
    3939         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
    3940 }
    3941 
    3942 void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    3943                                           GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
    3944 {
    3945     ec = 0;
    3946     if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceImageData, target, level, format,  pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
    3947         return;
    3948 
    3949     Vector<uint8_t> data;
    3950     bool needConversion = true;
    3951     // The data from ImageData is always of format RGBA8.
    3952     // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
    3953     if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
    3954         needConversion = false;
    3955     else {
    3956         if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
    3957             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
    3958             return;
    3959         }
    3960     }
    3961     if (m_unpackAlignment != 1)
    3962         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
    3963     texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), ec);
    3964     if (m_unpackAlignment != 1)
    3965         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
    3966 }
    3967 
    3968 void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    3969                                           GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
    3970 {
    3971     ec = 0;
    3972     if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image, ec))
    3973         return;
    3974 
    3975     RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
    3976     if (imageForRender->isSVGImage())
    3977         imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), 1);
    3978 
    3979     if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
    3980         return;
    3981 
    3982     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
    3983 }
    3984 
    3985 void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    3986                                           GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
    3987 {
    3988     ec = 0;
    3989     if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec)
    3990         || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
    3991         return;
    3992 
    3993     RefPtr<ImageData> imageData = canvas->getImageData();
    3994     if (imageData)
    3995         texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
    3996     else
    3997         texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
    3998 }
    3999 
    4000 #if ENABLE(VIDEO)
    4001 void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    4002                                           GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
    4003 {
    4004     ec = 0;
    4005     if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video, ec)
    4006         || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
    4007         return;
    4008 
    4009     RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec);
    4010     if (!image)
    4011         return;
    4012     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
    4013 }
    4014 #endif
    40153768
    40163769void WebGLRenderingContextBase::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
     
    48644617}
    48654618
    4866 bool WebGLRenderingContextBase::validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level)
    4867 {
    4868     switch (format) {
    4869     case GraphicsContext3D::ALPHA:
    4870     case GraphicsContext3D::LUMINANCE:
    4871     case GraphicsContext3D::LUMINANCE_ALPHA:
    4872     case GraphicsContext3D::RGB:
    4873     case GraphicsContext3D::RGBA:
    4874         break;
    4875     case GraphicsContext3D::DEPTH_STENCIL:
    4876     case GraphicsContext3D::DEPTH_COMPONENT:
    4877         if (m_webglDepthTexture)
    4878             break;
    4879         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
    4880         return false;
    4881     case Extensions3D::SRGB_EXT:
    4882     case Extensions3D::SRGB_ALPHA_EXT:
    4883     default:
    4884         if ((format == Extensions3D::SRGB_EXT || format == Extensions3D::SRGB_ALPHA_EXT)
    4885             && m_extsRGB)
    4886             break;
    4887         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
    4888         return false;
    4889     }
    4890 
    4891     switch (type) {
    4892     case GraphicsContext3D::UNSIGNED_BYTE:
    4893     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
    4894     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
    4895     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
    4896         break;
    4897     case GraphicsContext3D::FLOAT:
    4898         if (m_oesTextureFloat)
    4899             break;
    4900         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
    4901         return false;
    4902     case GraphicsContext3D::HALF_FLOAT_OES:
    4903         if (m_oesTextureHalfFloat)
    4904             break;
    4905         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
    4906         return false;
    4907     case GraphicsContext3D::UNSIGNED_INT:
    4908     case GraphicsContext3D::UNSIGNED_INT_24_8:
    4909     case GraphicsContext3D::UNSIGNED_SHORT:
    4910         if (m_webglDepthTexture)
    4911             break;
    4912         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
    4913         return false;
    4914     default:
    4915         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
    4916         return false;
    4917     }
    4918 
    4919     // Verify that the combination of format and type is supported.
    4920     switch (format) {
    4921     case GraphicsContext3D::ALPHA:
    4922     case GraphicsContext3D::LUMINANCE:
    4923     case GraphicsContext3D::LUMINANCE_ALPHA:
    4924         if (type != GraphicsContext3D::UNSIGNED_BYTE
    4925             && type != GraphicsContext3D::FLOAT
    4926             && type != GraphicsContext3D::HALF_FLOAT_OES) {
    4927             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
    4928             return false;
    4929         }
    4930         break;
    4931     case GraphicsContext3D::RGB:
    4932     case Extensions3D::SRGB_EXT:
    4933         if (type != GraphicsContext3D::UNSIGNED_BYTE
    4934             && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
    4935             && type != GraphicsContext3D::FLOAT
    4936             && type != GraphicsContext3D::HALF_FLOAT_OES) {
    4937             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
    4938             return false;
    4939         }
    4940         break;
    4941     case GraphicsContext3D::RGBA:
    4942     case Extensions3D::SRGB_ALPHA_EXT:
    4943         if (type != GraphicsContext3D::UNSIGNED_BYTE
    4944             && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
    4945             && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
    4946             && type != GraphicsContext3D::FLOAT
    4947             && type != GraphicsContext3D::HALF_FLOAT_OES) {
    4948             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
    4949             return false;
    4950         }
    4951         break;
    4952     case GraphicsContext3D::DEPTH_COMPONENT:
    4953         if (!m_webglDepthTexture) {
    4954             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
    4955             return false;
    4956         }
    4957         if (type != GraphicsContext3D::UNSIGNED_SHORT
    4958             && type != GraphicsContext3D::UNSIGNED_INT) {
    4959             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
    4960             return false;
    4961         }
    4962         if (level > 0) {
    4963           synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
    4964           return false;
    4965         }
    4966         break;
    4967     case GraphicsContext3D::DEPTH_STENCIL:
    4968         if (!m_webglDepthTexture) {
    4969             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
    4970             return false;
    4971         }
    4972         if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
    4973             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
    4974             return false;
    4975         }
    4976         if (level > 0) {
    4977           synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
    4978           return false;
    4979         }
    4980         break;
    4981     default:
    4982         ASSERT_NOT_REACHED();
    4983     }
    4984 
    4985     return true;
    4986 }
    4987 
    49884619bool WebGLRenderingContextBase::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level)
    49894620{
     
    50134644    // This function only checks if level is legal, so we return true and don't
    50144645    // generate INVALID_ENUM if target is illegal.
    5015     return true;
    5016 }
    5017 
    5018 bool WebGLRenderingContextBase::validateTexFuncParameters(const char* functionName,
    5019                                                       TexFuncValidationFunctionType functionType,
    5020                                                       GC3Denum target, GC3Dint level,
    5021                                                       GC3Denum internalformat,
    5022                                                       GC3Dsizei width, GC3Dsizei height, GC3Dint border,
    5023                                                       GC3Denum format, GC3Denum type)
    5024 {
    5025     // We absolutely have to validate the format and type combination.
    5026     // The texImage2D entry points taking HTMLImage, etc. will produce
    5027     // temporary data based on this combination, so it must be legal.
    5028     if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level))
    5029         return false;
    5030 
    5031     if (width < 0 || height < 0) {
    5032         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
    5033         return false;
    5034     }
    5035 
    5036     GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
    5037     switch (target) {
    5038     case GraphicsContext3D::TEXTURE_2D:
    5039         if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
    5040             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
    5041             return false;
    5042         }
    5043         break;
    5044     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
    5045     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
    5046     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
    5047     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
    5048     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
    5049     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
    5050         if (functionType != TexSubImage2D && width != height) {
    5051             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
    5052             return false;
    5053         }
    5054         // No need to check height here. For texImage width == height.
    5055         // For texSubImage that will be checked when checking yoffset + height is in range.
    5056         if (width > maxTextureSizeForLevel) {
    5057             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
    5058             return false;
    5059         }
    5060         break;
    5061     default:
    5062         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
    5063         return false;
    5064     }
    5065 
    5066     if (format != internalformat) {
    5067         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
    5068         return false;
    5069     }
    5070 
    5071     if (border) {
    5072         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
    5073         return false;
    5074     }
    5075 
    5076     return true;
    5077 }
    5078 
    5079 bool WebGLRenderingContextBase::validateTexFuncData(const char* functionName, GC3Dint level,
    5080                                                 GC3Dsizei width, GC3Dsizei height,
    5081                                                 GC3Denum format, GC3Denum type,
    5082                                                 ArrayBufferView* pixels,
    5083                                                 NullDisposition disposition)
    5084 {
    5085     if (!pixels) {
    5086         if (disposition == NullAllowed)
    5087             return true;
    5088         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
    5089         return false;
    5090     }
    5091 
    5092     if (!validateTexFuncFormatAndType(functionName, format, type, level))
    5093         return false;
    5094     if (!validateSettableTexFormat(functionName, format))
    5095         return false;
    5096 
    5097     switch (type) {
    5098     case GraphicsContext3D::UNSIGNED_BYTE:
    5099         if (pixels->getType() != JSC::TypeUint8) {
    5100             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
    5101             return false;
    5102         }
    5103         break;
    5104     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
    5105     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
    5106     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
    5107         if (pixels->getType() != JSC::TypeUint16) {
    5108             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
    5109             return false;
    5110         }
    5111         break;
    5112     case GraphicsContext3D::FLOAT: // OES_texture_float
    5113         if (pixels->getType() != JSC::TypeFloat32) {
    5114             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
    5115             return false;
    5116         }
    5117         break;
    5118     case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
    5119         // As per the specification, ArrayBufferView should be null when
    5120         // OES_texture_half_float is enabled.
    5121         if (pixels) {
    5122             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
    5123             return false;
    5124         }
    5125         break;
    5126     default:
    5127         ASSERT_NOT_REACHED();
    5128     }
    5129 
    5130     unsigned int totalBytesRequired;
    5131     GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
    5132     if (error != GraphicsContext3D::NO_ERROR) {
    5133         synthesizeGLError(error, functionName, "invalid texture dimensions");
    5134         return false;
    5135     }
    5136     if (pixels->byteLength() < totalBytesRequired) {
    5137         if (m_unpackAlignment != 1) {
    5138           error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
    5139           if (pixels->byteLength() == totalBytesRequired) {
    5140             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
    5141             return false;
    5142           }
    5143         }
    5144         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
    5145         return false;
    5146     }
    51474646    return true;
    51484647}
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h

    r179530 r179842  
    3434#include "Timer.h"
    3535#include "WebGLGetInfo.h"
     36#include "WebGLObject.h"
    3637#include <memory>
    3738#include <runtime/Float32Array.h>
     
    8687typedef int ExceptionCode;
    8788
     89class ScopedDrawingBufferBinder {
     90public:
     91    ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding)
     92        : m_drawingBuffer(drawingBuffer)
     93        , m_framebufferBinding(framebufferBinding)
     94    {
     95        // Commit DrawingBuffer if needed (e.g., for multisampling)
     96        if (!m_framebufferBinding && m_drawingBuffer)
     97            m_drawingBuffer->commit();
     98    }
     99   
     100    ~ScopedDrawingBufferBinder()
     101    {
     102        // Restore DrawingBuffer if needed
     103        if (!m_framebufferBinding && m_drawingBuffer)
     104            m_drawingBuffer->bind();
     105    }
     106   
     107private:
     108    DrawingBuffer* m_drawingBuffer;
     109    WebGLFramebuffer* m_framebufferBinding;
     110};
     111
     112inline void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
     113{
     114    ASSERT(clippedStart && clippedRange);
     115    if (start < 0) {
     116        range += start;
     117        start = 0;
     118    }
     119    GC3Dint end = start + range;
     120    if (end > sourceRange)
     121        range -= end - sourceRange;
     122    *clippedStart = start;
     123    *clippedRange = range;
     124}
     125
     126// Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
     127inline bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
     128    GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
     129    GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight)
     130{
     131    ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
     132    clip1D(x, width, sourceWidth, clippedX, clippedWidth);
     133    clip1D(y, height, sourceHeight, clippedY, clippedHeight);
     134    return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height);
     135}
     136
    88137class WebGLRenderingContextBase : public CanvasRenderingContext, public ActiveDOMObject {
    89138public:
     
    133182                                 GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data);
    134183
    135     void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
     184    virtual void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) = 0;
    136185    void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
    137186
     
    238287    void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
    239288
    240     void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    241                        GC3Dsizei width, GC3Dsizei height,
    242                        GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&);
    243     void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    244                        GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&);
    245     void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    246                        GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&);
    247     void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    248                        GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&);
     289    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     290        GC3Dsizei width, GC3Dsizei height,
     291        GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&) = 0;
     292    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     293        GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&) = 0;
     294    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     295        GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&) = 0;
     296    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     297        GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&) = 0;
    249298#if ENABLE(VIDEO)
    250     void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
    251                        GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&);
     299    virtual void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
     300        GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&) = 0;
    252301#endif
    253302
     
    585634    void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
    586635    void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
    587     void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&);
    588     void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&);
     636    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;
     637    virtual void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&) = 0;
    589638
    590639    void checkTextureCompleteness(const char*, bool);
     
    625674    // Helper function to check input format/type for functions {copy}Tex{Sub}Image.
    626675    // Generates GL error and returns false if parameters are invalid.
    627     bool validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level);
     676    virtual bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level) = 0;
    628677
    629678    // Helper function to check input level for functions {copy}Tex{Sub}Image.
     
    632681
    633682    enum TexFuncValidationFunctionType {
    634         NotTexSubImage2D,
    635         TexSubImage2D,
     683        TexImage,
     684        TexSubImage,
     685        CopyTexImage
    636686    };
    637687
     
    651701    // Helper function to check input parameters for functions {copy}Tex{Sub}Image.
    652702    // Generates GL error and returns false if parameters are invalid.
    653     bool validateTexFuncParameters(const char* functionName,
    654                                    TexFuncValidationFunctionType,
    655                                    GC3Denum target, GC3Dint level,
    656                                    GC3Denum internalformat,
    657                                    GC3Dsizei width, GC3Dsizei height, GC3Dint border,
    658                                    GC3Denum format, GC3Denum type);
     703    virtual bool validateTexFuncParameters(const char* functionName,
     704        TexFuncValidationFunctionType,
     705        GC3Denum target, GC3Dint level,
     706        GC3Denum internalformat,
     707        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
     708        GC3Denum format, GC3Denum type) = 0;
    659709
    660710    enum NullDisposition {
     
    666716    // is of the correct type and contains enough data for the texImage call.
    667717    // Generates GL error and returns false if parameters are invalid.
    668     bool validateTexFuncData(const char* functionName, GC3Dint level,
    669                              GC3Dsizei width, GC3Dsizei height,
    670                             GC3Denum format, GC3Denum type,
    671                              ArrayBufferView* pixels,
    672                              NullDisposition);
     718    virtual bool validateTexFuncData(const char* functionName, GC3Dint level,
     719        GC3Dsizei width, GC3Dsizei height,
     720        GC3Denum internalformat, GC3Denum format, GC3Denum type,
     721        ArrayBufferView* pixels,
     722        NullDisposition) = 0;
    673723
    674724    // Helper function to validate a given texture format is settable as in
  • trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h

    r179530 r179842  
    509509        RGBA32F = 0x8814,
    510510        RGB32F = 0x8815,
    511         RGBA16 = 0x881A,
     511        RGBA16F = 0x881A,
    512512        RGB16F = 0x881B,
    513513        VERTEX_ATTRIB_ARRAY_INTEGER = 0x88FD,
Note: See TracChangeset for help on using the changeset viewer.