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

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

Issue 2495953002: Support uploads of sub-rectangles of canvases to 2D and 3D textures. (Closed)
Patch Set: Fixed regression in accelerated video-to-texture uploads. Marked Mac Intel failures. Created 4 years, 1 month 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 6a68b1659cd48b1b932d67291b0ab8663a738304..d801d90ef7233f920f4a08f549777b7252f68277 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -4567,12 +4567,12 @@ IntRect WebGLRenderingContextBase::safeGetImageSize(Image* image) {
if (!image)
return IntRect();
- return IntRect(0, 0, image->width(), image->height());
+ return getTextureSourceSize(image);
}
IntRect WebGLRenderingContextBase::getImageDataSize(ImageData* pixels) {
DCHECK(pixels);
- return IntRect(0, 0, pixels->width(), pixels->height());
+ return getTextureSourceSize(pixels);
}
void WebGLRenderingContextBase::texImageHelperDOMArrayBufferView(
@@ -4815,7 +4815,7 @@ void WebGLRenderingContextBase::texImageHelperHTMLImageElement(
imageForRender.release(), image->width(), image->height(), funcName);
TexImageFunctionType functionType;
- if (functionID == TexImage2D)
+ if (functionID == TexImage2D || functionID == TexImage3D)
functionType = TexImage;
else
functionType = TexSubImage;
@@ -4863,17 +4863,22 @@ bool WebGLRenderingContextBase::canUseTexImageByGPU(
return true;
}
-void WebGLRenderingContextBase::texImageCanvasByGPU(HTMLCanvasElement* canvas,
- GLuint targetTexture,
- GLenum targetInternalformat,
- GLenum targetType,
- GLint targetLevel) {
+void WebGLRenderingContextBase::texImageCanvasByGPU(
+ HTMLCanvasElement* canvas,
+ GLuint targetTexture,
+ GLenum targetInternalformat,
+ GLenum targetType,
+ GLint targetLevel,
+ GLint xoffset,
+ GLint yoffset,
+ const IntRect& sourceSubRectangle) {
if (!canvas->is3D()) {
ImageBuffer* buffer = canvas->buffer();
if (buffer &&
!buffer->copyToPlatformTexture(
contextGL(), targetTexture, targetInternalformat, targetType,
- targetLevel, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
+ targetLevel, m_unpackPremultiplyAlpha, m_unpackFlipY,
+ IntPoint(xoffset, yoffset), sourceSubRectangle)) {
NOTREACHED();
}
} else {
@@ -4883,25 +4888,27 @@ void WebGLRenderingContextBase::texImageCanvasByGPU(HTMLCanvasElement* canvas,
if (!gl->drawingBuffer()->copyToPlatformTexture(
contextGL(), targetTexture, targetInternalformat, targetType,
targetLevel, m_unpackPremultiplyAlpha, !m_unpackFlipY,
- BackBuffer)) {
+ IntPoint(xoffset, yoffset), sourceSubRectangle, BackBuffer)) {
NOTREACHED();
}
}
}
-void WebGLRenderingContextBase::texImageByGPU(TexImageByGPUType functionType,
- WebGLTexture* texture,
- GLenum target,
- GLint level,
- GLint internalformat,
- GLenum type,
- GLint xoffset,
- GLint yoffset,
- GLint zoffset,
- CanvasImageSource* image) {
+void WebGLRenderingContextBase::texImageByGPU(
+ TexImageByGPUType functionType,
+ WebGLTexture* texture,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLenum type,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ CanvasImageSource* image,
+ const IntRect& sourceSubRectangle) {
DCHECK(image->isCanvasElement() || image->isImageBitmap());
- int width = image->sourceWidth();
- int height = image->sourceHeight();
+ int width = sourceSubRectangle.width();
+ int height = sourceSubRectangle.height();
ScopedTexture2DRestorer restorer(this);
@@ -4915,6 +4922,9 @@ void WebGLRenderingContextBase::texImageByGPU(TexImageByGPUType functionType,
target, internalformat, type, level);
}
+ GLint copyXOffset = xoffset;
+ GLint copyYOffset = yoffset;
+
// if direct copy is not possible, create a temporary texture and then copy
// from canvas to temporary texture to target texture.
if (!possibleDirectCopy) {
@@ -4933,15 +4943,19 @@ void WebGLRenderingContextBase::texImageByGPU(TexImageByGPUType functionType,
GL_CLAMP_TO_EDGE);
contextGL()->TexImage2D(GL_TEXTURE_2D, 0, targetInternalformat, width,
height, 0, GL_RGBA, targetType, 0);
+ copyXOffset = 0;
+ copyYOffset = 0;
}
- if (image->isCanvasElement())
+ if (image->isCanvasElement()) {
texImageCanvasByGPU(static_cast<HTMLCanvasElement*>(image), targetTexture,
- targetInternalformat, targetType, targetLevel);
- else
+ targetInternalformat, targetType, targetLevel,
+ copyXOffset, copyYOffset, sourceSubRectangle);
+ } else {
texImageBitmapByGPU(static_cast<ImageBitmap*>(image), targetTexture,
targetInternalformat, targetType, targetLevel,
!m_unpackFlipY);
+ }
if (!possibleDirectCopy) {
GLuint tmpFBO;
@@ -4978,6 +4992,9 @@ void WebGLRenderingContextBase::texImageHelperHTMLCanvasElement(
GLint yoffset,
GLint zoffset,
HTMLCanvasElement* canvas,
+ const IntRect& sourceSubRectangle,
+ GLsizei depth,
+ GLint unpackImageHeight,
ExceptionState& exceptionState) {
const char* funcName = getTexImageFunctionName(functionID);
if (isContextLost())
@@ -4994,8 +5011,41 @@ void WebGLRenderingContextBase::texImageHelperHTMLCanvasElement(
functionType = TexSubImage;
if (!validateTexFunc(funcName, functionType, SourceHTMLCanvasElement, target,
level, internalformat, canvas->width(), canvas->height(),
- 1, 0, format, type, xoffset, yoffset, zoffset))
+ depth, 0, format, type, xoffset, yoffset, zoffset))
+ return;
+
+ // Note that the sub-rectangle validation is needed for the GPU-GPU
+ // copy case, but is redundant for the software upload case
+ // (texImageImpl).
+ bool selectingSubRectangle = false;
+ if (!validateTexImageSubRectangle(
+ funcName, functionID, canvas, sourceSubRectangle, depth,
+ unpackImageHeight, &selectingSubRectangle)) {
return;
+ }
+
+ if (functionID == TexImage3D || functionID == TexSubImage3D) {
+ DCHECK_GE(unpackImageHeight, 0);
+
+ // Verify that the image data can cover the required depth.
+ CheckedNumeric<GLint> maxDepthSupported = 1;
+ if (unpackImageHeight) {
+ maxDepthSupported = sourceSubRectangle.height();
+ maxDepthSupported /= unpackImageHeight;
+ }
+
+ if (!maxDepthSupported.IsValid() ||
+ maxDepthSupported.ValueOrDie() < depth) {
+ synthesizeGLError(
+ GL_INVALID_OPERATION, funcName,
+ "Not enough data supplied to upload to a 3D texture with depth > 1");
+ return;
+ }
+ } else {
+ DCHECK_EQ(depth, 1);
+ DCHECK_EQ(unpackImageHeight, 0);
+ }
+
if (functionID == TexImage2D || functionID == TexSubImage2D) {
// texImageByGPU relies on copyTextureCHROMIUM which doesn't support
// float/integer/sRGB internal format.
@@ -5009,29 +5059,38 @@ void WebGLRenderingContextBase::texImageHelperHTMLCanvasElement(
zoffset, format, type,
canvas->copiedImage(FrontBuffer, PreferAcceleration).get(),
WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY,
- m_unpackPremultiplyAlpha,
- IntRect(0, 0, canvas->width(), canvas->height()), 1, 0);
+ m_unpackPremultiplyAlpha, sourceSubRectangle, 1, 0);
return;
}
+ // The GPU-GPU copy path uses the Y-up coordinate system.
+ IntRect adjustedSourceSubRectangle = sourceSubRectangle;
+ if (!m_unpackFlipY) {
+ adjustedSourceSubRectangle.setY(canvas->height() -
+ adjustedSourceSubRectangle.maxY());
+ }
+
if (functionID == TexImage2D) {
- texImage2DBase(target, level, internalformat, canvas->width(),
- canvas->height(), 0, format, type, 0);
+ texImage2DBase(target, level, internalformat, sourceSubRectangle.width(),
+ sourceSubRectangle.height(), 0, format, type, 0);
texImageByGPU(TexImage2DByGPU, texture, target, level, internalformat,
- type, 0, 0, 0, canvas);
+ type, 0, 0, 0, canvas, adjustedSourceSubRectangle);
} else {
texImageByGPU(TexSubImage2DByGPU, texture, target, level, GL_RGBA, type,
- xoffset, yoffset, 0, canvas);
+ xoffset, yoffset, 0, canvas, adjustedSourceSubRectangle);
}
} 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,
+ // 3D functions.
+
+ // TODO(zmo): Implement GPU-to-GPU copy path (crbug.com/612542).
+ // Note that code will also be needed to copy to layers of 3D
+ // textures, and elements of 2D texture arrays.
+ texImageImpl(functionID, target, level, internalformat, xoffset, yoffset,
+ zoffset, format, type,
canvas->copiedImage(FrontBuffer, PreferAcceleration).get(),
WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY,
- m_unpackPremultiplyAlpha,
- IntRect(0, 0, canvas->width(), canvas->height()), 1, 0);
+ m_unpackPremultiplyAlpha, sourceSubRectangle, depth,
+ unpackImageHeight);
}
}
@@ -5042,9 +5101,9 @@ void WebGLRenderingContextBase::texImage2D(GLenum target,
GLenum type,
HTMLCanvasElement* canvas,
ExceptionState& exceptionState) {
- texImageHelperHTMLCanvasElement(TexImage2D, target, level, internalformat,
- format, type, 0, 0, 0, canvas,
- exceptionState);
+ texImageHelperHTMLCanvasElement(
+ TexImage2D, target, level, internalformat, format, type, 0, 0, 0, canvas,
+ getTextureSourceSize(canvas), 1, 0, exceptionState);
}
PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(
@@ -5125,9 +5184,16 @@ void WebGLRenderingContextBase::texImageHelperHTMLVideoElement(
// This is a straight GPU-GPU copy, any necessary color space
// conversion was handled in the paintCurrentFrameInContext() call.
+
+ // Note that copyToPlatformTexture no longer allocates the
+ // destination texture.
+ texImage2DBase(target, level, internalformat, video->videoWidth(),
+ video->videoHeight(), 0, format, type, nullptr);
+
if (imageBuffer->copyToPlatformTexture(
contextGL(), texture->object(), internalformat, type, level,
- m_unpackPremultiplyAlpha, m_unpackFlipY)) {
+ m_unpackPremultiplyAlpha, m_unpackFlipY, IntPoint(0, 0),
+ IntRect(0, 0, video->videoWidth(), video->videoHeight()))) {
return;
}
}
@@ -5204,10 +5270,10 @@ void WebGLRenderingContextBase::texImageHelperImageBitmap(
texImage2DBase(target, level, internalformat, bitmap->width(),
bitmap->height(), 0, format, type, 0);
texImageByGPU(TexImage2DByGPU, texture, target, level, internalformat,
- type, 0, 0, 0, bitmap);
+ type, 0, 0, 0, bitmap, getTextureSourceSize(bitmap));
} else if (functionID == TexSubImage2D) {
texImageByGPU(TexSubImage2DByGPU, texture, target, level, GL_RGBA, type,
- xoffset, yoffset, 0, bitmap);
+ xoffset, yoffset, 0, bitmap, getTextureSourceSize(bitmap));
}
return;
}
@@ -5409,8 +5475,9 @@ void WebGLRenderingContextBase::texSubImage2D(GLenum target,
GLenum type,
HTMLCanvasElement* canvas,
ExceptionState& exceptionState) {
- texImageHelperHTMLCanvasElement(TexSubImage2D, target, level, 0, format, type,
- xoffset, yoffset, 0, canvas, exceptionState);
+ texImageHelperHTMLCanvasElement(
+ TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0,
+ canvas, getTextureSourceSize(canvas), 1, 0, exceptionState);
}
void WebGLRenderingContextBase::texSubImage2D(GLenum target,

Powered by Google App Engine
This is Rietveld 408576698