Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(661)

Unified Diff: third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp

Issue 2026803002: Avoid GPU readback in tex(Sub)Image2D(ImageBitmap) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: should work Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 70d454fe26280c8b1fb0f5a6742bb196a21fb48d..9de4966b6305c42c8dbfd86522d8aeecda00c21e 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -4141,15 +4141,33 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
}
-bool WebGLRenderingContextBase::canUseTexImageCanvasByGPU(GLint internalformat, GLenum type)
+bool WebGLRenderingContextBase::canUseTexImageByGPU(GLint internalformat, GLenum type)
{
if (isFloatType(type) || isIntegerFormat(internalformat) || isSRGBFormat(internalformat))
return false;
return true;
}
-void WebGLRenderingContextBase::texImageCanvasByGPU(TexImageByGPUType functionType, WebGLTexture* texture, GLenum target,
- GLint level, GLint internalformat, GLenum type, GLint xoffset, GLint yoffset, GLint zoffset, HTMLCanvasElement* canvas)
+void WebGLRenderingContextBase::texImageCanvasByGPU(HTMLCanvasElement* canvas, GLuint targetTexture, GLenum targetInternalformat, GLenum targetType, GLint targetLevel)
+{
+ if (!canvas->is3D()) {
+ ImageBuffer* buffer = canvas->buffer();
+ if (!buffer->copyToPlatformTexture(contextGL(), targetTexture, targetInternalformat, targetType,
+ targetLevel, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
+ NOTREACHED();
+ }
+ } else {
+ WebGLRenderingContextBase* gl = toWebGLRenderingContextBase(canvas->renderingContext());
+ ScopedTexture2DRestorer restorer(gl);
+ if (!gl->drawingBuffer()->copyToPlatformTexture(contextGL(), targetTexture, targetInternalformat, targetType,
+ targetLevel, m_unpackPremultiplyAlpha, !m_unpackFlipY, BackBuffer)) {
+ NOTREACHED();
+ }
+ }
+}
+
+void WebGLRenderingContextBase::texImageByGPU(TexImageByGPUType functionType, WebGLTexture* texture, GLenum target,
+ GLint level, GLint internalformat, GLenum type, GLint xoffset, GLint yoffset, GLint zoffset, HTMLCanvasElement* canvas, ImageBitmap* bitmap)
Ken Russell (switch to Gerrit) 2016/06/01 22:55:09 Please add DCHECK(!canvas || !bitmap) and DCHECK(c
xidachen 2016/06/02 13:52:52 Done.
{
ScopedTexture2DRestorer restorer(this);
@@ -4177,20 +4195,10 @@ void WebGLRenderingContextBase::texImageCanvasByGPU(TexImageByGPUType functionTy
canvas->height(), 0, GL_RGBA, targetType, 0);
}
- if (!canvas->is3D()) {
- ImageBuffer* buffer = canvas->buffer();
- if (!buffer->copyToPlatformTexture(contextGL(), targetTexture, targetInternalformat, targetType,
- targetLevel, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
- ASSERT_NOT_REACHED();
- }
- } else {
- WebGLRenderingContextBase* gl = toWebGLRenderingContextBase(canvas->renderingContext());
- ScopedTexture2DRestorer restorer(gl);
- if (!gl->drawingBuffer()->copyToPlatformTexture(contextGL(), targetTexture, targetInternalformat, targetType,
- targetLevel, m_unpackPremultiplyAlpha, !m_unpackFlipY, BackBuffer)) {
- ASSERT_NOT_REACHED();
- }
- }
+ if (canvas)
+ texImageCanvasByGPU(canvas, targetTexture, targetInternalformat, targetType, targetLevel);
+ else
+ texImageBitmapByGPU(bitmap, targetTexture, targetInternalformat, targetType, targetLevel);
if (!possibleDirectCopy) {
GLuint tmpFBO;
@@ -4225,9 +4233,9 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
if (!validateTexFunc("texImage2D", TexImage, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 1, 0, format, type, 0, 0, 0))
return;
- // texImageCanvasByGPU relies on copyTextureCHROMIUM which doesn't support float/integer/sRGB internal format.
+ // texImageByGPU 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() || !canUseTexImageByGPU(internalformat, type)) {
// 2D canvas has only FrontBuffer.
texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(FrontBuffer, PreferAcceleration).get(),
WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
@@ -4235,7 +4243,7 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
}
texImage2DBase(target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0);
- texImageCanvasByGPU(TexImage2DByGPU, texture, target, level, internalformat, type, 0, 0, 0, canvas);
+ texImageByGPU(TexImage2DByGPU, texture, target, level, internalformat, type, 0, 0, 0, canvas, nullptr);
}
PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video)
@@ -4298,6 +4306,12 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
texImage2DImpl(target, level, internalformat, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
}
+void WebGLRenderingContextBase::texImageBitmapByGPU(ImageBitmap* bitmap, GLuint targetTexture, GLenum targetInternalformat, GLenum targetType, GLint targetLevel)
+{
+ RefPtr<SkImage> skImage = bitmap->bitmapImage()->imageForCurrentFrame(drawingBuffer()->contextProvider());
+ bitmap->bitmapImage()->copyTexture(drawingBuffer()->contextProvider(), targetTexture, targetInternalformat, targetType);
+}
+
void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint internalformat,
GLenum format, GLenum type, ImageBitmap* bitmap, ExceptionState& exceptionState)
{
@@ -4305,29 +4319,34 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
return;
if (!validateImageBitmap("texImage2D", bitmap, exceptionState))
return;
- if (!validateTexture2DBinding("texImage2D", target))
+ WebGLTexture* texture = validateTexture2DBinding("texImage2D", target);
+ if (!texture)
return;
if (!validateTexFunc("texImage2D", TexImage, SourceImageBitmap, target, level, internalformat, bitmap->width(), bitmap->height(), 1, 0, format, type, 0, 0, 0))
return;
ASSERT(bitmap->bitmapImage());
+ if (bitmap->isTextureBacked() && canUseTexImageByGPU(internalformat, type)) {
+ texImage2DBase(target, level, internalformat, bitmap->width(), bitmap->height(), 0, format, type, 0);
+ texImageByGPU(TexImage2DByGPU, texture, target, level, internalformat, type, 0, 0, 0, nullptr, bitmap);
+ return;
+ }
RefPtr<SkImage> skImage = bitmap->bitmapImage()->imageForCurrentFrame();
SkPixmap pixmap;
OwnPtr<uint8_t[]> pixelData;
uint8_t* pixelDataPtr = nullptr;
- // TODO(crbug.com/613411): peekPixels fails if the SkImage is texture-backed
- // Use texture mailbox in that case.
+ // In the case where we cannot use texImageByGPU, peekPixels() fails.
Ken Russell (switch to Gerrit) 2016/06/01 22:55:09 This comment seems to indicate that peekPixels() w
xidachen 2016/06/02 13:52:52 The comment is bad, it doesn't convey what I want
bool peekSucceed = skImage->peekPixels(&pixmap);
if (peekSucceed) {
pixelDataPtr = static_cast<uint8_t*>(pixmap.writable_addr());
- } else if (skImage->isTextureBacked()) {
+ } else {
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) {
+ bool isPixelDataRGBA = (havePeekableRGBA || !peekSucceed);
+ if (isPixelDataRGBA && format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
needConversion = false;
} else {
if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) {
@@ -4335,9 +4354,9 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLint int
type = GL_FLOAT;
}
// In the case of ImageBitmap, we do not need to apply flipY or premultiplyAlpha.
- bool isPixelDataBGRA = (peekSucceed && pixmap.colorType() == SkColorType::kBGRA_8888_SkColorType);
+ bool isPixelDataBGRA = 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))) {
+ || (isPixelDataRGBA && !WebGLImageConversion::extractImageData(pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatRGBA8, bitmap->size(), format, type, false, false, data))) {
synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data");
return;
}
@@ -4550,7 +4569,7 @@ void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint
|| extensionEnabled(OESTextureFloatName)
|| extensionEnabled(OESTextureHalfFloatName)
|| extensionEnabled(EXTsRGBName);
- // texImageCanvasByGPU relies on copyTextureCHROMIUM which doesn't support float/integer/sRGB internal format.
+ // texImageByGPU 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.
@@ -4559,7 +4578,7 @@ void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint
return;
}
- texImageCanvasByGPU(TexSubImage2DByGPU, texture, target, level, GL_RGBA, type, xoffset, yoffset, 0, canvas);
+ texImageByGPU(TexSubImage2DByGPU, texture, target, level, GL_RGBA, type, xoffset, yoffset, 0, canvas, nullptr);
}
void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
@@ -4587,37 +4606,46 @@ void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint
return;
if (!validateImageBitmap("texSubImage2D", bitmap, exceptionState))
return;
- if (!validateTexture2DBinding("texSubImage2D", target))
+ WebGLTexture* texture = validateTexture2DBinding("texSubImage2D", target);
+ if (!texture)
return;
- if (!validateTexFunc("texSubImage2D", TexSubImage, SourceImageBitmap, target, level, 0, bitmap->width(), bitmap->height(), 1, 0, format, type, 0, 0, 0))
+ if (!validateTexFunc("texSubImage2D", TexSubImage, SourceImageBitmap, target, level, 0, bitmap->width(), bitmap->height(), 1, 0, format, type, xoffset, yoffset, 0))
+ return;
+ bool useReadBackPath = isWebGL2OrHigher()
+ || extensionEnabled(OESTextureFloatName)
+ || extensionEnabled(OESTextureHalfFloatName)
+ || extensionEnabled(EXTsRGBName);
Ken Russell (switch to Gerrit) 2016/06/01 22:55:09 This looks wrong. Whether the readback path is use
xidachen 2016/06/02 13:52:52 This part of code is actually copied from line 454
+ if (bitmap->isTextureBacked() && !useReadBackPath) {
+ texImageByGPU(TexSubImage2DByGPU, texture, target, level, GL_RGBA, type, xoffset, yoffset, 0, nullptr, bitmap);
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;
+ // In the case where we cannot use texImageByGPU, peekPixels() fails.
Ken Russell (switch to Gerrit) 2016/06/01 22:55:09 Same comment as above here.
xidachen 2016/06/02 13:52:52 Done.
bool peekSucceed = skImage->peekPixels(&pixmap);
if (peekSucceed) {
pixelDataPtr = static_cast<uint8_t*>(pixmap.writable_addr());
- } else if (skImage->isTextureBacked()) {
+ } else {
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) {
+ bool isPixelDataRGBA = (havePeekableRGBA || !peekSucceed);
+ if (isPixelDataRGBA && format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
needConversion = false;
} else {
+ 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;
+ }
// In the case of ImageBitmap, we do not need to apply flipY or premultiplyAlpha.
- bool isPixelDataBGRA = (peekSucceed && pixmap.colorType() == SkColorType::kBGRA_8888_SkColorType);
+ bool isPixelDataBGRA = 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))) {
+ || (isPixelDataRGBA && !WebGLImageConversion::extractImageData(pixelDataPtr, WebGLImageConversion::DataFormat::DataFormatRGBA8, bitmap->size(), format, type, false, false, data))) {
synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data");
return;
}

Powered by Google App Engine
This is Rietveld 408576698