Commit 11401539 authored by xidachen's avatar xidachen Committed by Commit bot

Pack repeated code in tex(Sub)Image2D and texSubImage3D into helper func

There are some repeated code in these functions and the only diff amongest
them is whether it gives "texImage2D" or "texSubImage2D" or "texSubImage3D".

This CL packs the repeated part into helper function. After this, when
we make changes to these functions in the future, we would only need to
change one place instead of 3 places. Also, this will reduce potential
bugs in the code. For example, at this moment, line 4131 in
WebGLRenderingContextBase.cpp (texImage2D) does this:
if (imageForRender && imageForRender->isSVGImage())

while line 1095 in WebGL2RenderingContextBase.cpp (texSubImage3D) does:
if (imageForRender->isSVGImage())
which doesn't do a null check on imageForRender.

This change can certainly prevent bugs like this.

For this change, we just need to make sure that all bots are green.

CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win_optional_gpu_tests_rel;tryserver.chromium.mac:mac_optional_gpu_tests_rel

Review-Url: https://codereview.chromium.org/2025703002
Cr-Commit-Position: refs/heads/master@{#398286}
parent 22155739
...@@ -945,24 +945,7 @@ void WebGL2RenderingContextBase::texStorage3D(GLenum target, GLsizei levels, GLe ...@@ -945,24 +945,7 @@ void WebGL2RenderingContextBase::texStorage3D(GLenum target, GLsizei levels, GLe
void WebGL2RenderingContextBase::texImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, DOMArrayBufferView* pixels) void WebGL2RenderingContextBase::texImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, DOMArrayBufferView* pixels)
{ {
if (isContextLost()) texImageHelperDOMArrayBufferView(TexImage3D, target, level, internalformat, width, height, border, format, type, depth, 0, 0, 0, pixels);
return;
if (!validateTexture3DBinding("texImage3D", target))
return;
if (!validateTexFunc("texImage3D", TexImage, SourceArrayBufferView, target, level, internalformat, width, height, depth, border, format, type, 0, 0, 0))
return;
if (!validateTexFuncData("texImage3D", Tex3D, level, width, height, depth, format, type, pixels, NullAllowed))
return;
void* data = pixels ? pixels->baseAddress() : 0;
Vector<uint8_t> tempData;
if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
// FIXME: WebGLImageConversion needs to be updated to accept image depth.
NOTIMPLEMENTED();
return;
}
contextGL()->TexImage3D(target, level, convertTexInternalFormat(internalformat, type), width, height, depth, border, format, type, data);
} }
void WebGL2RenderingContextBase::texImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLintptr offset) void WebGL2RenderingContextBase::texImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLintptr offset)
...@@ -983,62 +966,9 @@ void WebGL2RenderingContextBase::texImage3D(GLenum target, GLint level, GLint in ...@@ -983,62 +966,9 @@ void WebGL2RenderingContextBase::texImage3D(GLenum target, GLint level, GLint in
contextGL()->TexImage3D(target, level, convertTexInternalFormat(internalformat, type), width, height, depth, border, format, type, reinterpret_cast<const void *>(offset)); contextGL()->TexImage3D(target, level, convertTexInternalFormat(internalformat, type), width, height, depth, border, format, type, reinterpret_cast<const void *>(offset));
} }
void WebGL2RenderingContextBase::texSubImage3DImpl(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, 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, "texSubImage3D", "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, "texSubImage3D", "bad image data");
return;
}
}
resetUnpackParameters();
contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 1, format, type, needConversion ? data.data() : imagePixelData);
restoreUnpackParameters();
}
void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, DOMArrayBufferView* pixels) void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, DOMArrayBufferView* pixels)
{ {
if (isContextLost()) texImageHelperDOMArrayBufferView(TexSubImage3D, target, level, 0, width, height, 0, format, type, depth, xoffset, yoffset, zoffset, pixels);
return;
if (!validateTexture3DBinding("texSubImage3D", target))
return;
if (!validateTexFunc("texSubImage3D", TexSubImage, SourceArrayBufferView, target, level, 0, width, height, depth, 0, format, type, xoffset, yoffset, zoffset))
return;
if (!validateTexFuncData("texSubImage3D", Tex3D, level, width, height, depth, format, type, pixels, NullNotAllowed))
return;
void* data = pixels->baseAddress();
Vector<uint8_t> tempData;
bool changeUnpackParameters = false;
if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
// FIXME: WebGLImageConversion needs to be updated to accept image depth.
NOTIMPLEMENTED();
changeUnpackParameters = true;
}
if (changeUnpackParameters)
resetUnpackParameters();
contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
if (changeUnpackParameters)
restoreUnpackParameters();
} }
void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLintptr offset) void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLintptr offset)
...@@ -1061,138 +991,27 @@ void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint ...@@ -1061,138 +991,27 @@ void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint
void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, ImageData* pixels) void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, ImageData* pixels)
{ {
if (isContextLost()) texImageHelperImageData(TexSubImage3D, target, level, 0, 0, format, type, 1, xoffset, yoffset, zoffset, pixels);
return;
if (!pixels) {
synthesizeGLError(GL_INVALID_VALUE, "texSubImage3D", "no image data");
return;
}
if (pixels->data()->bufferBase()->isNeutered()) {
synthesizeGLError(GL_INVALID_VALUE, "texSubImage3D", "The source data has been neutered.");
return;
}
if (!validateTexture3DBinding("texSubImage3D", target))
return;
if (!validateTexFunc("texSubImage3D", TexSubImage, SourceImageData, target, level, 0, pixels->width(), pixels->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;
}
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, "texSubImage3D", "bad image data");
return;
}
}
resetUnpackParameters();
contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, pixels->width(), pixels->height(), 1, format, type, needConversion ? data.data() : pixels->data()->data());
restoreUnpackParameters();
} }
void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState)
{ {
if (isContextLost()) texImageHelperHTMLImageElement(TexSubImage3D, target, level, 0, format, type, xoffset, yoffset, zoffset, image, exceptionState);
return;
if (!validateHTMLImageElement("texSubImage3D", image, exceptionState))
return;
if (!validateTexture3DBinding("texSubImage3D", target))
return;
RefPtr<Image> imageForRender = image->cachedImage()->getImage();
if (imageForRender->isSVGImage())
imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), "texSubImage3D");
if (!imageForRender || !validateTexFunc("texSubImage3D", TexSubImage, SourceHTMLImageElement, target, level, 0, imageForRender->width(), imageForRender->height(), 1, 0, format, type, xoffset, yoffset, zoffset))
return;
texSubImage3DImpl(target, level, xoffset, yoffset, zoffset, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
} }
void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState)
{ {
if (isContextLost()) texImageHelperHTMLCanvasElement(TexSubImage3D, target, level, 0, format, type, xoffset, yoffset, zoffset, canvas, exceptionState);
return;
if (!validateHTMLCanvasElement("texSubImage3D", canvas, exceptionState))
return;
if (!validateTexture3DBinding("texSubImage3D", target))
return;
if (!validateTexFunc("texSubImage3D", TexSubImage, SourceHTMLCanvasElement, target, level, 0, canvas->width(), canvas->height(), 1, 0, format, type, xoffset, yoffset, zoffset))
return;
// FIXME: Implement GPU-to-GPU copy path (crbug.com/586269).
texSubImage3DImpl(target, level, xoffset, yoffset, zoffset, format, type, canvas->copiedImage(FrontBuffer, PreferAcceleration).get(),
WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
} }
void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState)
{ {
if (isContextLost()) texImageHelperHTMLVideoElement(TexSubImage3D, target, level, 0, format, type, xoffset, yoffset, zoffset, video, exceptionState);
return;
if (!validateHTMLVideoElement("texSubImage3D", video, exceptionState))
return;
if (!validateTexture3DBinding("texSubImage3D", target))
return;
if (!validateTexFunc("texSubImage3D", TexSubImage, SourceHTMLVideoElement, target, level, 0, video->videoWidth(), video->videoHeight(), 1, 0, format, type, xoffset, yoffset, zoffset))
return;
RefPtr<Image> image = videoFrameToImage(video);
if (!image)
return;
texSubImage3DImpl(target, level, xoffset, yoffset, zoffset, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
} }
void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState) void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState)
{ {
if (isContextLost()) texImageHelperImageBitmap(TexSubImage3D, target, level, 0, format, type, xoffset, yoffset, zoffset, bitmap, exceptionState);
return;
if (!validateImageBitmap("texSubImage3D", bitmap, exceptionState))
return;
if (!validateTexture3DBinding("texSubImage3D", target))
return;
if (!validateTexFunc("texSubImage3D", TexSubImage, SourceImageBitmap, target, level, 0, bitmap->width(), bitmap->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;
}
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, "texSubImage3D", "bad image data");
return;
}
}
resetUnpackParameters();
contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, bitmap->width(), bitmap->height(), 1, format, type, needConversion ? data.data() : pixelDataPtr);
restoreUnpackParameters();
} }
void WebGL2RenderingContextBase::copyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) void WebGL2RenderingContextBase::copyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
...@@ -1668,6 +1487,13 @@ bool WebGL2RenderingContextBase::validateClearBuffer(const char* functionName, G ...@@ -1668,6 +1487,13 @@ bool WebGL2RenderingContextBase::validateClearBuffer(const char* functionName, G
return true; return true;
} }
WebGLTexture* WebGL2RenderingContextBase::validateTexImageBinding(const char* funcName, TexImageFunctionID functionID, GLenum target)
{
if (functionID == TexImage3D || functionID == TexSubImage3D)
return validateTexture3DBinding(funcName, target);
return validateTexture2DBinding(funcName, target);
}
void WebGL2RenderingContextBase::clearBufferiv(GLenum buffer, GLint drawbuffer, DOMInt32Array* value) void WebGL2RenderingContextBase::clearBufferiv(GLenum buffer, GLint drawbuffer, DOMInt32Array* value)
{ {
if (isContextLost() || !validateClearBuffer("clearBufferiv", buffer, value->length())) if (isContextLost() || !validateClearBuffer("clearBufferiv", buffer, value->length()))
......
...@@ -235,7 +235,6 @@ protected: ...@@ -235,7 +235,6 @@ protected:
ScriptValue getInt64Parameter(ScriptState*, GLenum); ScriptValue getInt64Parameter(ScriptState*, GLenum);
void texSubImage3DImpl(GLenum, GLint, GLint, GLint, GLint, GLenum, GLenum, Image*, WebGLImageConversion::ImageHtmlDomSource, bool, bool);
void samplerParameter(WebGLSampler*, GLenum, GLfloat, GLint, bool); void samplerParameter(WebGLSampler*, GLenum, GLfloat, GLint, bool);
bool isBufferBoundToTransformFeedback(WebGLBuffer*); bool isBufferBoundToTransformFeedback(WebGLBuffer*);
...@@ -263,6 +262,7 @@ protected: ...@@ -263,6 +262,7 @@ protected:
GLint getMaxTextureLevelForTarget(GLenum target) override; GLint getMaxTextureLevelForTarget(GLenum target) override;
void renderbufferStorageImpl(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, const char* functionName) override; void renderbufferStorageImpl(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, const char* functionName) override;
WebGLTexture* validateTexImageBinding(const char*, TexImageFunctionID, GLenum) override;
// Helper function to check texture 3D target and texture bound to the target. // Helper function to check texture 3D target and texture bound to the target.
// Generate GL errors and return 0 if target is invalid or texture bound is // Generate GL errors and return 0 if target is invalid or texture bound is
// null. Otherwise, return the texture bound to the target. // null. Otherwise, return the texture bound to the target.
......
...@@ -3976,8 +3976,9 @@ void WebGLRenderingContextBase::texImage2DBase(GLenum target, GLint level, GLint ...@@ -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); 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. // All calling functions check isContextLost, so a duplicate check is not needed here.
if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) { if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
// The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented. // 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 ...@@ -3986,7 +3987,7 @@ void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLint
Vector<uint8_t> data; Vector<uint8_t> data;
WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE); WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE);
if (!imageExtractor.imagePixelData()) { if (!imageExtractor.imagePixelData()) {
synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data"); synthesizeGLError(GL_INVALID_VALUE, funcName, "bad image data");
return; return;
} }
WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
...@@ -3998,13 +3999,20 @@ void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLint ...@@ -3998,13 +3999,20 @@ void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLint
needConversion = false; needConversion = false;
} else { } else {
if (!WebGLImageConversion::packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { 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; return;
} }
} }
resetUnpackParameters(); 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(); restoreUnpackParameters();
} }
...@@ -4073,50 +4081,111 @@ PassRefPtr<Image> WebGLRenderingContextBase::drawImageIntoBuffer(PassRefPtr<Imag ...@@ -4073,50 +4081,111 @@ PassRefPtr<Image> WebGLRenderingContextBase::drawImageIntoBuffer(PassRefPtr<Imag
return buf->newImageSnapshot(); return buf->newImageSnapshot();
} }
void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat, WebGLTexture* WebGLRenderingContextBase::validateTexImageBinding(const char* funcName, TexImageFunctionID functionID, GLenum target)
GLsizei width, GLsizei height, GLint border, {
GLenum format, GLenum type, DOMArrayBufferView* pixels) 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()) if (isContextLost())
return; return;
if (!validateTexture2DBinding("texImage2D", target)) if (!validateTexImageBinding(funcName, functionID, target))
return; 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; 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; return;
void* data = pixels ? pixels->baseAddress() : 0; void* data = pixels ? pixels->baseAddress() : 0;
Vector<uint8_t> tempData; Vector<uint8_t> tempData;
bool changeUnpackAlignment = false; bool changeUnpackAlignment = false;
if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
if (!WebGLImageConversion::extractTextureData(width, height, format, type, m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData)) if (sourceType == Tex2D) {
return; if (!WebGLImageConversion::extractTextureData(width, height, format, type, m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData))
data = tempData.data(); return;
data = tempData.data();
}
changeUnpackAlignment = true; 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) if (changeUnpackAlignment)
resetUnpackParameters(); 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) if (changeUnpackAlignment)
restoreUnpackParameters(); restoreUnpackParameters();
} }
void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat, 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()) if (isContextLost())
return; return;
if (!pixels) { if (!pixels) {
synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "no image data"); synthesizeGLError(GL_INVALID_VALUE, funcName, "no image data");
return; return;
} }
if (pixels->data()->bufferBase()->isNeutered()) { 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; return;
} }
if (!validateTexture2DBinding("texImage2D", target)) if (!validateTexImageBinding(funcName, functionID, target))
return; 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; return;
Vector<uint8_t> data; Vector<uint8_t> data;
bool needConversion = true; bool needConversion = true;
...@@ -4130,37 +4199,59 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int ...@@ -4130,37 +4199,59 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
type = GL_FLOAT; type = GL_FLOAT;
} }
if (!WebGLImageConversion::extractImageData(pixels->data()->data(), WebGLImageConversion::DataFormat::DataFormatRGBA8, pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { 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; return;
} }
} }
resetUnpackParameters(); 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(); restoreUnpackParameters();
} }
void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat, 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()) if (isContextLost())
return; return;
if (!validateHTMLImageElement("texImage2D", image, exceptionState)) if (!validateHTMLImageElement(funcName, image, exceptionState))
return; return;
if (!validateTexture2DBinding("texImage2D", target)) if (!validateTexImageBinding(funcName, functionID, target))
return; return;
RefPtr<Image> imageForRender = image->cachedImage()->getImage(); RefPtr<Image> imageForRender = image->cachedImage()->getImage();
if (imageForRender && imageForRender->isSVGImage()) 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; return;
if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) { texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, zoffset, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
// The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented. }
type = GL_FLOAT;
} void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha); 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) bool WebGLRenderingContextBase::canUseTexImageCanvasByGPU(GLint internalformat, GLenum type)
...@@ -4234,30 +4325,65 @@ void WebGLRenderingContextBase::texImageCanvasByGPU(TexImageByGPUType functionTy ...@@ -4234,30 +4325,65 @@ void WebGLRenderingContextBase::texImageCanvasByGPU(TexImageByGPUType functionTy
} }
} }
void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat, void WebGLRenderingContextBase::texImageHelperHTMLCanvasElement(TexImageFunctionID functionID,
GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) 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()) if (isContextLost())
return; return;
if (!validateHTMLCanvasElement("texImage2D", canvas, exceptionState)) if (!validateHTMLCanvasElement(funcName, canvas, exceptionState))
return; return;
WebGLTexture* texture = validateTexture2DBinding("texImage2D", target); WebGLTexture* texture = validateTexImageBinding(funcName, functionID, target);
if (!texture) if (!texture)
return; return;
if (!validateTexFunc("texImage2D", TexImage, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 1, 0, format, type, 0, 0, 0)) TexImageFunctionType functionType;
return; 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. texImage2DBase(target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0);
// FIXME: relax the constrains if copyTextureCHROMIUM is upgraded to handle more formats. texImageCanvasByGPU(TexImage2DByGPU, texture, target, level, internalformat, type, 0, 0, 0, canvas);
if (!canvas->renderingContext() || !canvas->renderingContext()->isAccelerated() || !canUseTexImageCanvasByGPU(internalformat, type)) { } else if (functionID == TexSubImage2D) {
// 2D canvas has only FrontBuffer. // FIXME: Implement GPU-to-GPU path for WebGL 2 and more internal formats.
texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(FrontBuffer, PreferAcceleration).get(), 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); WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
return;
} }
}
texImage2DBase(target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0); void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
texImageCanvasByGPU(TexImage2DByGPU, texture, target, level, internalformat, type, 0, 0, 0, canvas); 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) PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video)
...@@ -4273,63 +4399,84 @@ PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* ...@@ -4273,63 +4399,84 @@ PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement*
return buf->newImageSnapshot(); return buf->newImageSnapshot();
} }
void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat, void WebGLRenderingContextBase::texImageHelperHTMLVideoElement(TexImageFunctionID functionID,
GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) 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()) if (isContextLost())
return; return;
if (!validateHTMLVideoElement("texImage2D", video, exceptionState)) if (!validateHTMLVideoElement(funcName, video, exceptionState))
return; return;
WebGLTexture* texture = validateTexture2DBinding("texImage2D", target); WebGLTexture* texture = validateTexImageBinding(funcName, functionID, target);
if (!texture) if (!texture)
return; 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; return;
// Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible. if (functionID == TexImage2D) {
// Otherwise, it will fall back to the normal SW path. // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible.
if (GL_TEXTURE_2D == target) { // Otherwise, it will fall back to the normal SW path.
if (Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, type, level) if (GL_TEXTURE_2D == target) {
&& video->copyVideoTextureToPlatformTexture(contextGL(), texture->object(), internalformat, type, m_unpackPremultiplyAlpha, m_unpackFlipY)) { if (Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, type, level)
return; && 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. // 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()))); OwnPtr<ImageBufferSurface> surface = adoptPtr(new AcceleratedImageBufferSurface(IntSize(video->videoWidth(), video->videoHeight())));
if (surface->isValid()) { if (surface->isValid()) {
OwnPtr<ImageBuffer> imageBuffer(ImageBuffer::create(std::move(surface))); OwnPtr<ImageBuffer> imageBuffer(ImageBuffer::create(std::move(surface)));
if (imageBuffer) { if (imageBuffer) {
// The video element paints an RGBA frame into our surface here. By using an AcceleratedImageBufferSurface, // 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 // 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). // may still do a CPU conversion and upload the results).
video->paintCurrentFrame(imageBuffer->canvas(), IntRect(0, 0, video->videoWidth(), video->videoHeight()), nullptr); 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. // 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, if (imageBuffer->copyToPlatformTexture(contextGL(), texture->object(), internalformat, type,
level, m_unpackPremultiplyAlpha, m_unpackFlipY)) { level, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
return; return;
}
} }
} }
} }
} }
// Normal pure SW path.
RefPtr<Image> image = videoFrameToImage(video); RefPtr<Image> image = videoFrameToImage(video);
if (!image) if (!image)
return; 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, 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()) if (isContextLost())
return; return;
if (!validateImageBitmap("texImage2D", bitmap, exceptionState)) if (!validateImageBitmap(funcName, bitmap, exceptionState))
return; return;
if (!validateTexture2DBinding("texImage2D", target)) if (!validateTexImageBinding(funcName, functionID, target))
return; 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; return;
ASSERT(bitmap->bitmapImage()); ASSERT(bitmap->bitmapImage());
RefPtr<SkImage> skImage = bitmap->bitmapImage()->imageForCurrentFrame(); RefPtr<SkImage> skImage = bitmap->bitmapImage()->imageForCurrentFrame();
...@@ -4360,15 +4507,28 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int ...@@ -4360,15 +4507,28 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
bool isPixelDataBGRA = (peekSucceed && pixmap.colorType() == SkColorType::kBGRA_8888_SkColorType); bool isPixelDataBGRA = (peekSucceed && pixmap.colorType() == SkColorType::kBGRA_8888_SkColorType);
if ((isPixelDataBGRA && !WebGLImageConversion::extractImageData(pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatBGRA8, bitmap->size(), format, type, false, false, data)) 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))) { || (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; return;
} }
} }
resetUnpackParameters(); 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(); 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) void WebGLRenderingContextBase::texParameter(GLenum target, GLenum pname, GLfloat paramf, GLint parami, bool isFloat)
{ {
if (isContextLost()) if (isContextLost())
...@@ -4431,222 +4591,41 @@ void WebGLRenderingContextBase::texParameteri(GLenum target, GLenum pname, GLint ...@@ -4431,222 +4591,41 @@ void WebGLRenderingContextBase::texParameteri(GLenum target, GLenum pname, GLint
texParameter(target, pname, 0, param, false); 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, void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLsizei width, GLsizei height,
GLenum format, GLenum type, DOMArrayBufferView* pixels) GLenum format, GLenum type, DOMArrayBufferView* pixels)
{ {
if (isContextLost()) texImageHelperDOMArrayBufferView(TexSubImage2D, target, level, 0, width, height, 0, format, type, 1, xoffset, yoffset, 0, pixels);
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();
} }
void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum format, GLenum type, ImageData* pixels) GLenum format, GLenum type, ImageData* pixels)
{ {
if (isContextLost()) texImageHelperImageData(TexSubImage2D, target, level, 0, 0, format, type, 1, xoffset, yoffset, 0, pixels);
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();
} }
void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState)
{ {
if (isContextLost()) texImageHelperHTMLImageElement(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, image, exceptionState);
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);
} }
void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState)
{ {
if (isContextLost()) texImageHelperHTMLCanvasElement(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, canvas, exceptionState);
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);
} }
void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState)
{ {
if (isContextLost()) texImageHelperHTMLVideoElement(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, video, exceptionState);
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);
} }
void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum format, GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState) GLenum format, GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState)
{ {
if (isContextLost()) texImageHelperImageBitmap(TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, bitmap, exceptionState);
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();
} }
void WebGLRenderingContextBase::uniform1f(const WebGLUniformLocation* location, GLfloat x) void WebGLRenderingContextBase::uniform1f(const WebGLUniformLocation* location, GLfloat x)
......
...@@ -769,17 +769,18 @@ protected: ...@@ -769,17 +769,18 @@ protected:
// Convert texture internal format. // Convert texture internal format.
GLenum convertTexInternalFormat(GLenum internalformat, GLenum type); GLenum convertTexInternalFormat(GLenum internalformat, GLenum type);
void texImage2DBase(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
void texImage2DImpl(GLenum target, GLint level, GLint internalformat, GLenum format, GLenum type, Image*, WebGLImageConversion::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha);
void texSubImage2DBase(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
void texSubImage2DImpl(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, Image*, WebGLImageConversion::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha);
enum TexImageFunctionType { enum TexImageFunctionType {
TexImage, TexImage,
TexSubImage, TexSubImage,
CopyTexImage, CopyTexImage,
CompressedTexImage CompressedTexImage
}; };
enum TexImageFunctionID {
TexImage2D,
TexSubImage2D,
TexImage3D,
TexSubImage3D
};
enum TexImageByGPUType { enum TexImageByGPUType {
TexImage2DByGPU, TexImage2DByGPU,
TexSubImage2DByGPU, TexSubImage2DByGPU,
...@@ -789,6 +790,10 @@ protected: ...@@ -789,6 +790,10 @@ protected:
Tex2D, Tex2D,
Tex3D Tex3D
}; };
void texImage2DBase(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
void texImageImpl(TexImageFunctionID, GLenum target, GLint level, GLint internalformat, GLint xoffset, GLint yoffset, GLint zoffset,
GLenum format, GLenum type, Image*, WebGLImageConversion::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha);
// Copy from the canvas element directly to the texture via the GPU, without a read-back to system memory. // Copy from the canvas element directly to the texture via the GPU, without a read-back to system memory.
void texImageCanvasByGPU(TexImageByGPUType, WebGLTexture*, GLenum target, GLint level, void texImageCanvasByGPU(TexImageByGPUType, WebGLTexture*, GLenum target, GLint level,
GLint internalformat, GLenum type, GLint xoffset, GLint yoffset, GLint zoffset, HTMLCanvasElement*); GLint internalformat, GLenum type, GLint xoffset, GLint yoffset, GLint zoffset, HTMLCanvasElement*);
...@@ -819,6 +824,9 @@ protected: ...@@ -819,6 +824,9 @@ protected:
// null. Otherwise, return the texture bound to the target. // null. Otherwise, return the texture bound to the target.
WebGLTexture* validateTextureBinding(const char* functionName, GLenum target); WebGLTexture* validateTextureBinding(const char* functionName, GLenum target);
// Wrapper function for validateTexture2D(3D)Binding, used in texImageHelper functions.
virtual WebGLTexture* validateTexImageBinding(const char*, TexImageFunctionID, GLenum);
// Helper function to check texture 2D target and texture bound to the target. // Helper function to check texture 2D target and texture bound to the target.
// Generate GL errors and return 0 if target is invalid or texture bound is // Generate GL errors and return 0 if target is invalid or texture bound is
// null. Otherwise, return the texture bound to the target. // null. Otherwise, return the texture bound to the target.
...@@ -1088,6 +1096,16 @@ protected: ...@@ -1088,6 +1096,16 @@ protected:
CrossThreadWeakPersistentThisPointer<WebGLRenderingContextBase> createWeakThisPointer() { return CrossThreadWeakPersistentThisPointer<WebGLRenderingContextBase>(this); } CrossThreadWeakPersistentThisPointer<WebGLRenderingContextBase> createWeakThisPointer() { return CrossThreadWeakPersistentThisPointer<WebGLRenderingContextBase>(this); }
ImageBitmap* transferToImageBitmapBase(); ImageBitmap* transferToImageBitmapBase();
// Helper functions for tex(Sub)Image2D && texSubImage3D
void texImageHelperDOMArrayBufferView(TexImageFunctionID, GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, GLsizei, GLint, GLint, GLint, DOMArrayBufferView*);
void texImageHelperImageData(TexImageFunctionID, GLenum, GLint, GLint, GLint, GLenum, GLenum, GLsizei, GLint, GLint, GLint, ImageData*);
void texImageHelperHTMLImageElement(TexImageFunctionID, GLenum, GLint, GLint, GLenum, GLenum, GLint, GLint, GLint, HTMLImageElement*, ExceptionState&);
void texImageHelperHTMLCanvasElement(TexImageFunctionID, GLenum, GLint, GLint, GLenum, GLenum, GLint, GLint, GLint, HTMLCanvasElement*, ExceptionState&);
void texImageHelperHTMLVideoElement(TexImageFunctionID, GLenum, GLint, GLint, GLenum, GLenum, GLint, GLint, GLint, HTMLVideoElement*, ExceptionState&);
void texImageHelperImageBitmap(TexImageFunctionID, GLenum, GLint, GLint, GLenum, GLenum, GLint, GLint, GLint, ImageBitmap*, ExceptionState&);
static const char* getTexImageFunctionName(TexImageFunctionID);
private: private:
WebGLRenderingContextBase(HTMLCanvasElement*, OffscreenCanvas*, PassOwnPtr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&); WebGLRenderingContextBase(HTMLCanvasElement*, OffscreenCanvas*, PassOwnPtr<WebGraphicsContext3DProvider>, const WebGLContextAttributes&);
static PassOwnPtr<WebGraphicsContext3DProvider> createContextProviderInternal(HTMLCanvasElement*, ScriptState*, WebGLContextAttributes, unsigned); static PassOwnPtr<WebGraphicsContext3DProvider> createContextProviderInternal(HTMLCanvasElement*, ScriptState*, WebGLContextAttributes, unsigned);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment