Title: [282335] trunk
Revision
282335
Author
[email protected]
Date
2021-09-13 10:20:57 -0700 (Mon, 13 Sep 2021)

Log Message

image-rendering: pixelated does not work with WebGL (but does with Canvas2D)
https://bugs.webkit.org/show_bug.cgi?id=193895
<rdar://problem/47656086>

Patch by Kimmo Kinnunen <[email protected]> on 2021-09-13
Reviewed by Simon Fraser.

Source/WebCore:

Implement image-rendering: crisp-edges for WebGL canvas elements
normal on-screen compositing code path on Cocoa by using CA layer filtering
properties.

Similar to non-compositing code path, approximate image-rendering: pixelated
by making it an alias of crisp-edges.

Test: webgl/webgl-image-rendering.html

* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::setContentsMinificationFilter):
(WebCore::GraphicsLayer::contentsMinificationFilter const):
(WebCore::GraphicsLayer::setContentsMagnificationFilter):
(WebCore::GraphicsLayer::contentsMagnificationFilter const):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::toPlatformCALayerFilterType):
(WebCore::GraphicsLayerCA::setContentsMinificationFilter):
(WebCore::GraphicsLayerCA::setContentsMagnificationFilter):
(WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
(WebCore::GraphicsLayerCA::updateContentsScalingFilters):
(WebCore::GraphicsLayerCA::updateContentsPlatformLayer):
(WebCore::GraphicsLayerCA::layerChangeAsString):
* platform/graphics/ca/GraphicsLayerCA.h:
* rendering/RenderHTMLCanvas.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::createPrimaryGraphicsLayer):
(WebCore::RenderLayerBacking::updateContentsScalingFilters):
(WebCore::RenderLayerBacking::updateConfigurationAfterStyleChange):
(WebCore::RenderLayerBacking::updateGeometry):
(WebCore::RenderLayerBacking::paintIntoLayer):
* rendering/RenderLayerBacking.h:

LayoutTests:

Add a test comparing upscaling of WebGL canvas element and an image element
with the same contents when using image-rendering: properties.

* platform/mac/webgl/webgl-image-rendering-expected.png: Added.
* webgl/webgl-image-rendering-expected.txt: Added.
* webgl/webgl-image-rendering.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (282334 => 282335)


--- trunk/LayoutTests/ChangeLog	2021-09-13 17:06:25 UTC (rev 282334)
+++ trunk/LayoutTests/ChangeLog	2021-09-13 17:20:57 UTC (rev 282335)
@@ -1,3 +1,18 @@
+2021-09-13  Kimmo Kinnunen  <[email protected]>
+
+        image-rendering: pixelated does not work with WebGL (but does with Canvas2D)
+        https://bugs.webkit.org/show_bug.cgi?id=193895
+        <rdar://problem/47656086>
+
+        Reviewed by Simon Fraser.
+
+        Add a test comparing upscaling of WebGL canvas element and an image element
+        with the same contents when using image-rendering: properties.
+
+        * platform/mac/webgl/webgl-image-rendering-expected.png: Added.
+        * webgl/webgl-image-rendering-expected.txt: Added.
+        * webgl/webgl-image-rendering.html: Added.
+
 2021-09-13  Eric Hutchison  <[email protected]>
 
         Updated test expectations for performance-api/performance-observer-no-document-leak.html.

Added: trunk/LayoutTests/platform/mac/webgl/webgl-image-rendering-expected.png


(Binary files differ)
Index: trunk/LayoutTests/platform/mac/webgl/webgl-image-rendering-expected.png =================================================================== --- trunk/LayoutTests/platform/mac/webgl/webgl-image-rendering-expected.png 2021-09-13 17:06:25 UTC (rev 282334) +++ trunk/LayoutTests/platform/mac/webgl/webgl-image-rendering-expected.png 2021-09-13 17:20:57 UTC (rev 282335) Property changes on: trunk/LayoutTests/platform/mac/webgl/webgl-image-rendering-expected.png ___________________________________________________________________

