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 b5715e16af0b389c83c4665e1bb4a7772bfb1bb6..7162bbf7ec3a4a784ba44a76052a52c993aebf41 100644 |
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
@@ -1882,17 +1882,12 @@ void WebGLRenderingContextBase::compressedTexImage2D(GLenum target, GLint level, |
if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, 1, internalformat, data)) |
return; |
- if (tex->isImmutable()) { |
- synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage2D", "attempted to modify immutable texture"); |
- return; |
- } |
if (isNPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { |
synthesizeGLError(GL_INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2"); |
return; |
} |
webContext()->compressedTexImage2D(target, level, internalformat, width, height, |
border, data->byteLength(), data->baseAddress()); |
- tex->setLevelInfo(target, level, internalformat, width, height, 1, GL_UNSIGNED_BYTE); |
} |
void WebGLRenderingContextBase::compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, DOMArrayBufferView* data) |
@@ -1906,10 +1901,6 @@ void WebGLRenderingContextBase::compressedTexSubImage2D(GLenum target, GLint lev |
return; |
if (!validateCompressedTexFormat("compressedTexSubImage2D", format)) |
return; |
- if (format != tex->getInternalFormat(target, level)) { |
- synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format"); |
- return; |
- } |
if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, 0, width, height, 1, format, tex)) |
return; |
if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, 1, format, data)) |
@@ -1918,6 +1909,7 @@ void WebGLRenderingContextBase::compressedTexSubImage2D(GLenum target, GLint lev |
width, height, format, data->byteLength(), data->baseAddress()); |
} |
+ |
bool WebGLRenderingContextBase::validateSettableTexFormat(const char* functionName, GLenum format) |
{ |
if (isWebGL2OrHigher()) |
@@ -1964,17 +1956,9 @@ void WebGLRenderingContextBase::copyTexImage2D(GLenum target, GLint level, GLenu |
} |
if (!validateSettableTexFormat("copyTexImage2D", internalformat)) |
return; |
- if (tex->isImmutable()) { |
- synthesizeGLError(GL_INVALID_OPERATION, "copyTexImage2D", "attempted to modify immutable texture"); |
- return; |
- } |
WebGLFramebuffer* readFramebufferBinding = nullptr; |
if (!validateReadBufferAndGetInfo("copyTexImage2D", readFramebufferBinding)) |
return; |
- if (!isTexInternalFormatColorBufferCombinationValid(internalformat, boundFramebufferColorFormat())) { |
- synthesizeGLError(GL_INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format"); |
- return; |
- } |
if (isNPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { |
synthesizeGLError(GL_INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2"); |
return; |
@@ -1982,7 +1966,6 @@ void WebGLRenderingContextBase::copyTexImage2D(GLenum target, GLint level, GLenu |
clearIfComposited(); |
ScopedDrawingBufferBinder binder(drawingBuffer(), readFramebufferBinding); |
webContext()->copyTexImage2D(target, level, internalformat, x, y, width, height, border); |
- tex->setLevelInfo(target, level, internalformat, width, height, 1, WebGLTexture::getValidTypeForInternalFormat(internalformat)); |
} |
void WebGLRenderingContextBase::copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) |
@@ -1994,12 +1977,6 @@ void WebGLRenderingContextBase::copyTexSubImage2D(GLenum target, GLint level, GL |
return; |
if (!validateReadBufferAndGetInfo("copyTexSubImage2D", readFramebufferBinding)) |
return; |
- WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true); |
- ASSERT(tex); |
- if (!isTexInternalFormatColorBufferCombinationValid(tex->getInternalFormat(target, level), boundFramebufferColorFormat())) { |
- synthesizeGLError(GL_INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format"); |
- return; |
- } |
clearIfComposited(); |
ScopedDrawingBufferBinder binder(drawingBuffer(), readFramebufferBinding); |
webContext()->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); |
@@ -2478,18 +2455,7 @@ void WebGLRenderingContextBase::generateMipmap(GLenum target) |
WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false); |
if (!tex) |
return; |
- if (!tex->canGenerateMipmaps()) { |
- synthesizeGLError(GL_INVALID_OPERATION, "generateMipmap", "cannot generate mipmaps"); |
- return; |
- } |
- if (tex->getInternalFormat(target, 0) == GL_SRGB_EXT || tex->getInternalFormat(target, 0) == GL_SRGB_ALPHA_EXT) { |
- synthesizeGLError(GL_INVALID_OPERATION, "generateMipmap", "cannot generate mipmaps for sRGB textures"); |
- return; |
- } |
- if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0))) |
- return; |
webContext()->generateMipmap(target); |
- tex->generateMipmapLevelInfo(); |
} |
WebGLActiveInfo* WebGLRenderingContextBase::getActiveAttrib(WebGLProgram* program, GLuint index) |
@@ -3673,14 +3639,10 @@ bool WebGLRenderingContextBase::validateReadBufferAndGetInfo(const char* functio |
readFramebufferBinding = getReadFramebufferBinding(); |
if (readFramebufferBinding) { |
const char* reason = "framebuffer incomplete"; |
- if (readFramebufferBinding->checkStatus(&reason) != GL_FRAMEBUFFER_COMPLETE) { |
+ if (readFramebufferBinding->checkDepthStencilStatus(&reason) != GL_FRAMEBUFFER_COMPLETE) { |
synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason); |
return false; |
} |
- if (!readFramebufferBinding->getReadBufferFormatAndType(nullptr, nullptr)) { |
- synthesizeGLError(GL_INVALID_OPERATION, functionName, "no image to read from"); |
- return false; |
- } |
} else { |
if (m_readBufferOfDefaultFramebuffer == GL_NONE) { |
ASSERT(isWebGL2OrHigher()); |
@@ -4050,10 +4012,7 @@ GLenum WebGLRenderingContextBase::convertTexInternalFormat(GLenum internalformat |
void WebGLRenderingContextBase::texImage2DBase(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) |
{ |
// All calling functions check isContextLost, so a duplicate check is not needed here. |
- WebGLTexture* tex = validateTextureBinding("texImage2D", target, true); |
- ASSERT(tex); |
webContext()->texImage2D(target, level, convertTexInternalFormat(internalformat, type), width, height, border, format, type, pixels); |
- tex->setLevelInfo(target, level, internalformat, width, height, 1, type); |
} |
void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLint internalformat, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha) |
@@ -4096,15 +4055,6 @@ bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexIma |
if (!texture) |
return false; |
- if (functionType == TexSubImage) { |
- if (!texture->isValid(target, level)) { |
- synthesizeGLError(GL_INVALID_OPERATION, functionName, "no previously defined texture image"); |
- return false; |
- } |
- } |
- |
- if (internalformat == 0) |
- internalformat = texture->getInternalFormat(target, level); |
if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, depth, border, format, type)) |
return false; |
@@ -4113,28 +4063,7 @@ bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexIma |
return false; |
if (!validateSize(functionName, xoffset, yoffset, zoffset)) |
return false; |
- // Before checking if it is in the range, check if overflow happens first. |
- CheckedInt<GLint> maxX = xoffset, maxY = yoffset, maxZ = zoffset; |
- maxX += width; |
- maxY += height; |
- maxZ += depth; |
- if (!maxX.isValid() || !maxY.isValid() || !maxZ.isValid() |
- || maxX.value() > texture->getWidth(target, level) |
- || maxY.value() > texture->getHeight(target, level) |
- || maxZ.value() > texture->getDepth(target, level)) { |
- synthesizeGLError(GL_INVALID_VALUE, functionName, "dimensions out of range"); |
- return false; |
- } |
- if (!isWebGL2OrHigher() && texture->getType(target, level) != type) { |
- synthesizeGLError(GL_INVALID_OPERATION, functionName, "type of incoming data does not match that used to define the texture"); |
- return false; |
- } |
} else { |
- if (texture->isImmutable()) { |
- synthesizeGLError(GL_INVALID_OPERATION, functionName, "attempted to modify immutable texture"); |
- return false; |
- } |
- |
// Depth is for WebGL 2.0 only where iSNPOTStrict() is always false. |
if (isNPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { |
synthesizeGLError(GL_INVALID_VALUE, functionName, "level > 0 not power of 2"); |
@@ -4344,9 +4273,6 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int |
if (isContextLost() || !validateHTMLCanvasElement("texImage2D", canvas, exceptionState) || !validateTexFunc("texImage2D", TexImage, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 1, 0, format, type, 0, 0, 0)) |
return; |
- WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); |
- ASSERT(texture); |
- |
// 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)) { |
@@ -4357,8 +4283,9 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int |
} |
texImage2DBase(target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0); |
+ WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); |
+ ASSERT(texture); |
texImageCanvasByGPU(TexImage2DByGPU, texture, target, level, internalformat, type, 0, 0, 0, canvas); |
- texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), 1, type); |
} |
PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video) |
@@ -4388,7 +4315,6 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int |
if (GL_TEXTURE_2D == target) { |
if (Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, type, level) |
&& video->copyVideoTextureToPlatformTexture(webContext(), texture->object(), internalformat, type, m_unpackPremultiplyAlpha, m_unpackFlipY)) { |
- texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), 1, type); |
return; |
} |
@@ -4405,7 +4331,6 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int |
// This is a straight GPU-GPU copy, any necessary color space conversion was handled in the paintCurrentFrameInContext() call. |
if (imageBuffer->copyToPlatformTexture(webContext(), texture->object(), internalformat, type, |
level, m_unpackPremultiplyAlpha, m_unpackFlipY)) { |
- texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), 1, type); |
return; |
} |
} |
@@ -4615,10 +4540,14 @@ void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint |
WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true); |
ASSERT(texture); |
- GLint internalformat = texture->getInternalFormat(target, level); |
+ // 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() || !canUseTexImageCanvasByGPU(internalformat, type)) { |
+ 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); |
@@ -5378,22 +5307,6 @@ ScriptValue WebGLRenderingContextBase::getWebGLIntArrayParameter(ScriptState* sc |
return WebGLAny(scriptState, DOMInt32Array::create(value, length)); |
} |
-bool WebGLRenderingContextBase::isTexInternalFormatColorBufferCombinationValid(GLenum texInternalFormat, GLenum colorBufferFormat) |
-{ |
- unsigned need = WebGLImageConversion::getChannelBitsByFormat(texInternalFormat); |
- unsigned have = WebGLImageConversion::getChannelBitsByFormat(colorBufferFormat); |
- return (need & have) == need; |
-} |
- |
-GLenum WebGLRenderingContextBase::boundFramebufferColorFormat() |
-{ |
- if (m_framebufferBinding && m_framebufferBinding->object()) |
- return m_framebufferBinding->colorBufferFormat(); |
- if (m_requestedAttributes.alpha()) |
- return GL_RGBA; |
- return GL_RGB; |
-} |
- |
WebGLTexture* WebGLRenderingContextBase::validateTextureBinding(const char* functionName, GLenum target, bool useSixEnumsForCubeMap) |
{ |
WebGLTexture* tex = nullptr; |
@@ -5503,7 +5416,7 @@ bool WebGLRenderingContextBase::validateTexFuncFormatAndType(const char* functio |
} |
} |
- if (m_supportedInternalFormats.find(internalformat) == m_supportedInternalFormats.end()) { |
+ if (internalformat != 0 && m_supportedInternalFormats.find(internalformat) == m_supportedInternalFormats.end()) { |
if (functionType == TexImage) { |
synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid internalformat"); |
} else { |
@@ -5520,7 +5433,7 @@ bool WebGLRenderingContextBase::validateTexFuncFormatAndType(const char* functio |
return false; |
} |
FormatType combinationQuery = { internalformat, format, type }; |
- if (m_supportedFormatTypeCombinations.find(combinationQuery) == m_supportedFormatTypeCombinations.end()) { |
+ if (internalformat != 0 && m_supportedFormatTypeCombinations.find(combinationQuery) == m_supportedFormatTypeCombinations.end()) { |
synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid internalformat/format/type combination"); |
return false; |
} |
@@ -5755,14 +5668,6 @@ bool WebGLRenderingContextBase::validateCopyTexSubImage(const char* functionName |
synthesizeGLError(GL_INVALID_VALUE, functionName, "bad dimensions"); |
return false; |
} |
- if (maxX.value() > tex->getWidth(target, level) || maxY.value() > tex->getHeight(target, level) || zoffset >= tex->getDepth(target, level)) { |
- synthesizeGLError(GL_INVALID_VALUE, functionName, "rectangle out of range"); |
- return false; |
- } |
- GLenum internalformat = tex->getInternalFormat(target, level); |
- if (!validateSettableTexFormat(functionName, internalformat)) |
- return false; |
- |
return true; |
} |
@@ -6025,17 +5930,6 @@ bool WebGLRenderingContextBase::validateCompressedTexSubDimensions(const char* f |
synthesizeGLError(GL_INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4"); |
return false; |
} |
- CheckedInt<GLint> maxX = xoffset, maxY = yoffset; |
- maxX += width; |
- maxY += height; |
- if (!maxX.isValid() || ((width % kBlockWidth) && maxX.value() != tex->getWidth(target, level))) { |
Ken Russell (switch to Gerrit)
2016/02/11 01:25:01
Are all of these compressed texture formats' valid
Zhenyao Mo
2016/02/11 02:16:46
It is my next step to consolidate compressed textu
|
- synthesizeGLError(GL_INVALID_OPERATION, functionName, "width not multiple of 4 and width + xoffset not equal to width of the texture level for ETC2/EAC format texture"); |
- return false; |
- } |
- if (!maxY.isValid() || ((height % kBlockHeight) && maxY.value() != tex->getHeight(target, level))) { |
- synthesizeGLError(GL_INVALID_OPERATION, functionName, "height not multiple of 4 and height + yoffset not equal to height of the texture level for ETC2/EAC format texture"); |
- return false; |
- } |
return validateCompressedTexDimensions(functionName, TexSubImage, target, level, width, height, depth, format); |
} |
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: |
@@ -6048,15 +5942,6 @@ bool WebGLRenderingContextBase::validateCompressedTexSubDimensions(const char* f |
synthesizeGLError(GL_INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4"); |
return false; |
} |
- // Before checking if it is in the range, check if overflow happens first. |
- CheckedInt<GLint> maxX = xoffset, maxY = yoffset; |
- maxX += width; |
- maxY += height; |
- if (!maxX.isValid() || !maxY.isValid() || maxX.value() > tex->getWidth(target, level) |
- || maxY.value() > tex->getHeight(target, level)) { |
- synthesizeGLError(GL_INVALID_VALUE, functionName, "dimensions out of range"); |
- return false; |
- } |
return validateCompressedTexDimensions(functionName, TexSubImage, target, level, width, height, depth, format); |
} |
case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: |
@@ -6067,11 +5952,6 @@ bool WebGLRenderingContextBase::validateCompressedTexSubDimensions(const char* f |
synthesizeGLError(GL_INVALID_OPERATION, functionName, "xoffset and yoffset must be zero"); |
return false; |
} |
- if (width != tex->getWidth(target, level) |
- || height != tex->getHeight(target, level)) { |
- synthesizeGLError(GL_INVALID_OPERATION, functionName, "dimensions must match existing level"); |
- return false; |
- } |
return validateCompressedTexDimensions(functionName, TexSubImage, target, level, width, height, depth, format); |
} |
case GC3D_COMPRESSED_ATC_RGB_AMD: |