Title: [235611] trunk
Revision
235611
Author
ms2...@igalia.com
Date
2018-09-04 05:10:34 -0700 (Tue, 04 Sep 2018)

Log Message

Implement support for passing ImageBitmap to texImage2D/texSubImage2D
https://bugs.webkit.org/show_bug.cgi?id=187584

Reviewed by Dean Jackson.

Source/WebCore:

Test: fast/canvas/webgl/gl-teximage-imagebitmap.html

* html/canvas/WebGL2RenderingContext.h: Update union type definition.
* html/canvas/WebGL2RenderingContext.idl: Update union type definition.
* html/canvas/WebGLRenderingContext.idl: Update union type definition.
* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::texSubImage2D): implement.
(WebCore::WebGLRenderingContextBase::texImage2D): implement.
* html/canvas/WebGLRenderingContextBase.h: Update union type definition; add to TexFuncValidationSourceType.
* html/canvas/WebGLRenderingContextBase.idl: Remove unused union type definition.

LayoutTests:

* fast/canvas/webgl/gl-teximage-imagebitmap-expected.txt: Added.
* fast/canvas/webgl/gl-teximage-imagebitmap.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (235610 => 235611)


--- trunk/LayoutTests/ChangeLog	2018-09-04 10:27:27 UTC (rev 235610)
+++ trunk/LayoutTests/ChangeLog	2018-09-04 12:10:34 UTC (rev 235611)
@@ -1,3 +1,13 @@
+2018-09-04  Zan Dobersek  <zdober...@igalia.com> and Ms2ger  <ms2...@igalia.com>
+
+        Implement support for passing ImageBitmap to texImage2D/texSubImage2D
+        https://bugs.webkit.org/show_bug.cgi?id=187584
+
+        Reviewed by Dean Jackson.
+
+        * fast/canvas/webgl/gl-teximage-imagebitmap-expected.txt: Added.
+        * fast/canvas/webgl/gl-teximage-imagebitmap.html: Added.
+
 2018-09-04  Yacine Bandou  <yacine.ban...@softathome.com>
 
         [EME] Add layout test for InitData and InitDataType in WebM encrypted event

Added: trunk/LayoutTests/fast/canvas/webgl/gl-teximage-imagebitmap-expected.txt (0 => 235611)


--- trunk/LayoutTests/fast/canvas/webgl/gl-teximage-imagebitmap-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/gl-teximage-imagebitmap-expected.txt	2018-09-04 12:10:34 UTC (rev 235611)
@@ -0,0 +1,15 @@
+PASS getError was expected value: NO_ERROR : Should be no errors from setup.
+PASS getError was expected value: NO_ERROR : Should be no errors from setup
+PASS pixel 0, 149 should be 0, 0, 0, 255 was 0, 0, 0, 255
+PASS pixel 150, 149 should be 0, 0, 255, 255 was 0, 0, 255, 255
+PASS pixel 299, 149 should be 255, 0, 0, 255 was 255, 0, 0, 255
+PASS pixel 0, 75 should be 255, 0, 255, 255 was 255, 0, 255, 255
+PASS pixel 150, 75 should be 255, 0, 0, 255 was 255, 0, 0, 255
+PASS pixel 299, 75 should be 0, 255, 0, 255 was 0, 255, 0, 255
+PASS pixel 0, 0 should be 255, 0, 0, 255 was 255, 0, 0, 255
+PASS pixel 150, 0 should be 255, 255, 0, 255 was 255, 255, 0, 255
+PASS pixel 299, 0 should be 255, 0, 0, 255 was 255, 0, 0, 255
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/canvas/webgl/gl-teximage-imagebitmap.html (0 => 235611)