Added: svn:mime-type

+image/png \ No newline at end of property

Added: trunk/LayoutTests/webgl/webgl-image-rendering-expected.txt (0 => 282335)


--- trunk/LayoutTests/webgl/webgl-image-rendering-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webgl/webgl-image-rendering-expected.txt	2021-09-13 17:20:57 UTC (rev 282335)
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+

Added: trunk/LayoutTests/webgl/webgl-image-rendering.html (0 => 282335)


--- trunk/LayoutTests/webgl/webgl-image-rendering.html	                        (rev 0)
+++ trunk/LayoutTests/webgl/webgl-image-rendering.html	2021-09-13 17:20:57 UTC (rev 282335)
@@ -0,0 +1,97 @@
+<!--
+    Tests that image-rendering behavior for WebGL canvas element is the same as
+    for an image with the same contents.
+    Left (canvas element) should be the same as right (image element).
+ -->
+<body>
+    <style type=text/css>
+    canvas {
+        width: 64px;
+        height: 64px;
+        display: inline-block;
+    }
+    img {
+        width: 64px;
+        height: 64px;
+        display: inline-block;
+    }
+    .pixelated canvas, .pixelated img {
+        image-rendering: pixelated;
+    }
+    .crisp-edges canvas, .crisp-edges img {
+        image-rendering: crisp-edges;
+    }
+    </style>
+    <div class="pixelated">
+        <canvas width="2" height="2""></canvas>
+        <img src=""
+    </div>
+    <div class="to-be-pixelated">
+        <canvas width="2" height="2""></canvas>
+        <img src=""
+    </div>
+    <div class="pixelated delayed">
+        <canvas width="2" height="2""></canvas>
+        <img src=""
+    </div>
+    <div class="crisp-edges">
+        <canvas width="2" height="2"></canvas>
+        <img src=""
+    </div>
+    <div class="to-be-crisp-edges">
+        <canvas width="2" height="2"></canvas>
+        <img src=""
+    </div>
+    <div class="crisp-edges delayed">
+        <canvas width="2" height="2"></canvas>
+        <img src=""
+    </div>
+    <div>
+        <canvas width="2" height="2"></canvas>
+        <img src=""
+    </div>
+    <div class="to-be-cleared pixelated">
+        <canvas width="2" height="2"></canvas>
+        <img src=""
+    </div>
+    <div class="to-be-cleared crisp-edges">
+        <canvas width="2" height="2"></canvas>
+        <img src=""
+    </div>
+
+    <script>
+    if (window.testRunner) {
+        window.testRunner.dumpAsText(true);
+        window.testRunner.waitUntilDone();
+    }
+    function clear(e) {
+        const gl = e.getContext('webgl');
+        gl.clearColor(0, 1, 0, 1);
+        gl.enable(gl.SCISSOR_TEST);
+        gl.scissor(0, 1, 1, 1);
+        gl.clear(gl.COLOR_BUFFER_BIT);
+    }
+    [...document.querySelectorAll('canvas')].forEach((e) => {
+        if (e.parentNode.className.includes("delayed"))
+            return;
+        clear(e);
+    });
+
+    [...document.querySelectorAll('.to-be-cleared')].forEach((e) => {
+        e.className = ""
+    });
+    window.requestAnimationFrame(() => {
+        [...document.querySelectorAll('.to-be-pixelated')].forEach((e) => {
+            e.className = "pixelated"
+        });
+        [...document.querySelectorAll('.to-be-crisp-edges')].forEach((e) => {
+            e.className = "crisp-edges"
+        });
+        [...document.querySelectorAll('div.delayed > canvas')].forEach((e) => {
+            clear(e);
+        });
+        if (window.testRunner)
+            window.testRunner.notifyDone();
+    });
+    </script>
+</body>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (282334 => 282335)


