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 5fbbbae804cc29c5758b026e8aa9762a0231e295..d890e8026cd8a367450a57fa30c6097715bdc1e5 100644 |
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
@@ -515,6 +515,29 @@ private: |
Member<WebGLRenderingContextBase> m_context; |
}; |
+class ScopedUnpackParametersResetRestore { |
+ STACK_ALLOCATED(); |
+ |
+public: |
+ explicit ScopedUnpackParametersResetRestore(WebGLRenderingContextBase* context, bool enabled = true) |
+ : m_context(context) |
+ , m_enabled(enabled) |
+ { |
+ if (enabled) |
+ m_context->resetUnpackParameters(); |
+ } |
+ |
+ ~ScopedUnpackParametersResetRestore() |
+ { |
+ if (m_enabled) |
+ m_context->restoreUnpackParameters(); |
+ } |
+ |
+private: |
+ Member<WebGLRenderingContextBase> m_context; |
+ bool m_enabled; |
+}; |
+ |
static void formatWebGLStatusString(const StringView& glInfo, const StringView& infoString, StringBuilder& builder) |
{ |
if (infoString.isEmpty()) |
@@ -4038,7 +4061,7 @@ void WebGLRenderingContextBase::texImageImpl(TexImageFunctionID functionID, GLen |
} |
} |
- resetUnpackParameters(); |
+ ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
if (functionID == TexImage2D) { |
texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 0, format, type, needConversion ? data.data() : imagePixelData); |
} else if (functionID == TexSubImage2D) { |
@@ -4047,7 +4070,6 @@ void WebGLRenderingContextBase::texImageImpl(TexImageFunctionID functionID, GLen |
DCHECK_EQ(functionID, TexSubImage3D); |
contextGL()->TexSubImage3D(target, level, xoffset, yoffset, zoffset, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 1, format, type, needConversion ? data.data() : imagePixelData); |
} |
- restoreUnpackParameters(); |
} |
bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexImageFunctionType functionType, TexFuncValidationSourceType sourceType, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLint xoffset, GLint yoffset, GLint zoffset) |
@@ -4189,14 +4211,11 @@ void WebGLRenderingContextBase::texImageHelperDOMArrayBufferView(TexImageFunctio |
return; |
} |
- if (changeUnpackAlignment) |
- resetUnpackParameters(); |
+ ScopedUnpackParametersResetRestore temporaryResetUnpack(this, changeUnpackAlignment); |
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, |
@@ -4246,7 +4265,7 @@ void WebGLRenderingContextBase::texImageHelperImageData(TexImageFunctionID funct |
return; |
} |
} |
- resetUnpackParameters(); |
+ ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
if (functionID == TexImage2D) { |
texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), border, format, type, needConversion ? data.data() : pixels->data()->data()); |
} else if (functionID == TexSubImage2D) { |
@@ -4255,7 +4274,6 @@ void WebGLRenderingContextBase::texImageHelperImageData(TexImageFunctionID funct |
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, |
@@ -4311,8 +4329,7 @@ void WebGLRenderingContextBase::texImageCanvasByGPU(HTMLCanvasElement* canvas, G |
{ |
if (!canvas->is3D()) { |
ImageBuffer* buffer = canvas->buffer(); |
- if (!buffer->copyToPlatformTexture(contextGL(), targetTexture, targetInternalformat, targetType, |
- targetLevel, m_unpackPremultiplyAlpha, m_unpackFlipY)) { |
+ if (extensionsUtil()->canUseCopyTextureCHROMIUM(targetTexture, targetInternalformat, targetType, targetLevel) && !buffer->copyToPlatformTexture(contextGL(), targetTexture, targetInternalformat, targetType, targetLevel, m_unpackPremultiplyAlpha, m_unpackFlipY)) { |
NOTREACHED(); |
} |
} else { |
@@ -4340,7 +4357,7 @@ void WebGLRenderingContextBase::texImageByGPU(TexImageByGPUType functionType, We |
GLint targetLevel = level; |
bool possibleDirectCopy = false; |
if (functionType == TexImage2DByGPU) { |
- possibleDirectCopy = Extensions3DUtil::canUseCopyTextureCHROMIUM(target, internalformat, type, level); |
+ possibleDirectCopy = extensionsUtil()->canUseCopyTextureCHROMIUM(target, internalformat, type, level); |
} |
// if direct copy is not possible, create a temporary texture and then copy from canvas to temporary texture to target texture. |
@@ -4464,30 +4481,37 @@ void WebGLRenderingContextBase::texImageHelperHTMLVideoElement(TexImageFunctionI |
if (!validateTexFunc(funcName, functionType, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 1, 0, format, type, xoffset, yoffset, zoffset)) |
return; |
- if (functionID == TexImage2D) { |
+ if (functionID == TexImage2D && GL_TEXTURE_2D == target && extensionsUtil()->canUseCopyTextureCHROMIUM(target, internalformat, type, level)) { |
// 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 (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. |
- std::unique_ptr<ImageBufferSurface> surface = wrapUnique(new AcceleratedImageBufferSurface(IntSize(video->videoWidth(), video->videoHeight()))); |
- if (surface->isValid()) { |
- std::unique_ptr<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, |
+ { |
+ // Try using optimized CPU-GPU path for some formats: e.g. Y16 and Y8. It leaves early for other formats or if frame is stored on GPU. |
+ ScopedUnpackParametersResetRestore(this, m_unpackFlipY || m_unpackPremultiplyAlpha); |
+ if (video->texImageImpl(getTexImageFunctionName(functionID), target, contextGL(), level, internalformat, format, type, xoffset, yoffset, zoffset, |
+ m_unpackFlipY, m_unpackPremultiplyAlpha && m_unpackColorspaceConversion == GL_NONE)) |
+ return; |
+ } |
+ |
+ if (functionID == TexImage2D && GL_TEXTURE_2D == target && extensionsUtil()->canUseCopyTextureCHROMIUM(target, internalformat, type, level)) { |
+ // Try using an accelerated image buffer, this allows YUV conversion to be done on the GPU. |
+ std::unique_ptr<ImageBufferSurface> surface = wrapUnique(new AcceleratedImageBufferSurface(IntSize(video->videoWidth(), video->videoHeight()))); |
+ if (surface->isValid()) { |
+ std::unique_ptr<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; |
- } |
+ return; |
} |
} |
} |
@@ -4572,7 +4596,7 @@ void WebGLRenderingContextBase::texImageHelperImageBitmap(TexImageFunctionID fun |
return; |
} |
} |
- resetUnpackParameters(); |
+ ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
if (functionID == TexImage2D) { |
texImage2DBase(target, level, internalformat, bitmap->width(), bitmap->height(), 0, format, type, needConversion ? data.data() : pixelDataPtr); |
} else if (functionID == TexSubImage2D) { |
@@ -4581,7 +4605,6 @@ void WebGLRenderingContextBase::texImageHelperImageBitmap(TexImageFunctionID fun |
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, |