--- trunk/LayoutTests/fast/canvas/webgl/gl-teximage-imagebitmap.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/gl-teximage-imagebitmap.html	2018-09-04 12:10:34 UTC (rev 235611)
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>texImage2D with ImageBitmap.</title>
+<script src=""
+<script src="" </script>
+<script src="" </script>
+</head>
+<body>
+<canvas id="example"></canvas>
+<div id="description"></div>
+<script>
+function loadImage(url) {
+  return new Promise((resolve, reject) => {
+    var img = document.createElement('img');
+    img._onload_ = () => resolve(img);
+    img._onerror_ = e => reject(e);
+    img.src = ""
+  });
+}
+
+function checkPixel(buf, width, x, y, color) {
+  var off = (y * width + x) * 4;
+  var msg = "pixel " + x + ", " + y + " should be " +
+            color[0] + ", " +
+            color[1] + ", " +
+            color[2] + ", " +
+            color[3] + " was " +
+            buf[off + 0] + ", " +
+            buf[off + 1] + ", " +
+            buf[off + 2] + ", " +
+            buf[off + 3];
+
+  for (var ii = 0; ii < 4; ++ii) {
+    if (buf[off + ii] != color[ii]) {
+      testFailed(msg);
+      return;
+    }
+  }
+  testPassed(msg);
+}
+
+function checkPixelRange(buf, width, x, y, color, allowedRange) {
+  var off = (y * width + x) * 4;
+  var msg = "pixel " + x + ", " + y + " should be within " +
+            allowedRange + " units of " +
+            color[0] + ", " +
+            color[1] + ", " +
+            color[2] + ", " +
+            color[3];
+  var subMsg = " was " +
+            buf[off + 0] + ", " +
+            buf[off + 1] + ", " +
+            buf[off + 2] + ", " +
+            buf[off + 3];
+  // When running in WebKit's test harness, we don't want to print the
+  // pixel value when the test passes, because different machines might
+  // have different results and we record the text output.
+  var inDumpRenderTree = window.testRunner;
+  for (var ii = 0; ii < 4; ++ii) {
+    if (Math.abs(buf[off + ii] - color[ii]) > allowedRange) {
+      testFailed(msg + subMsg);
+      return;
+    }
+  }
+  testPassed(msg + (inDumpRenderTree ? "" : subMsg));
+}
+
+async function test() {
+  var wtu = WebGLTestUtils;
+  var canvas = document.getElementById("example");
+  var gl = wtu.create3DContext(canvas);
+  var program = wtu.setupTexturedQuad(gl);
+
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+
+  var img = await loadImage('resources/3x3.png');
+
+  var loc = gl.getUniformLocation(program, "tex");
+  gl.uniform1i(loc, 0);
+
+  gl.disable(gl.BLEND);
+  gl.disable(gl.DEPTH_TEST);
+
+  var width = canvas.width;
+  var height = canvas.height;
+
+  var tex = gl.createTexture();
+  gl.bindTexture(gl.TEXTURE_2D, tex);
+  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+  var bitmap = await createImageBitmap(img);
+
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+                bitmap);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+  wtu.drawQuad(gl);
+
+  var buf = new Uint8Array(width * height * 4);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+  var left = 0;
+  var middle = Math.floor(width / 2);
+  var right = width - 1;
+  var bottom = 0;
+  var center = Math.floor(height / 2);
+  var top = height - 1;
+  checkPixel(buf, width, left,   top,    [  0,   0,   0, 255]);
+  checkPixel(buf, width, middle, top,    [  0,   0, 255, 255]);
+  checkPixel(buf, width, right,  top,    [255,   0,   0, 255]);
+  checkPixel(buf, width, left,   center, [255,   0, 255, 255]);
+  checkPixel(buf, width, middle, center, [255,   0,   0, 255]);
+  checkPixel(buf, width, right,  center, [  0, 255,   0, 255]);
+  checkPixel(buf, width, left,   bottom, [255,   0,   0, 255]);
+  checkPixel(buf, width, middle, bottom, [255, 255,   0, 255]);
+  checkPixel(buf, width, right,  bottom, [255,   0,   0, 255]);
+}
+
+window.testRunner.waitUntilDone();
+test().then(() => {
+  window.testRunner.notifyDone();
+}, e => {
+  testFailed(String(e));
+});
+</script>

Modified: trunk/Source/WebCore/ChangeLog (235610 => 235611)


