- 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;