--- trunk/Source/WebCore/ChangeLog	2021-09-13 17:06:25 UTC (rev 282334)
+++ trunk/Source/WebCore/ChangeLog	2021-09-13 17:20:57 UTC (rev 282335)
@@ -1,3 +1,43 @@
+2021-09-13  Kimmo Kinnunen  <[email protected]>
+
+        image-rendering: pixelated does not work with WebGL (but does with Canvas2D)
+        https://bugs.webkit.org/show_bug.cgi?id=193895
+        <rdar://problem/47656086>
+
+        Reviewed by Simon Fraser.
+
+        Implement image-rendering: crisp-edges for WebGL canvas elements
+        normal on-screen compositing code path on Cocoa by using CA layer filtering
+        properties.
+
+        Similar to non-compositing code path, approximate image-rendering: pixelated
+        by making it an alias of crisp-edges.
+
+        Test: webgl/webgl-image-rendering.html
+
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::setContentsMinificationFilter):
+        (WebCore::GraphicsLayer::contentsMinificationFilter const):
+        (WebCore::GraphicsLayer::setContentsMagnificationFilter):
+        (WebCore::GraphicsLayer::contentsMagnificationFilter const):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::toPlatformCALayerFilterType):
+        (WebCore::GraphicsLayerCA::setContentsMinificationFilter):
+        (WebCore::GraphicsLayerCA::setContentsMagnificationFilter):
+        (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
+        (WebCore::GraphicsLayerCA::updateContentsScalingFilters):
+        (WebCore::GraphicsLayerCA::updateContentsPlatformLayer):
+        (WebCore::GraphicsLayerCA::layerChangeAsString):
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        * rendering/RenderHTMLCanvas.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::createPrimaryGraphicsLayer):
+        (WebCore::RenderLayerBacking::updateContentsScalingFilters):
+        (WebCore::RenderLayerBacking::updateConfigurationAfterStyleChange):
+        (WebCore::RenderLayerBacking::updateGeometry):
+        (WebCore::RenderLayerBacking::paintIntoLayer):
+        * rendering/RenderLayerBacking.h:
+
 2021-09-13  Alan Bujtas  <[email protected]>
 
         [LFC] Remove redundant LayoutState::ensureFormattingState

Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.h (282334 => 282335)


--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.h	2021-09-13 17:06:25 UTC (rev 282334)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.h	2021-09-13 17:20:57 UTC (rev 282335)
@@ -540,6 +540,12 @@
     virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation) { m_contentsOrientation = orientation; }
     CompositingCoordinatesOrientation contentsOrientation() const { return m_contentsOrientation; }
 
+    enum class ScalingFilter { Linear, Nearest, Trilinear };
+    virtual void setContentsMinificationFilter(ScalingFilter filter) { m_contentsMinificationFilter = filter; }
+    ScalingFilter contentsMinificationFilter() const { return m_contentsMinificationFilter; }
+    virtual void setContentsMagnificationFilter(ScalingFilter filter) { m_contentsMagnificationFilter = filter; }
+    ScalingFilter contentsMagnificationFilter() const { return m_contentsMagnificationFilter; }
+
     void dumpLayer(WTF::TextStream&, OptionSet<LayerTreeAsTextOptions> = { }) const;
 
     virtual void setShowDebugBorder(bool show) { m_showDebugBorder = show; }
@@ -769,6 +775,8 @@
     FloatRoundedRect m_masksToBoundsRect;
     FloatSize m_contentsTilePhase;
     FloatSize m_contentsTileSize;
+    ScalingFilter m_contentsMinificationFilter = ScalingFilter::Linear;
+    ScalingFilter m_contentsMagnificationFilter = ScalingFilter::Linear;
     FloatRoundedRect m_backdropFiltersRect;
     std::optional<FloatRect> m_animationExtent;
 

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (282334 => 282335)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2021-09-13 17:06:25 UTC (rev 282334)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2021-09-13 17:20:57 UTC (rev 282335)
@@ -302,6 +302,20 @@
 #endif
 }
 