--- trunk/Source/WebCore/ChangeLog	2018-09-04 10:27:27 UTC (rev 235610)
+++ trunk/Source/WebCore/ChangeLog	2018-09-04 12:10:34 UTC (rev 235611)
@@ -1,3 +1,21 @@
+2018-09-04  Zan Dobersek  <zdober...@igalia.com> and Ms2ger  <ms2...@igalia.com>
+
+        Implement support for passing ImageBitmap to texImage2D/texSubImage2D
+        https://bugs.webkit.org/show_bug.cgi?id=187584
+
+        Reviewed by Dean Jackson.
+
+        Test: fast/canvas/webgl/gl-teximage-imagebitmap.html
+
+        * html/canvas/WebGL2RenderingContext.h: Update union type definition.
+        * html/canvas/WebGL2RenderingContext.idl: Update union type definition.
+        * html/canvas/WebGLRenderingContext.idl: Update union type definition.
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::texSubImage2D): implement.
+        (WebCore::WebGLRenderingContextBase::texImage2D): implement.
+        * html/canvas/WebGLRenderingContextBase.h: Update union type definition; add to TexFuncValidationSourceType.
+        * html/canvas/WebGLRenderingContextBase.idl: Remove unused union type definition.
+
 2018-09-04  Yacine Bandou  <yacine.bandou_...@softathome.com>
 
         [EME] Add the WebM initData support in ClearKey CDM

Modified: trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h (235610 => 235611)


--- trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h	2018-09-04 10:27:27 UTC (rev 235610)
+++ trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.h	2018-09-04 12:10:34 UTC (rev 235611)
@@ -68,9 +68,9 @@
     void texStorage3D(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth);
 
 #if ENABLE(VIDEO)
-    using TexImageSource = WTF::Variant<RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<HTMLVideoElement>>;
+    using TexImageSource = WTF::Variant<RefPtr<ImageBitmap>, RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<HTMLVideoElement>>;
 #else
-    using TexImageSource = WTF::Variant<RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>>;
+    using TexImageSource = WTF::Variant<RefPtr<ImageBitmap>, RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>>;
 #endif
 
     using WebGLRenderingContextBase::texImage2D;

Modified: trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.idl (235610 => 235611)


--- trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.idl	2018-09-04 10:27:27 UTC (rev 235610)
+++ trunk/Source/WebCore/html/canvas/WebGL2RenderingContext.idl	2018-09-04 12:10:34 UTC (rev 235611)
@@ -44,11 +44,10 @@
 typedef (Int32Array or sequence<GLint>) Int32List;
 typedef (Uint32Array or sequence<GLuint>) Uint32List;
 
-// FIXME: Should allow ImageBitmap too.
 #ifdef ENABLE_VIDEO
-typedef (ImageData or HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) TexImageSource;
+typedef (ImageBitmap or ImageData or HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) TexImageSource;
 #else
