| Index: third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
|
| diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
|
| index f9bec570ac2fb0685d666ba733f3f2a2b1811ad3..fb622a1592c3a19a6608e8f9d254a72977d142b9 100644
|
| --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
|
| +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
|
| @@ -3976,8 +3976,9 @@ void WebGLRenderingContextBase::texImage2DBase(GLenum target, GLint level, GLint
|
| contextGL()->TexImage2D(target, level, convertTexInternalFormat(internalformat, type), width, height, border, format, type, pixels);
|
| }
|
|
|
| -void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLint internalformat, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
|
| +void WebGLRenderingContextBase::texImageImpl(TexImageFunctionID functionID, GLenum target, GLint level, GLint internalformat, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
|
| {
|
| + const char* funcName = getTexImageFunctionName(functionID);
|
| // All calling functions check isContextLost, so a duplicate check is not needed here.
|
| if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
|
| // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented.
|
| @@ -3986,7 +3987,7 @@ void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLint
|
| Vector<uint8_t> data;
|
| WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE);
|
| if (!imageExtractor.imagePixelData()) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data");
|
| + synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data");
|
| return;
|
| }
|
| WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
|
| @@ -3998,13 +3999,20 @@ void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLint
|
| needConversion = false;
|
| } else {
|
| if (!WebGLImageConversion::packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "packImage error");
|
| + synthesizeGLError(GL_INVALID_VALUE, funcName, "packImage error");
|
| return;
|
| }
|
| }
|
|
|
| resetUnpackParameters();
|
| - texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 0, format, type, needConversion ? data.data() : imagePixelData);
|
| + if (functionID == TexImage2D) {
|
| + texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 0, format, type, needConversion ? data.data() : imagePixelData);
|
| + } else if (functionID == TexSubImage2D) {
|
| + contextGL()->TexSubImage2D(target, level, xoffset, yoffset, imageExtractor.imageWidth(), imageExtractor.imageHeight(), format, type, needConversion ? data.data() : imagePixelData);
|
| + } else {
|
| + DCHECK_EQ(functionID, TexSubImage3D);
|
| + contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 1, format, type, needConversion ? data.data() : imagePixelData);
|
| + }
|
| restoreUnpackParameters();
|
| }
|
|
|
| @@ -4073,50 +4081,111 @@ PassRefPtr<Image> WebGLRenderingContextBase::drawImageIntoBuffer(PassRefPtr<Imag
|
| return buf->newImageSnapshot();
|
| }
|
|
|
| -void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
|
| - GLsizei width, GLsizei height, GLint border,
|
| - GLenum format, GLenum type, DOMArrayBufferView* pixels)
|
| +WebGLTexture* WebGLRenderingContextBase::validateTexImageBinding(const char* funcName, TexImageFunctionID functionID, GLenum target)
|
| +{
|
| + return validateTexture2DBinding(funcName, target);
|
| +}
|
| +
|
| +const char* WebGLRenderingContextBase::getTexImageFunctionName(TexImageFunctionID funcName)
|
| {
|
| + switch (funcName) {
|
| + case TexImage2D:
|
| + return "texImage2D";
|
| + case TexSubImage2D:
|
| + return "texSubImage2D";
|
| + case TexSubImage3D:
|
| + return "texSubImage3D";
|
| + case TexImage3D:
|
| + return "texImage3D";
|
| + default: // Adding default to prevent compile error
|
| + return "";
|
| + }
|
| +}
|
| +
|
| +void WebGLRenderingContextBase::texImageHelperDOMArrayBufferView(TexImageFunctionID functionID,
|
| + GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border,
|
| + GLenum format, GLenum type, GLsizei depth, GLint xoffset, GLint yoffset, GLint zoffset, DOMArrayBufferView* pixels)
|
| +{
|
| + const char* funcName = getTexImageFunctionName(functionID);
|
| if (isContextLost())
|
| return;
|
| - if (!validateTexture2DBinding("texImage2D", target))
|
| + if (!validateTexImageBinding(funcName, functionID, target))
|
| return;
|
| - if (!validateTexFunc("texImage2D", TexImage, SourceArrayBufferView, target, level, internalformat, width, height, 1, border, format, type, 0, 0, 0))
|
| + TexImageFunctionType functionType;
|
| + if (functionID == TexImage2D || functionID == TexImage3D)
|
| + functionType = TexImage;
|
| + else
|
| + functionType = TexSubImage;
|
| + if (!validateTexFunc(funcName, functionType, SourceArrayBufferView, target, level, internalformat, width, height, depth, border, format, type, xoffset, yoffset, zoffset))
|
| return;
|
| - if (!validateTexFuncData("texImage2D", Tex2D, level, width, height, 1, format, type, pixels, NullAllowed))
|
| + TexImageDimension sourceType;
|
| + if (functionID == TexImage2D || functionID == TexSubImage2D)
|
| + sourceType = Tex2D;
|
| + else
|
| + sourceType = Tex3D;
|
| + if (!validateTexFuncData(funcName, sourceType, level, width, height, depth, format, type, pixels, NullAllowed))
|
| return;
|
| void* data = pixels ? pixels->baseAddress() : 0;
|
| Vector<uint8_t> tempData;
|
| bool changeUnpackAlignment = false;
|
| if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
|
| - if (!WebGLImageConversion::extractTextureData(width, height, format, type, m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData))
|
| - return;
|
| - data = tempData.data();
|
| + if (sourceType == Tex2D) {
|
| + if (!WebGLImageConversion::extractTextureData(width, height, format, type, m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData))
|
| + return;
|
| + data = tempData.data();
|
| + }
|
| changeUnpackAlignment = true;
|
| }
|
| + // FIXME: implement flipY and premultiplyAlpha for tex(Sub)3D.
|
| + if (functionID == TexImage3D) {
|
| + contextGL()->TexImage3D(target, level, convertTexInternalFormat(internalformat, type), width, height, depth, border, format, type, data);
|
| + return;
|
| + }
|
| + if (functionID == TexSubImage3D) {
|
| + contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
|
| + return;
|
| + }
|
| +
|
| if (changeUnpackAlignment)
|
| resetUnpackParameters();
|
| - texImage2DBase(target, level, internalformat, width, height, border, format, type, data);
|
| + if (functionID == TexImage2D)
|
| + texImage2DBase(target, level, internalformat, width, height, border, format, type, data);
|
| + else if (functionID == TexSubImage2D)
|
| + contextGL()->TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, data);
|
| if (changeUnpackAlignment)
|
| restoreUnpackParameters();
|
| }
|
|
|
| void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
|
| - GLenum format, GLenum type, ImageData* pixels)
|
| + GLsizei width, GLsizei height, GLint border,
|
| + GLenum format, GLenum type, DOMArrayBufferView* pixels)
|
| {
|
| + texImageHelperDOMArrayBufferView(TexImage2D, target, level, internalformat, width, height, border, format, type, 1, 0, 0, 0, pixels);
|
| +}
|
| +
|
| +void WebGLRenderingContextBase::texImageHelperImageData(TexImageFunctionID functionID,
|
| + GLenum target, GLint level, GLint internalformat, GLint border, GLenum format,
|
| + GLenum type, GLsizei depth, GLint xoffset, GLint yoffset, GLint zoffset, ImageData* pixels)
|
| +{
|
| + const char* funcName = getTexImageFunctionName(functionID);
|
| if (isContextLost())
|
| return;
|
| if (!pixels) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "no image data");
|
| + synthesizeGLError(GL_INVALID_VALUE, funcName, "no image data");
|
| return;
|
| }
|
| if (pixels->data()->bufferBase()->isNeutered()) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "The source data has been neutered.");
|
| + synthesizeGLError(GL_INVALID_VALUE, funcName, "The source data has been neutered.");
|
| return;
|
| }
|
| - if (!validateTexture2DBinding("texImage2D", target))
|
| + if (!validateTexImageBinding(funcName, functionID, target))
|
| return;
|
| - if (!validateTexFunc("texImage2D", TexImage, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 1, 0, format, type, 0, 0, 0))
|
| + TexImageFunctionType functionType;
|
| + if (functionID == TexImage2D)
|
| + functionType = TexImage;
|
| + else
|
| + functionType = TexSubImage;
|
| + if (!validateTexFunc(funcName, functionType, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), depth, border, format, type, xoffset, yoffset, zoffset))
|
| return;
|
| Vector<uint8_t> data;
|
| bool needConversion = true;
|
| @@ -4130,37 +4199,59 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
|
| type = GL_FLOAT;
|
| }
|
| if (!WebGLImageConversion::extractImageData(pixels->data()->data(), WebGLImageConversion::DataFormat::DataFormatRGBA8, pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data");
|
| + synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data");
|
| return;
|
| }
|
| }
|
| resetUnpackParameters();
|
| - texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data());
|
| + if (functionID == TexImage2D) {
|
| + texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), border, format, type, needConversion ? data.data() : pixels->data()->data());
|
| + } else if (functionID == TexSubImage2D) {
|
| + contextGL()->TexSubImage2D(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data());
|
| + } else {
|
| + DCHECK_EQ(functionID, TexSubImage3D);
|
| + contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, pixels->width(), pixels->height(), depth, format, type, needConversion ? data.data() : pixels->data()->data());
|
| + }
|
| restoreUnpackParameters();
|
| }
|
|
|
| void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
|
| - GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState)
|
| + GLenum format, GLenum type, ImageData* pixels)
|
| +{
|
| + texImageHelperImageData(TexImage2D, target, level, internalformat, 0, format, type, 1, 0, 0, 0, pixels);
|
| +}
|
| +
|
| +void WebGLRenderingContextBase::texImageHelperHTMLImageElement(TexImageFunctionID functionID,
|
| + GLenum target, GLint level, GLint internalformat, GLenum format, GLenum type, GLint xoffset,
|
| + GLint yoffset, GLint zoffset, HTMLImageElement* image, ExceptionState& exceptionState)
|
| {
|
| + const char* funcName = getTexImageFunctionName(functionID);
|
| if (isContextLost())
|
| return;
|
| - if (!validateHTMLImageElement("texImage2D", image, exceptionState))
|
| + if (!validateHTMLImageElement(funcName, image, exceptionState))
|
| return;
|
| - if (!validateTexture2DBinding("texImage2D", target))
|
| + if (!validateTexImageBinding(funcName, functionID, target))
|
| return;
|
|
|
| RefPtr<Image> imageForRender = image->cachedImage()->getImage();
|
| if (imageForRender && imageForRender->isSVGImage())
|
| - imageForRender = drawImageIntoBuffer(imageForRender.release(), image->width(), image->height(), "texImage2D");
|
| + imageForRender = drawImageIntoBuffer(imageForRender.release(), image->width(), image->height(), funcName);
|
|
|
| - if (!imageForRender || !validateTexFunc("texImage2D", TexImage, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 1, 0, format, type, 0, 0, 0))
|
| + TexImageFunctionType functionType;
|
| + if (functionID == TexImage2D)
|
| + functionType = TexImage;
|
| + else
|
| + functionType = TexSubImage;
|
| + if (!imageForRender || !validateTexFunc(funcName, functionType, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 1, 0, format, type, xoffset, yoffset, zoffset))
|
| return;
|
|
|
| - if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
|
| - // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented.
|
| - type = GL_FLOAT;
|
| - }
|
| - texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| + texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, zoffset, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| +}
|
| +
|
| +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
|
| + GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState)
|
| +{
|
| + texImageHelperHTMLImageElement(TexImage2D, target, level, internalformat, format, type, 0, 0, 0, image, exceptionState);
|
| }
|
|
|
| bool WebGLRenderingContextBase::canUseTexImageCanvasByGPU(GLint internalformat, GLenum type)
|
| @@ -4234,30 +4325,65 @@ void WebGLRenderingContextBase::texImageCanvasByGPU(TexImageByGPUType functionTy
|
| }
|
| }
|
|
|
| -void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
|
| - GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState)
|
| +void WebGLRenderingContextBase::texImageHelperHTMLCanvasElement(TexImageFunctionID functionID,
|
| + GLenum target, GLint level, GLint internalformat, GLenum format, GLenum type, GLint xoffset,
|
| + GLint yoffset, GLint zoffset, HTMLCanvasElement* canvas, ExceptionState& exceptionState)
|
| {
|
| + const char* funcName = getTexImageFunctionName(functionID);
|
| if (isContextLost())
|
| return;
|
| - if (!validateHTMLCanvasElement("texImage2D", canvas, exceptionState))
|
| + if (!validateHTMLCanvasElement(funcName, canvas, exceptionState))
|
| return;
|
| - WebGLTexture* texture = validateTexture2DBinding("texImage2D", target);
|
| + WebGLTexture* texture = validateTexImageBinding(funcName, functionID, target);
|
| if (!texture)
|
| return;
|
| - if (!validateTexFunc("texImage2D", TexImage, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 1, 0, format, type, 0, 0, 0))
|
| - return;
|
| + TexImageFunctionType functionType;
|
| + if (functionID == TexImage2D)
|
| + functionType = TexImage;
|
| + else
|
| + functionType = TexSubImage;
|
| + if (!validateTexFunc(funcName, functionType, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 1, 0, format, type, xoffset, yoffset, zoffset))
|
| + return;
|
| + if (functionID == TexImage2D) {
|
| + // texImageCanvasByGPU relies on copyTextureCHROMIUM which doesn't support float/integer/sRGB internal format.
|
| + // FIXME: relax the constrains if copyTextureCHROMIUM is upgraded to handle more formats.
|
| + if (!canvas->renderingContext() || !canvas->renderingContext()->isAccelerated() || !canUseTexImageCanvasByGPU(internalformat, type)) {
|
| + // 2D canvas has only FrontBuffer.
|
| + texImageImpl(TexImage2D, target, level, internalformat, xoffset, yoffset, zoffset, format, type, canvas->copiedImage(FrontBuffer, PreferAcceleration).get(),
|
| + WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| + return;
|
| + }
|
|
|
| - // texImageCanvasByGPU relies on copyTextureCHROMIUM which doesn't support float/integer/sRGB internal format.
|
| - // FIXME: relax the constrains if copyTextureCHROMIUM is upgraded to handle more formats.
|
| - if (!canvas->renderingContext() || !canvas->renderingContext()->isAccelerated() || !canUseTexImageCanvasByGPU(internalformat, type)) {
|
| - // 2D canvas has only FrontBuffer.
|
| - texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(FrontBuffer, PreferAcceleration).get(),
|
| + texImage2DBase(target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0);
|
| + texImageCanvasByGPU(TexImage2DByGPU, texture, target, level, internalformat, type, 0, 0, 0, canvas);
|
| + } else if (functionID == TexSubImage2D) {
|
| + // FIXME: Implement GPU-to-GPU path for WebGL 2 and more internal formats.
|
| + bool useReadBackPath = isWebGL2OrHigher()
|
| + || extensionEnabled(OESTextureFloatName)
|
| + || extensionEnabled(OESTextureHalfFloatName)
|
| + || extensionEnabled(EXTsRGBName);
|
| + // texImageCanvasByGPU relies on copyTextureCHROMIUM which doesn't support float/integer/sRGB internal format.
|
| + // FIXME: relax the constrains if copyTextureCHROMIUM is upgraded to handle more formats.
|
| + if (!canvas->renderingContext() || !canvas->renderingContext()->isAccelerated() || useReadBackPath) {
|
| + // 2D canvas has only FrontBuffer.
|
| + texImageImpl(TexSubImage2D, target, level, 0, xoffset, yoffset, 0, format, type, canvas->copiedImage(FrontBuffer, PreferAcceleration).get(),
|
| + WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| + return;
|
| + }
|
| +
|
| + texImageCanvasByGPU(TexSubImage2DByGPU, texture, target, level, GL_RGBA, type, xoffset, yoffset, 0, canvas);
|
| + } else {
|
| + DCHECK_EQ(functionID, TexSubImage3D);
|
| + // FIXME: Implement GPU-to-GPU copy path (crbug.com/586269).
|
| + texImageImpl(TexSubImage3D, target, level, 0, xoffset, yoffset, zoffset, format, type, canvas->copiedImage(FrontBuffer, PreferAcceleration).get(),
|
| WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| - return;
|
| }
|
| +}
|
|
|
| - texImage2DBase(target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0);
|
| - texImageCanvasByGPU(TexImage2DByGPU, texture, target, level, internalformat, type, 0, 0, 0, canvas);
|
| +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
|
| + GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState)
|
| +{
|
| + texImageHelperHTMLCanvasElement(TexImage2D, target, level, internalformat, format, type, 0, 0, 0, canvas, exceptionState);
|
| }
|
|
|
| PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video)
|
| @@ -4273,63 +4399,84 @@ PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement*
|
| return buf->newImageSnapshot();
|
| }
|
|
|
| -void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
|
| - GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState)
|
| +void WebGLRenderingContextBase::texImageHelperHTMLVideoElement(TexImageFunctionID functionID,
|
| + GLenum target, GLint level, GLint internalformat, GLenum format, GLenum type, GLint xoffset,
|
| + GLint yoffset, GLint zoffset, HTMLVideoElement* video, ExceptionState& exceptionState)
|
| {
|
| + const char* funcName = getTexImageFunctionName(functionID);
|
| if (isContextLost())
|
| return;
|
| - if (!validateHTMLVideoElement("texImage2D", video, exceptionState))
|
| + if (!validateHTMLVideoElement(funcName, video, exceptionState))
|
| return;
|
| - WebGLTexture* texture = validateTexture2DBinding("texImage2D", target);
|
| + WebGLTexture* texture = validateTexImageBinding(funcName, functionID, target);
|
| if (!texture)
|
| return;
|
| - if (!validateTexFunc("texImage2D", TexImage, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 1, 0, format, type, 0, 0, 0))
|
| + TexImageFunctionType functionType;
|
| + if (functionID == TexImage2D)
|
| + functionType = TexImage;
|
| + else
|
| + functionType = TexSubImage;
|
| + if (!validateTexFunc(funcName, functionType, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 1, 0, format, type, xoffset, yoffset, zoffset))
|
| return;
|
|
|
| - // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible.
|
| - // Otherwise, it will fall back to the normal SW path.
|
| - if (GL_TEXTURE_2D == target) {
|
| - if (Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, type, level)
|
| - && video->copyVideoTextureToPlatformTexture(contextGL(), texture->object(), internalformat, type, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
|
| - return;
|
| - }
|
| + if (functionID == TexImage2D) {
|
| + // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible.
|
| + // Otherwise, it will fall back to the normal SW path.
|
| + if (GL_TEXTURE_2D == target) {
|
| + if (Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, type, level)
|
| + && video->copyVideoTextureToPlatformTexture(contextGL(), texture->object(), internalformat, type, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
|
| + return;
|
| + }
|
|
|
| - // Try using an accelerated image buffer, this allows YUV conversion to be done on the GPU.
|
| - OwnPtr<ImageBufferSurface> surface = adoptPtr(new AcceleratedImageBufferSurface(IntSize(video->videoWidth(), video->videoHeight())));
|
| - if (surface->isValid()) {
|
| - OwnPtr<ImageBuffer> imageBuffer(ImageBuffer::create(std::move(surface)));
|
| - if (imageBuffer) {
|
| - // The video element paints an RGBA frame into our surface here. By using an AcceleratedImageBufferSurface,
|
| - // we enable the WebMediaPlayer implementation to do any necessary color space conversion on the GPU (though it
|
| - // may still do a CPU conversion and upload the results).
|
| - video->paintCurrentFrame(imageBuffer->canvas(), IntRect(0, 0, video->videoWidth(), video->videoHeight()), nullptr);
|
| -
|
| - // This is a straight GPU-GPU copy, any necessary color space conversion was handled in the paintCurrentFrameInContext() call.
|
| - if (imageBuffer->copyToPlatformTexture(contextGL(), texture->object(), internalformat, type,
|
| - level, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
|
| - return;
|
| + // Try using an accelerated image buffer, this allows YUV conversion to be done on the GPU.
|
| + OwnPtr<ImageBufferSurface> surface = adoptPtr(new AcceleratedImageBufferSurface(IntSize(video->videoWidth(), video->videoHeight())));
|
| + if (surface->isValid()) {
|
| + OwnPtr<ImageBuffer> imageBuffer(ImageBuffer::create(std::move(surface)));
|
| + if (imageBuffer) {
|
| + // The video element paints an RGBA frame into our surface here. By using an AcceleratedImageBufferSurface,
|
| + // we enable the WebMediaPlayer implementation to do any necessary color space conversion on the GPU (though it
|
| + // may still do a CPU conversion and upload the results).
|
| + video->paintCurrentFrame(imageBuffer->canvas(), IntRect(0, 0, video->videoWidth(), video->videoHeight()), nullptr);
|
| +
|
| + // This is a straight GPU-GPU copy, any necessary color space conversion was handled in the paintCurrentFrameInContext() call.
|
| + if (imageBuffer->copyToPlatformTexture(contextGL(), texture->object(), internalformat, type,
|
| + level, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
|
| + return;
|
| + }
|
| }
|
| }
|
| }
|
| }
|
|
|
| - // Normal pure SW path.
|
| RefPtr<Image> image = videoFrameToImage(video);
|
| if (!image)
|
| return;
|
| - texImage2DImpl(target, level, internalformat, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| + texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, zoffset, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| }
|
|
|
| void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
|
| - GLenum format, GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState)
|
| + GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState)
|
| +{
|
| + texImageHelperHTMLVideoElement(TexImage2D, target, level, internalformat, format, type, 0, 0, 0, video, exceptionState);
|
| +}
|
| +
|
| +void WebGLRenderingContextBase::texImageHelperImageBitmap(TexImageFunctionID functionID,
|
| + GLenum target, GLint level, GLint internalformat, GLenum format, GLenum type, GLint xoffset,
|
| + GLint yoffset, GLint zoffset, ImageBitmap* bitmap, ExceptionState& exceptionState)
|
| {
|
| + const char* funcName = getTexImageFunctionName(functionID);
|
| if (isContextLost())
|
| return;
|
| - if (!validateImageBitmap("texImage2D", bitmap, exceptionState))
|
| + if (!validateImageBitmap(funcName, bitmap, exceptionState))
|
| return;
|
| - if (!validateTexture2DBinding("texImage2D", target))
|
| + if (!validateTexImageBinding(funcName, functionID, target))
|
| return;
|
| - if (!validateTexFunc("texImage2D", TexImage, SourceImageBitmap, target, level, internalformat, bitmap->width(), bitmap->height(), 1, 0, format, type, 0, 0, 0))
|
| + TexImageFunctionType functionType;
|
| + if (functionID == TexImage2D)
|
| + functionType = TexImage;
|
| + else
|
| + functionType = TexSubImage;
|
| + if (!validateTexFunc(funcName, functionType, SourceImageBitmap, target, level, internalformat, bitmap->width(), bitmap->height(), 1, 0, format, type, xoffset, yoffset, zoffset))
|
| return;
|
| ASSERT(bitmap->bitmapImage());
|
| RefPtr<SkImage> skImage = bitmap->bitmapImage()->imageForCurrentFrame();
|
| @@ -4360,15 +4507,28 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
|
| bool isPixelDataBGRA = (peekSucceed && pixmap.colorType() == SkColorType::kBGRA_8888_SkColorType);
|
| if ((isPixelDataBGRA && !WebGLImageConversion::extractImageData(pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatBGRA8, bitmap->size(), format, type, false, false, data))
|
| || (isPixelDataRBGA && !WebGLImageConversion::extractImageData(pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatRGBA8, bitmap->size(), format, type, false, false, data))) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data");
|
| + synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data");
|
| return;
|
| }
|
| }
|
| resetUnpackParameters();
|
| - texImage2DBase(target, level, internalformat, bitmap->width(), bitmap->height(), 0, format, type, needConversion ? data.data() : pixelDataPtr);
|
| + if (functionID == TexImage2D) {
|
| + texImage2DBase(target, level, internalformat, bitmap->width(), bitmap->height(), 0, format, type, needConversion ? data.data() : pixelDataPtr);
|
| + } else if (functionID == TexSubImage2D) {
|
| + contextGL()->TexSubImage2D(target, level, xoffset, yoffset, bitmap->width(), bitmap->height(), format, type, needConversion ? data.data() : pixelDataPtr);
|
| + } else {
|
| + DCHECK_EQ(functionID, TexSubImage3D);
|
| + contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, bitmap->width(), bitmap->height(), 1, format, type, needConversion ? data.data() : pixelDataPtr);
|
| + }
|
| restoreUnpackParameters();
|
| }
|
|
|
| +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
|
| + GLenum format, GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState)
|
| +{
|
| + texImageHelperImageBitmap(TexImage2D, target, level, internalformat, format, type, 0, 0, 0, bitmap, exceptionState);
|
| +}
|
| +
|
| void WebGLRenderingContextBase::texParameter(GLenum target, GLenum pname, GLfloat paramf, GLint parami, bool isFloat)
|
| {
|
| if (isContextLost())
|
| @@ -4431,222 +4591,41 @@ void WebGLRenderingContextBase::texParameteri(GLenum target, GLenum pname, GLint
|
| texParameter(target, pname, 0, param, false);
|
| }
|
|
|
| -void WebGLRenderingContextBase::texSubImage2DImpl(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
|
| -{
|
| - // All calling functions check isContextLost, so a duplicate check is not needed here.
|
| - if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
|
| - // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented.
|
| - type = GL_FLOAT;
|
| - }
|
| - Vector<uint8_t> data;
|
| - WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE);
|
| - if (!imageExtractor.imagePixelData()) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image");
|
| - return;
|
| - }
|
| - WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
|
| - WebGLImageConversion::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
|
| - const void* imagePixelData = imageExtractor.imagePixelData();
|
| -
|
| - bool needConversion = true;
|
| - if (type == GL_UNSIGNED_BYTE && sourceDataFormat == WebGLImageConversion::DataFormatRGBA8 && format == GL_RGBA && alphaOp == WebGLImageConversion::AlphaDoNothing && !flipY) {
|
| - needConversion = false;
|
| - } else {
|
| - if (!WebGLImageConversion::packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data");
|
| - return;
|
| - }
|
| - }
|
| -
|
| - resetUnpackParameters();
|
| - contextGL()->TexSubImage2D(target, level, xoffset, yoffset, imageExtractor.imageWidth(), imageExtractor.imageHeight(), format, type, needConversion ? data.data() : imagePixelData);
|
| - restoreUnpackParameters();
|
| -}
|
| -
|
| void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
| GLsizei width, GLsizei height,
|
| GLenum format, GLenum type, DOMArrayBufferView* pixels)
|
| {
|
| - if (isContextLost())
|
| - return;
|
| - if (!validateTexture2DBinding("texSubImage2D", target))
|
| - return;
|
| - if (!validateTexFunc("texSubImage2D", TexSubImage, SourceArrayBufferView, target, level, 0, width, height, 1, 0, format, type, xoffset, yoffset, 0))
|
| - return;
|
| - if (!validateTexFuncData("texSubImage2D", Tex2D, level, width, height, 1, format, type, pixels, NullNotAllowed))
|
| - return;
|
| - void* data = pixels->baseAddress();
|
| - Vector<uint8_t> tempData;
|
| - bool changeUnpackAlignment = false;
|
| - if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
|
| - if (!WebGLImageConversion::extractTextureData(width, height, format, type,
|
| - m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData))
|
| - return;
|
| - data = tempData.data();
|
| - changeUnpackAlignment = true;
|
| - }
|
| - if (changeUnpackAlignment)
|
| - resetUnpackParameters();
|
| - contextGL()->TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, data);
|
| - if (changeUnpackAlignment)
|
| - restoreUnpackParameters();
|
| + texImageHelperDOMArrayBufferView(TexSubImage2D, target, level, 0, width, height, 0, format, type, 1, xoffset, yoffset, 0, pixels);
|
| }
|
|
|
| void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
| GLenum format, GLenum type, ImageData* pixels)
|
| {
|
| - if (isContextLost())
|
| - return;
|
| - if (!pixels) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "no image data");
|
| - return;
|
| - }
|
| - if (pixels->data()->bufferBase()->isNeutered()) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "The source data has been neutered.");
|
| - return;
|
| - }
|
| - if (!validateTexture2DBinding("texSubImage2D", target))
|
| - return;
|
| - if (!validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, 0, pixels->width(), pixels->height(), 1, 0, format, type, xoffset, yoffset, 0))
|
| - return;
|
| - if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
|
| - // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented.
|
| - type = GL_FLOAT;
|
| - }
|
| - Vector<uint8_t> data;
|
| - bool needConversion = true;
|
| - // The data from ImageData is always of format RGBA8.
|
| - // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
|
| - if (format == GL_RGBA && type == GL_UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha) {
|
| - needConversion = false;
|
| - } else {
|
| - if (!WebGLImageConversion::extractImageData(pixels->data()->data(), WebGLImageConversion::DataFormat::DataFormatRGBA8, pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data");
|
| - return;
|
| - }
|
| - }
|
| - resetUnpackParameters();
|
| - contextGL()->TexSubImage2D(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data());
|
| - restoreUnpackParameters();
|
| + texImageHelperImageData(TexSubImage2D, target, level, 0, 0, format, type, 1, xoffset, yoffset, 0, pixels);
|
| }
|
|
|
| void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
| GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState)
|
| {
|
| - if (isContextLost())
|
| - return;
|
| - if (!validateHTMLImageElement("texSubImage2D", image, exceptionState))
|
| - return;
|
| - if (!validateTexture2DBinding("texSubImage2D", target))
|
| - return;
|
| -
|
| - RefPtr<Image> imageForRender = image->cachedImage()->getImage();
|
| - if (imageForRender && imageForRender->isSVGImage())
|
| - imageForRender = drawImageIntoBuffer(imageForRender.release(), image->width(), image->height(), "texSubImage2D");
|
| -
|
| - if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLImageElement, target, level, 0, imageForRender->width(), imageForRender->height(), 1, 0, format, type, xoffset, yoffset, 0))
|
| - return;
|
| -
|
| - if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
|
| - // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented.
|
| - type = GL_FLOAT;
|
| - }
|
| - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| + texImageHelperHTMLImageElement(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, image, exceptionState);
|
| }
|
|
|
| void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
| GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState)
|
| {
|
| - if (isContextLost())
|
| - return;
|
| - if (!validateHTMLCanvasElement("texSubImage2D", canvas, exceptionState))
|
| - return;
|
| - WebGLTexture* texture = validateTexture2DBinding("texSubImage2D", target);
|
| - if (!texture)
|
| - return;
|
| - if (!validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLCanvasElement, target, level, 0, canvas->width(), canvas->height(), 1, 0, format, type, xoffset, yoffset, 0))
|
| - return;
|
| -
|
| - // FIXME: Implement GPU-to-GPU path for WebGL 2 and more internal formats.
|
| - bool useReadBackPath = isWebGL2OrHigher()
|
| - || extensionEnabled(OESTextureFloatName)
|
| - || extensionEnabled(OESTextureHalfFloatName)
|
| - || extensionEnabled(EXTsRGBName);
|
| - // texImageCanvasByGPU relies on copyTextureCHROMIUM which doesn't support float/integer/sRGB internal format.
|
| - // FIXME: relax the constrains if copyTextureCHROMIUM is upgraded to handle more formats.
|
| - if (!canvas->renderingContext() || !canvas->renderingContext()->isAccelerated() || useReadBackPath) {
|
| - // 2D canvas has only FrontBuffer.
|
| - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(FrontBuffer, PreferAcceleration).get(),
|
| - WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| - return;
|
| - }
|
| -
|
| - texImageCanvasByGPU(TexSubImage2DByGPU, texture, target, level, GL_RGBA, type, xoffset, yoffset, 0, canvas);
|
| + texImageHelperHTMLCanvasElement(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, canvas, exceptionState);
|
| }
|
|
|
| void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
| GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState)
|
| {
|
| - if (isContextLost())
|
| - return;
|
| - if (!validateHTMLVideoElement("texSubImage2D", video, exceptionState))
|
| - return;
|
| - if (!validateTexture2DBinding("texSubImage2D", target))
|
| - return;
|
| - if (!validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, 0, video->videoWidth(), video->videoHeight(), 1, 0, format, type, xoffset, yoffset, 0))
|
| - return;
|
| -
|
| - RefPtr<Image> image = videoFrameToImage(video);
|
| - if (!image)
|
| - return;
|
| - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
|
| + texImageHelperHTMLVideoElement(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, video, exceptionState);
|
| }
|
|
|
| void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
| GLenum format, GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState)
|
| {
|
| - if (isContextLost())
|
| - return;
|
| - if (!validateImageBitmap("texSubImage2D", bitmap, exceptionState))
|
| - return;
|
| - if (!validateTexture2DBinding("texSubImage2D", target))
|
| - return;
|
| - if (!validateTexFunc("texSubImage2D", TexSubImage, SourceImageBitmap, target, level, 0, bitmap->width(), bitmap->height(), 1, 0, format, type, 0, 0, 0))
|
| - return;
|
| - if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
|
| - // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented.
|
| - type = GL_FLOAT;
|
| - }
|
| - ASSERT(bitmap->bitmapImage());
|
| - RefPtr<SkImage> skImage = bitmap->bitmapImage()->imageForCurrentFrame();
|
| - SkPixmap pixmap;
|
| - OwnPtr<uint8_t[]> pixelData;
|
| - uint8_t* pixelDataPtr = nullptr;
|
| - bool peekSucceed = skImage->peekPixels(&pixmap);
|
| - if (peekSucceed) {
|
| - pixelDataPtr = static_cast<uint8_t*>(pixmap.writable_addr());
|
| - } else if (skImage->isTextureBacked()) {
|
| - pixelData = bitmap->copyBitmapData(bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha);
|
| - pixelDataPtr = pixelData.get();
|
| - }
|
| - Vector<uint8_t> data;
|
| - bool needConversion = true;
|
| - bool havePeekableRGBA = (peekSucceed && pixmap.colorType() == SkColorType::kRGBA_8888_SkColorType);
|
| - bool isPixelDataRBGA = (havePeekableRGBA || !peekSucceed);
|
| - if (isPixelDataRBGA && format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
|
| - needConversion = false;
|
| - } else {
|
| - // In the case of ImageBitmap, we do not need to apply flipY or premultiplyAlpha.
|
| - bool isPixelDataBGRA = (peekSucceed && pixmap.colorType() == SkColorType::kBGRA_8888_SkColorType);
|
| - if ((isPixelDataBGRA && !WebGLImageConversion::extractImageData(pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatBGRA8, bitmap->size(), format, type, false, false, data))
|
| - || (isPixelDataRBGA && !WebGLImageConversion::extractImageData(pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatRGBA8, bitmap->size(), format, type, false, false, data))) {
|
| - synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data");
|
| - return;
|
| - }
|
| - }
|
| - resetUnpackParameters();
|
| - contextGL()->TexSubImage2D(target, level, xoffset, yoffset, bitmap->width(), bitmap->height(), format, type, needConversion ? data.data() : pixelDataPtr);
|
| - restoreUnpackParameters();
|
| + texImageHelperImageBitmap(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, bitmap, exceptionState);
|
| }
|
|
|
| void WebGLRenderingContextBase::uniform1f(const WebGLUniformLocation* location, GLfloat x)
|
|
|