+static PlatformCALayer::FilterType toPlatformCALayerFilterType(GraphicsLayer::ScalingFilter filter)
+{
+    switch (filter) {
+    case GraphicsLayer::ScalingFilter::Linear:
+        return PlatformCALayer::Linear;
+    case GraphicsLayer::ScalingFilter::Nearest:
+        return PlatformCALayer::Nearest;
+    case GraphicsLayer::ScalingFilter::Trilinear:
+        return PlatformCALayer::Trilinear;
+    }
+    ASSERT_NOT_REACHED();
+    return PlatformCALayer::Linear;
+}
+
 bool GraphicsLayer::supportsLayerType(Type type)
 {
     switch (type) {
@@ -1341,6 +1355,22 @@
 }
 #endif
 
+void GraphicsLayerCA::setContentsMinificationFilter(ScalingFilter filter)
+{
+    if (filter == m_contentsMinificationFilter)
+        return;
+    GraphicsLayer::setContentsMinificationFilter(filter);
+    noteLayerPropertyChanged(ContentsScalingFiltersChanged);
+}
+
+void GraphicsLayerCA::setContentsMagnificationFilter(ScalingFilter filter)
+{
+    if (filter == m_contentsMagnificationFilter)
+        return;
+    GraphicsLayer::setContentsMagnificationFilter(filter);
+    noteLayerPropertyChanged(ContentsScalingFiltersChanged);
+}
+
 void GraphicsLayerCA::layerDidDisplay(PlatformCALayer* layer)
 {
     if (!m_layerClones)
@@ -2025,6 +2055,8 @@
         updateIsDescendentOfSeparatedPortal();
 #endif
 #endif
+    if (m_uncommittedChanges & ContentsScalingFiltersChanged)
+        updateContentsScalingFilters();
 
     if (m_uncommittedChanges & ChildrenChanged) {
         updateSublayerList();
@@ -2485,6 +2517,14 @@
 #endif
 #endif
 
+void GraphicsLayerCA::updateContentsScalingFilters()
+{
+    if (!m_contentsLayer)
+        return;
+    m_contentsLayer->setMinificationFilter(toPlatformCALayerFilterType(m_contentsMinificationFilter));
+    m_contentsLayer->setMagnificationFilter(toPlatformCALayerFilterType(m_contentsMagnificationFilter));
+}
+
 bool GraphicsLayerCA::updateStructuralLayer()
 {
     return ensureStructuralLayer(structuralLayerPurpose());
@@ -2758,6 +2798,7 @@
         m_contentsLayer->setNeedsDisplay();
 
     updateContentsRects();
+    updateContentsScalingFilters();
 }
 
 void GraphicsLayerCA::updateContentsColorLayer()
@@ -4186,6 +4227,7 @@
     case LayerChange::DescendentOfSeparatedPortalChanged: return "DescendentOfSeparatedPortalChanged";
 #endif
 #endif
+    case LayerChange::ContentsScalingFiltersChanged: return "ContentsScalingFiltersChanged";
     }
     ASSERT_NOT_REACHED();
     return "";

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (282334 => 282335)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2021-09-13 17:06:25 UTC (rev 282334)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2021-09-13 17:20:57 UTC (rev 282335)
@@ -155,6 +155,8 @@
     WEBCORE_EXPORT void setContentsToModel(RefPtr<Model>&&) override;
     WEBCORE_EXPORT PlatformLayerID contentsLayerIDForModel() const override;
 #endif
+    WEBCORE_EXPORT void setContentsMinificationFilter(ScalingFilter) override;
+    WEBCORE_EXPORT void setContentsMagnificationFilter(ScalingFilter) override;
 
     bool usesContentsLayer() const override { return m_contentsLayerPurpose != ContentsLayerPurpose::None; }
     
@@ -463,6 +465,7 @@
     void updateIsDescendentOfSeparatedPortal();
 #endif
 #endif
+    void updateContentsScalingFilters();
 
     enum StructuralLayerPurpose {
         NoStructuralLayer = 0,
@@ -578,6 +581,7 @@
         DescendentOfSeparatedPortalChanged      = 1LLU << 43,
 #endif
 #endif
+        ContentsScalingFiltersChanged           = 1LLU << 44,
     };
     typedef uint64_t LayerChangeFlags;
     static const char* layerChangeAsString(LayerChange);

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (282334 => 282335)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2021-09-13 17:06:25 UTC (rev 282334)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2021-09-13 17:20:57 UTC (rev 282335)
@@ -540,17 +540,18 @@
             m_graphicsLayer->setAcceleratesDrawing(true);
     }
 #endif    
-    
-    updateOpacity(renderer().style());
-    updateTransform(renderer().style());
-    updateFilters(renderer().style());
+    auto& style = renderer().style();
+    updateOpacity(style);
+    updateTransform(style);
+    updateFilters(style);
 #if ENABLE(FILTERS_LEVEL_2)
-    updateBackdropFilters(renderer().style());
+    updateBackdropFilters(style);
 #endif
 #if ENABLE(CSS_COMPOSITING)
-    updateBlendMode(renderer().style());
+    updateBlendMode(style);
 #endif
-    updateCustomAppearance(renderer().style());
+    updateCustomAppearance(style);
+    updateContentsScalingFilters(style);
 }
 
 #if PLATFORM(IOS_FAMILY)