-typedef (ImageData or HTMLImageElement or HTMLCanvasElement) TexImageSource;
+typedef (ImageBitmap or ImageData or HTMLImageElement or HTMLCanvasElement) TexImageSource;
 #endif
 
 [

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContext.idl (235610 => 235611)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContext.idl	2018-09-04 10:27:27 UTC (rev 235610)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContext.idl	2018-09-04 12:10:34 UTC (rev 235611)
@@ -27,11 +27,10 @@
 typedef long GLint;
 typedef long GLsizei;
 
-// FIXME: Should allow ImageBitmap too.
 #ifdef ENABLE_VIDEO
-typedef (ImageData or HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) TexImageSource;
+typedef (ImageBitmap or ImageData or HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) TexImageSource;
 #else
-typedef (ImageData or HTMLImageElement or HTMLCanvasElement) TexImageSource;
+typedef (ImageBitmap or ImageData or HTMLImageElement or HTMLCanvasElement) TexImageSource;
 #endif
 
 [

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (235610 => 235611)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2018-09-04 10:27:27 UTC (rev 235610)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2018-09-04 12:10:34 UTC (rev 235611)
@@ -3886,7 +3886,7 @@
     if (isContextLostOrPending())
         return { };
 
-    auto visitor = WTF::makeVisitor([&](const RefPtr<ImageData>& pixels) -> ExceptionOr<void> {
+    auto visitor = WTF::makeVisitor([&](const RefPtr<ImageBitmap>& bitmap) -> ExceptionOr<void> {
         auto texture = validateTextureBinding("texSubImage2D", target, true);
         if (!texture)
             return { };
@@ -3897,6 +3897,28 @@
             return { };
         }
 
+        if (!validateTexFunc("texSubImage2D", TexSubImage, SourceImageBitmap, target, level, internalFormat, bitmap->width(), bitmap->height(), 0, format, type, xoffset, yoffset))
+            return { };
+
+        ImageBuffer* buffer = bitmap->buffer();
+        if (!buffer)
+            return { };
+
+        RefPtr<Image> image = buffer->copyImage(ImageBuffer::fastCopyImageMode());
+        if (image)
+            texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
+        return { };
+    }, [&](const RefPtr<ImageData>& pixels) -> ExceptionOr<void> {
+        auto texture = validateTextureBinding("texSubImage2D", target, true);
+        if (!texture)
+            return { };
+
+        GC3Denum internalFormat = texture->getInternalFormat(target, level);
+        if (!internalFormat) {
+            synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level");
+            return { };
+        }
+
         if (!validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, internalFormat, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
             return { };
 
@@ -4430,7 +4452,38 @@
         return { };
     }
 
-    auto visitor = WTF::makeVisitor([&](const RefPtr<ImageData>& pixels) -> ExceptionOr<void> {
+    auto visitor = WTF::makeVisitor([&](const RefPtr<ImageBitmap>& bitmap) -> ExceptionOr<void> {
+        if (isContextLostOrPending() || !validateTexFunc("texImage2D", TexImage, SourceImageBitmap, target, level, internalformat, bitmap->width(), bitmap->height(), 0, format, type, 0, 0))
+            return { };
+
+        ImageBuffer* buffer = bitmap->buffer();
+        if (!buffer)
+            return { };
+
+        auto texture = validateTextureBinding("texImage2D", target, true);
+        // If possible, copy from the bitmap directly to the texture
+        // via the GPU, without a read-back to system memory.
+        //
+        // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE should be lifted when
+        // ImageBuffer::copyToPlatformTexture implementations are fully functional.
+        if (texture
+            && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA)
+            && type == GraphicsContext3D::UNSIGNED_BYTE) {
+            auto textureInternalFormat = texture->getInternalFormat(target, level);
+            if (isRGBFormat(textureInternalFormat) || !texture->isValid(target, level)) {
+                if (buffer->copyToPlatformTexture(*m_context.get(), target, texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
+                    texture->setLevelInfo(target, level, internalformat, bitmap->width(), bitmap->height(), type);
+                    return { };
+                }
+            }
+        }
+
+        // Normal pure SW path.
+        RefPtr<Image> image = buffer->copyImage(ImageBuffer::fastCopyImageMode());
+        if (image)
+            texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
+        return { };
+    }, [&](const RefPtr<ImageData>& pixels) -> ExceptionOr<void> {
         if (isContextLostOrPending() || !validateTexFunc("texImage2D", TexImage, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0))
             return { };
         Vector<uint8_t> data;

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h (235610 => 235611)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2018-09-04 10:27:27 UTC (rev 235610)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2018-09-04 12:10:34 UTC (rev 235611)
@@ -232,9 +232,9 @@
     void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&);
 
 #if ENABLE(VIDEO)
-    using TexImageSource = WTF::Variant<RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<HTMLVideoElement>>;
+    using TexImageSource = WTF::Variant<RefPtr<ImageBitmap>, RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<HTMLVideoElement>>;
 #else
-    using TexImageSource = WTF::Variant<RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>>;
+    using TexImageSource = WTF::Variant<RefPtr<ImageBitmap>, RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>>;
 #endif
 
     ExceptionOr<void> texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, std::optional<TexImageSource>);
@@ -676,6 +676,7 @@
 
     enum TexFuncValidationSourceType {
         SourceArrayBufferView,
+        SourceImageBitmap,
         SourceImageData,
         SourceHTMLImageElement,
         SourceHTMLCanvasElement,

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.idl (235610 => 235611)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.idl	2018-09-04 10:27:27 UTC (rev 235610)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.idl	2018-09-04 12:10:34 UTC (rev 235611)
@@ -41,13 +41,6 @@
 typedef (Float32Array or sequence<GLfloat>) Float32List;
 typedef (Int32Array or sequence<GLint>) Int32List;
 
-// FIXME: Should allow ImageBitmap too.
-#ifdef ENABLE_VIDEO
-typedef (ImageData or HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) TexImageSource;
-#else
-typedef (ImageData or HTMLImageElement or HTMLCanvasElement) TexImageSource;
-#endif
-
 typedef (HTMLCanvasElement or OffscreenCanvas) WebGLCanvas;
 
 [
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to