Chromium Code Reviews| 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 3982dddc41d4fd2a2963f8324dfcbaff0c419407..15dcc4ab8f958eec31b3719969f27a3225700f56 100644 |
| --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
| +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp |
| @@ -819,13 +819,13 @@ sk_sp<SkImage> WebGLRenderingContextBase::makeImageSnapshot( |
| SharedGpuContext::gr(), SkBudgeted::kYes, imageInfo, 0, |
| imageInfo.alphaType() == kOpaque_SkAlphaType ? nullptr |
| : &disableLCDProps); |
| - GLuint textureId = skia::GrBackendObjectToGrGLTextureInfo( |
| - surface->getTextureHandle( |
| - SkSurface::kDiscardWrite_TextureHandleAccess)) |
| - ->fID; |
| + const GrGLTextureInfo* textureInfo = skia::GrBackendObjectToGrGLTextureInfo( |
| + surface->getTextureHandle(SkSurface::kDiscardWrite_TextureHandleAccess)); |
| + GLuint textureId = textureInfo->fID; |
| + GLenum textureTarget = textureInfo->fTarget; |
| drawingBuffer()->copyToPlatformTexture( |
| - gl, textureId, GL_RGBA, GL_UNSIGNED_BYTE, 0, true, false, IntPoint(0, 0), |
| + gl, textureTarget, textureId, true, false, IntPoint(0, 0), |
| IntRect(IntPoint(0, 0), drawingBuffer()->size()), BackBuffer); |
| return surface->makeImageSnapshot(); |
| } |
| @@ -989,76 +989,6 @@ static const GLenum kSupportedTypesTexImageSourceES3[] = { |
| GL_HALF_FLOAT, GL_FLOAT, GL_UNSIGNED_INT_10F_11F_11F_REV, |
| }; |
| -bool isUnsignedIntegerFormat(GLenum internalformat) { |
| - switch (internalformat) { |
| - case GL_R8UI: |
| - case GL_R16UI: |
| - case GL_R32UI: |
| - case GL_RG8UI: |
| - case GL_RG16UI: |
| - case GL_RG32UI: |
| - case GL_RGB8UI: |
| - case GL_RGB16UI: |
| - case GL_RGB32UI: |
| - case GL_RGBA8UI: |
| - case GL_RGB10_A2UI: |
| - case GL_RGBA16UI: |
| - case GL_RGBA32UI: |
| - return true; |
| - default: |
| - return false; |
| - } |
| -} |
| - |
| -bool isSignedIntegerFormat(GLenum internalformat) { |
| - switch (internalformat) { |
| - case GL_R8I: |
| - case GL_R16I: |
| - case GL_R32I: |
| - case GL_RG8I: |
| - case GL_RG16I: |
| - case GL_RG32I: |
| - case GL_RGB8I: |
| - case GL_RGB16I: |
| - case GL_RGB32I: |
| - case GL_RGBA8I: |
| - case GL_RGBA16I: |
| - case GL_RGBA32I: |
| - return true; |
| - default: |
| - return false; |
| - } |
| -} |
| - |
| -bool isIntegerFormat(GLenum internalformat) { |
| - return (isUnsignedIntegerFormat(internalformat) || |
| - isSignedIntegerFormat(internalformat)); |
| -} |
| - |
| -bool isFloatType(GLenum type) { |
| - switch (type) { |
| - case GL_FLOAT: |
| - case GL_HALF_FLOAT: |
| - case GL_HALF_FLOAT_OES: |
| - case GL_UNSIGNED_INT_10F_11F_11F_REV: |
| - return true; |
| - default: |
| - return false; |
| - } |
| -} |
| - |
| -bool isSRGBFormat(GLenum internalformat) { |
| - switch (internalformat) { |
| - case GL_SRGB_EXT: |
| - case GL_SRGB_ALPHA_EXT: |
| - case GL_SRGB8: |
| - case GL_SRGB8_ALPHA8: |
| - return true; |
| - default: |
| - return false; |
| - } |
| -} |
| - |
| } // namespace |
| WebGLRenderingContextBase::WebGLRenderingContextBase( |
| @@ -4959,21 +4889,23 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, |
| sentinelEmptyRect(), 1, 0, exceptionState); |
| } |
| -bool WebGLRenderingContextBase::canUseTexImageByGPU( |
| - TexImageFunctionID functionID, |
| - GLint internalformat, |
| - GLenum type) { |
| - if (functionID == TexImage2D && |
| - (isFloatType(type) || isIntegerFormat(internalformat) || |
| - isSRGBFormat(internalformat))) |
| +bool WebGLRenderingContextBase::canUseTexImageByGPU(GLenum type) { |
| +#if OS(MACOSX) |
| + // RGB5_A1 is not color-renderable on NVIDIA Mac, see crbug.com/676209. |
| + // Though, glCopyTextureCHROMIUM can handle RGB5_A1 internalformat by doing a |
| + // fallback path, but it doesn't know the type info. So, we still cannot do |
|
Zhenyao Mo
2017/03/31 21:12:59
Maybe I miss something, but in command buffer side
qiankun
2017/04/05 08:43:16
We can detect the type info as you said. The fallb
|
| + // the fallback path in glCopyTextureCHROMIUM for |
| + // RGBA/RGBA/UNSIGNED_SHORT_5_5_5_1 format and type combination. |
| + if (type == GL_UNSIGNED_SHORT_5_5_5_1) |
| return false; |
| - // TODO(crbug.com/622958): Implement GPU-to-GPU path for WebGL 2 and more |
| - // internal formats. |
| - if (functionID == TexSubImage2D && |
| - (isWebGL2OrHigher() || extensionEnabled(OESTextureFloatName) || |
| - extensionEnabled(OESTextureHalfFloatName) || |
| - extensionEnabled(EXTsRGBName))) |
| +#endif |
| + // OES_texture_half_float doesn't support HALF_FLOAT_OES type for |
| + // CopyTexImage/CopyTexSubImage. And OES_texture_half_float doesn't require |
| + // HALF_FLOAT_OES type texture to be renderable. So, HALF_FLOAT_OES type |
| + // texture cannot be copied to or drawn to by glCopyTextureCHROMIUM. |
| + if (type == GL_HALF_FLOAT_OES) |
|
Zhenyao Mo
2017/03/31 21:12:59
Is this the right place for this? Because in most
qiankun
2017/04/05 08:43:15
This is used to skip gpu path for RGBA/RGBA/HALF_F
|
| return false; |
| + |
| return true; |
| } |
| @@ -4996,10 +4928,8 @@ SnapshotReason WebGLRenderingContextBase::functionIDToSnapshotReason( |
| void WebGLRenderingContextBase::texImageCanvasByGPU( |
| TexImageFunctionID functionID, |
| HTMLCanvasElement* canvas, |
| + GLenum target, |
| GLuint targetTexture, |
| - GLenum targetInternalformat, |
| - GLenum targetType, |
| - GLint targetLevel, |
| GLint xoffset, |
| GLint yoffset, |
| const IntRect& sourceSubRectangle) { |
| @@ -5007,10 +4937,9 @@ void WebGLRenderingContextBase::texImageCanvasByGPU( |
| ImageBuffer* buffer = canvas->buffer(); |
| if (buffer && |
| !buffer->copyToPlatformTexture( |
| - functionIDToSnapshotReason(functionID), contextGL(), targetTexture, |
| - targetInternalformat, targetType, targetLevel, |
| - m_unpackPremultiplyAlpha, m_unpackFlipY, IntPoint(xoffset, yoffset), |
| - sourceSubRectangle)) { |
| + functionIDToSnapshotReason(functionID), contextGL(), target, |
| + targetTexture, m_unpackPremultiplyAlpha, m_unpackFlipY, |
| + IntPoint(xoffset, yoffset), sourceSubRectangle)) { |
| NOTREACHED(); |
| } |
| } else { |
| @@ -5018,9 +4947,9 @@ void WebGLRenderingContextBase::texImageCanvasByGPU( |
| toWebGLRenderingContextBase(canvas->renderingContext()); |
| ScopedTexture2DRestorer restorer(gl); |
| if (!gl->drawingBuffer()->copyToPlatformTexture( |
| - contextGL(), targetTexture, targetInternalformat, targetType, |
| - targetLevel, m_unpackPremultiplyAlpha, !m_unpackFlipY, |
| - IntPoint(xoffset, yoffset), sourceSubRectangle, BackBuffer)) { |
| + contextGL(), target, targetTexture, m_unpackPremultiplyAlpha, |
| + !m_unpackFlipY, IntPoint(xoffset, yoffset), sourceSubRectangle, |
| + BackBuffer)) { |
| NOTREACHED(); |
| } |
| } |
| @@ -5031,8 +4960,6 @@ void WebGLRenderingContextBase::texImageByGPU( |
| WebGLTexture* texture, |
| GLenum target, |
| GLint level, |
| - GLint internalformat, |
| - GLenum type, |
| GLint xoffset, |
| GLint yoffset, |
| GLint zoffset, |
| @@ -5045,24 +4972,18 @@ void WebGLRenderingContextBase::texImageByGPU( |
| ScopedTexture2DRestorer restorer(this); |
| GLuint targetTexture = texture->object(); |
| - GLenum targetType = type; |
| - GLenum targetInternalformat = internalformat; |
| - GLint targetLevel = level; |
| bool possibleDirectCopy = false; |
| - if (functionID == TexImage2D) { |
| - possibleDirectCopy = Extensions3DUtil::canUseCopyTextureCHROMIUM( |
| - target, internalformat, type, level); |
| + if (functionID == TexImage2D || functionID == TexSubImage2D) { |
| + possibleDirectCopy = Extensions3DUtil::canUseCopyTextureCHROMIUM(target); |
| } |
| GLint copyXOffset = xoffset; |
| GLint copyYOffset = yoffset; |
| + GLenum copyTarget = target; |
| // if direct copy is not possible, create a temporary texture and then copy |
| // from canvas to temporary texture to target texture. |
| if (!possibleDirectCopy) { |
| - targetLevel = 0; |
| - targetInternalformat = GL_RGBA; |
| - targetType = GL_UNSIGNED_BYTE; |
| contextGL()->GenTextures(1, &targetTexture); |
| contextGL()->BindTexture(GL_TEXTURE_2D, targetTexture); |
| contextGL()->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, |
| @@ -5073,21 +4994,26 @@ void WebGLRenderingContextBase::texImageByGPU( |
| GL_CLAMP_TO_EDGE); |
| contextGL()->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, |
| GL_CLAMP_TO_EDGE); |
| - contextGL()->TexImage2D(GL_TEXTURE_2D, 0, targetInternalformat, width, |
| - height, 0, GL_RGBA, targetType, 0); |
| + contextGL()->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, |
| + GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| copyXOffset = 0; |
| copyYOffset = 0; |
| + copyTarget = GL_TEXTURE_2D; |
| } |
| - if (image->isCanvasElement()) { |
| - texImageCanvasByGPU(functionID, static_cast<HTMLCanvasElement*>(image), |
| - targetTexture, targetInternalformat, targetType, |
| - targetLevel, copyXOffset, copyYOffset, |
| - sourceSubRectangle); |
| - } else { |
| - texImageBitmapByGPU(static_cast<ImageBitmap*>(image), targetTexture, |
| - targetInternalformat, targetType, targetLevel, |
| - !m_unpackFlipY); |
| + { |
| + // glCopyTextureCHROMIUM has a DRAW_AND_READBACK path which will call |
| + // texImage2D. So, reset unpack buffer parameters before that. |
| + ScopedUnpackParametersResetRestore temporaryResetUnpack(this); |
| + if (image->isCanvasElement()) { |
| + texImageCanvasByGPU(functionID, static_cast<HTMLCanvasElement*>(image), |
| + copyTarget, targetTexture, copyXOffset, copyYOffset, |
| + sourceSubRectangle); |
| + } else { |
| + texImageBitmapByGPU(static_cast<ImageBitmap*>(image), copyTarget, |
| + targetTexture, !m_unpackFlipY, copyXOffset, |
| + copyYOffset, sourceSubRectangle); |
| + } |
| } |
| if (!possibleDirectCopy) { |
| @@ -5164,7 +5090,7 @@ void WebGLRenderingContextBase::texImageHelperHTMLCanvasElement( |
| // upgraded to handle more formats. |
| if (!canvas->renderingContext() || |
| !canvas->renderingContext()->isAccelerated() || |
| - !canUseTexImageByGPU(functionID, internalformat, type)) { |
| + !canUseTexImageByGPU(type)) { |
| // 2D canvas has only FrontBuffer. |
| texImageImpl(functionID, target, level, internalformat, xoffset, yoffset, |
| zoffset, format, type, |
| @@ -5187,11 +5113,11 @@ void WebGLRenderingContextBase::texImageHelperHTMLCanvasElement( |
| if (functionID == TexImage2D) { |
| texImage2DBase(target, level, internalformat, sourceSubRectangle.width(), |
| sourceSubRectangle.height(), 0, format, type, 0); |
| - texImageByGPU(functionID, texture, target, level, internalformat, type, 0, |
| - 0, 0, canvas, adjustedSourceSubRectangle); |
| + texImageByGPU(functionID, texture, target, level, 0, 0, 0, canvas, |
| + adjustedSourceSubRectangle); |
| } else { |
| - texImageByGPU(functionID, texture, target, level, GL_RGBA, type, xoffset, |
| - yoffset, 0, canvas, adjustedSourceSubRectangle); |
| + texImageByGPU(functionID, texture, target, level, xoffset, yoffset, 0, |
| + canvas, adjustedSourceSubRectangle); |
| } |
| } else { |
| // 3D functions. |
| @@ -5273,9 +5199,15 @@ void WebGLRenderingContextBase::texImageHelperHTMLVideoElement( |
| sourceImageRect == sentinelEmptyRect() || |
| sourceImageRect == |
| IntRect(0, 0, video->videoWidth(), video->videoHeight()); |
| - if (functionID == TexImage2D && sourceImageRectIsDefault && depth == 1 && |
| - GL_TEXTURE_2D == target && Extensions3DUtil::canUseCopyTextureCHROMIUM( |
| - target, internalformat, type, level)) { |
| + const bool useCopyTextureCHROMIUM = |
| + functionID == TexImage2D && sourceImageRectIsDefault && depth == 1 && |
| + GL_TEXTURE_2D == target && canUseTexImageByGPU(type); |
| + // Format of source video may be 16-bit format, e.g. Y16 format. |
| + // glCopyTextureCHROMIUM requires the source texture to be in 8-bit format. |
| + // Converting 16-bits formated source texture to 8-bits formated texture will |
| + // cause precision lost. So, uploading such video texture to half float or |
| + // float texture can not use GPU-GPU path. |
| + if (useCopyTextureCHROMIUM) { |
| DCHECK_EQ(xoffset, 0); |
| DCHECK_EQ(yoffset, 0); |
| DCHECK_EQ(zoffset, 0); |
| @@ -5296,7 +5228,25 @@ void WebGLRenderingContextBase::texImageHelperHTMLVideoElement( |
| texture->updateLastUploadedVideo(video->webMediaPlayer()); |
| return; |
| } |
| + } |
| + |
| + if (sourceImageRectIsDefault) { |
| + // 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( |
| + static_cast<WebMediaPlayer::TexImageFunctionID>(functionID), target, |
| + contextGL(), level, convertTexInternalFormat(internalformat, type), |
| + format, type, xoffset, yoffset, zoffset, m_unpackFlipY, |
| + m_unpackPremultiplyAlpha && |
| + m_unpackColorspaceConversion == GL_NONE)) { |
| + texture->updateLastUploadedVideo(video->webMediaPlayer()); |
| + return; |
| + } |
| + } |
| + if (useCopyTextureCHROMIUM) { |
| // Try using an accelerated image buffer, this allows YUV conversion to be |
| // done on the GPU. |
| std::unique_ptr<ImageBufferSurface> surface = |
| @@ -5318,9 +5268,9 @@ void WebGLRenderingContextBase::texImageHelperHTMLVideoElement( |
| // was handled in the paintCurrentFrameInContext() call. |
| if (imageBuffer->copyToPlatformTexture( |
| - functionIDToSnapshotReason(functionID), contextGL(), |
| - texture->object(), internalformat, type, level, |
| - m_unpackPremultiplyAlpha, m_unpackFlipY, IntPoint(0, 0), |
| + functionIDToSnapshotReason(functionID), contextGL(), target, |
| + texture->object(), m_unpackPremultiplyAlpha, m_unpackFlipY, |
| + IntPoint(0, 0), |
| IntRect(0, 0, video->videoWidth(), video->videoHeight()))) { |
| texture->updateLastUploadedVideo(video->webMediaPlayer()); |
| return; |
| @@ -5329,22 +5279,6 @@ void WebGLRenderingContextBase::texImageHelperHTMLVideoElement( |
| } |
| } |
| - if (sourceImageRectIsDefault) { |
| - // 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( |
| - static_cast<WebMediaPlayer::TexImageFunctionID>(functionID), target, |
| - contextGL(), level, convertTexInternalFormat(internalformat, type), |
| - format, type, xoffset, yoffset, zoffset, m_unpackFlipY, |
| - m_unpackPremultiplyAlpha && |
| - m_unpackColorspaceConversion == GL_NONE)) { |
| - texture->updateLastUploadedVideo(video->webMediaPlayer()); |
| - return; |
| - } |
| - } |
| - |
| RefPtr<Image> image = videoFrameToImage(video); |
| if (!image) |
| return; |
| @@ -5356,15 +5290,17 @@ void WebGLRenderingContextBase::texImageHelperHTMLVideoElement( |
| texture->updateLastUploadedVideo(video->webMediaPlayer()); |
| } |
| -void WebGLRenderingContextBase::texImageBitmapByGPU(ImageBitmap* bitmap, |
| - GLuint targetTexture, |
| - GLenum targetInternalformat, |
| - GLenum targetType, |
| - GLint targetLevel, |
| - bool flipY) { |
| - bitmap->bitmapImage()->copyToTexture(drawingBuffer()->contextProvider(), |
| - targetTexture, targetInternalformat, |
| - targetType, flipY); |
| +void WebGLRenderingContextBase::texImageBitmapByGPU( |
| + ImageBitmap* bitmap, |
| + GLenum target, |
| + GLuint targetTexture, |
| + bool flipY, |
| + GLint xoffset, |
| + GLint yoffset, |
| + const IntRect& sourceSubRectangle) { |
| + bitmap->bitmapImage()->copyToTexture( |
| + drawingBuffer()->contextProvider(), target, targetTexture, flipY, |
| + IntPoint(xoffset, yoffset), sourceSubRectangle); |
| } |
| void WebGLRenderingContextBase::texImage2D(GLenum target, |
| @@ -5426,17 +5362,16 @@ void WebGLRenderingContextBase::texImageHelperImageBitmap( |
| // TODO(kbr): make this work for sub-rectangles of ImageBitmaps. |
| if (functionID != TexSubImage3D && functionID != TexImage3D && |
| - bitmap->isAccelerated() && |
| - canUseTexImageByGPU(functionID, internalformat, type) && |
| + bitmap->isAccelerated() && canUseTexImageByGPU(type) && |
| !selectingSubRectangle) { |
| if (functionID == TexImage2D) { |
| texImage2DBase(target, level, internalformat, width, height, 0, format, |
| type, 0); |
| - texImageByGPU(functionID, texture, target, level, internalformat, type, 0, |
| - 0, 0, bitmap, sourceSubRect); |
| + texImageByGPU(functionID, texture, target, level, 0, 0, 0, bitmap, |
| + sourceSubRect); |
| } else if (functionID == TexSubImage2D) { |
| - texImageByGPU(functionID, texture, target, level, GL_RGBA, type, xoffset, |
| - yoffset, 0, bitmap, sourceSubRect); |
| + texImageByGPU(functionID, texture, target, level, xoffset, yoffset, 0, |
| + bitmap, sourceSubRect); |
| } |
| return; |
| } |