@@ -779,6 +780,26 @@
         m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::None);
 }
 
+void RenderLayerBacking::updateContentsScalingFilters(const RenderStyle& style)
+{
+    if (!renderer().isCanvas() || canvasCompositingStrategy(renderer()) != CanvasAsLayerContents)
+        return;
+    auto minificationFilter = GraphicsLayer::ScalingFilter::Linear;
+    auto magnificationFilter = GraphicsLayer::ScalingFilter::Linear;
+    switch (style.imageRendering()) {
+    case ImageRendering::CrispEdges:
+    case ImageRendering::Pixelated:
+        // FIXME: In order to match other code-paths, we treat these the same.
+        minificationFilter = GraphicsLayer::ScalingFilter::Nearest;
+        magnificationFilter = GraphicsLayer::ScalingFilter::Nearest;
+        break;
+    default:
+        break;
+    }
+    m_graphicsLayer->setContentsMinificationFilter(minificationFilter);
+    m_graphicsLayer->setContentsMagnificationFilter(magnificationFilter);
+}
+
 static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer& layer)
 {
     for (auto* curr = &layer; curr; curr = curr->parent()) {
@@ -959,6 +980,7 @@
     updateBlendMode(style);
 #endif
     updateCustomAppearance(style);
+    updateContentsScalingFilters(style);
 }
 
 bool RenderLayerBacking::updateConfiguration(const RenderLayer* compositingAncestor)
@@ -1284,6 +1306,7 @@
 #if ENABLE(CSS_COMPOSITING)
     updateBlendMode(style);
 #endif
+    updateContentsScalingFilters(style);
 
     ASSERT(compositedAncestor == m_owningLayer.ancestorCompositingLayer());
     LayoutRect parentGraphicsLayerRect = computeParentGraphicsLayerRect(compositedAncestor);

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.h (282334 => 282335)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.h	2021-09-13 17:06:25 UTC (rev 282334)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.h	2021-09-13 17:20:57 UTC (rev 282335)
@@ -355,6 +355,7 @@
     void updateBlendMode(const RenderStyle&);
 #endif
     void updateCustomAppearance(const RenderStyle&);
+    void updateContentsScalingFilters(const RenderStyle&);
 
     // Return the opacity value that this layer should use for compositing.
     float compositingOpacity(float rendererOpacity) const;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to