- Revision
- 295717
- Author
- hironori.fu...@sony.com
- Date
- 2022-06-21 20:09:26 -0700 (Tue, 21 Jun 2022)
Log Message
TextureMapper: mask should be applied after filter is applied
https://bugs.webkit.org/show_bug.cgi?id=241772
Reviewed by Don Olmstead.
If an element has both a mask-image and filters, the mask should be
applied after the filters.
BitmapTextureGL::applyFilters didn't actually apply the last filter.
It stored the last filter information in it, and applied the last
filter when blitting onto the target. If the element has a mask,
applyFilters should apply all filters before applying the mask.
* LayoutTests/compositing/masks/mask-and-drop-shadow-expected.html: Added.
* LayoutTests/compositing/masks/mask-and-drop-shadow.html: Added.
* Source/WebCore/platform/graphics/texmap/BitmapTexture.h:
(WebCore::BitmapTexture::applyFilters):
* Source/WebCore/platform/graphics/texmap/BitmapTextureGL.cpp:
(WebCore::BitmapTextureGL::applyFilters):
* Source/WebCore/platform/graphics/texmap/BitmapTextureGL.h:
* Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp:
(WebCore::TextureMapperLayer::computeOverlapRegions):
(WebCore::TextureMapperLayer::paintIntoSurface):
Canonical link: https://commits.webkit.org/251722@main
Modified Paths
Added Paths
Diff
Added: trunk/LayoutTests/compositing/masks/mask-and-drop-shadow-expected.html (0 => 295717)
--- trunk/LayoutTests/compositing/masks/mask-and-drop-shadow-expected.html (rev 0)
+++ trunk/LayoutTests/compositing/masks/mask-and-drop-shadow-expected.html 2022-06-22 03:09:26 UTC (rev 295717)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<style>
+ div {
+ width: 200px;
+ height: 200px;
+ background: green;
+ will-change: transform;
+ position: absolute;
+ -webkit-mask-image: linear-gradient(45deg, black, transparent);
+ }
+</style>
+
+You should see no red.
+
+<div></div>
Added: trunk/LayoutTests/compositing/masks/mask-and-drop-shadow.html (0 => 295717)
--- trunk/LayoutTests/compositing/masks/mask-and-drop-shadow.html (rev 0)
+++ trunk/LayoutTests/compositing/masks/mask-and-drop-shadow.html 2022-06-22 03:09:26 UTC (rev 295717)
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<style>
+ div {
+ width: 200px;
+ height: 200px;
+ background: green;
+ filter: drop-shadow(50px 50px 0px red);
+ will-change: transform;
+ position: absolute;
+ -webkit-mask-image: linear-gradient(45deg, black, transparent);
+ }
+</style>
+
+You should see no red.
+
+<div></div>
Modified: trunk/Source/WebCore/platform/graphics/texmap/BitmapTexture.h (295716 => 295717)
--- trunk/Source/WebCore/platform/graphics/texmap/BitmapTexture.h 2022-06-22 03:00:34 UTC (rev 295716)
+++ trunk/Source/WebCore/platform/graphics/texmap/BitmapTexture.h 2022-06-22 03:09:26 UTC (rev 295717)
@@ -78,7 +78,7 @@
inline int numberOfBytes() const { return size().width() * size().height() * bpp() >> 3; }
inline bool isOpaque() const { return !(m_flags & SupportsAlpha); }
- virtual RefPtr<BitmapTexture> applyFilters(TextureMapper&, const FilterOperations&) { return this; }
+ virtual RefPtr<BitmapTexture> applyFilters(TextureMapper&, const FilterOperations&, bool) { return this; }
protected:
IntSize m_contentSize;
Modified: trunk/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.cpp (295716 => 295717)
--- trunk/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.cpp 2022-06-22 03:00:34 UTC (rev 295716)
+++ trunk/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.cpp 2022-06-22 03:09:26 UTC (rev 295717)
@@ -202,7 +202,7 @@
}
}
-RefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper& textureMapper, const FilterOperations& filters)
+RefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper& textureMapper, const FilterOperations& filters, bool defersLastFilter)
{
if (filters.isEmpty())
return this;
@@ -222,17 +222,14 @@
int numPasses = getPassesRequiredForFilter(filter->type());
for (int j = 0; j < numPasses; ++j) {
bool last = (i == filters.size() - 1) && (j == numPasses - 1);
- if (!last) {
- if (!intermediateSurface)
- intermediateSurface = texmapGL.acquireTextureFromPool(contentSize(), BitmapTexture::SupportsAlpha);
- texmapGL.bindSurface(intermediateSurface.get());
- }
-
- if (last) {
+ if (defersLastFilter && last) {
toBitmapTextureGL(resultSurface.get())->m_filterInfo = BitmapTextureGL::FilterInfo(filter.copyRef(), j, spareSurface.copyRef());
break;
}
+ if (!intermediateSurface)
+ intermediateSurface = texmapGL.acquireTextureFromPool(contentSize(), BitmapTexture::SupportsAlpha);
+ texmapGL.bindSurface(intermediateSurface.get());
texmapGL.drawFiltered(*resultSurface.get(), spareSurface.get(), *filter, j);
if (!j && filter->type() == FilterOperation::DROP_SHADOW) {
spareSurface = resultSurface;
Modified: trunk/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.h (295716 => 295717)
--- trunk/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.h 2022-06-22 03:00:34 UTC (rev 295716)
+++ trunk/Source/WebCore/platform/graphics/texmap/BitmapTextureGL.h 2022-06-22 03:09:26 UTC (rev 295717)
@@ -60,7 +60,7 @@
void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine) override;
bool isBackedByOpenGL() const override { return true; }
- RefPtr<BitmapTexture> applyFilters(TextureMapper&, const FilterOperations&) override;
+ RefPtr<BitmapTexture> applyFilters(TextureMapper&, const FilterOperations&, bool defersLastFilter) override;
struct FilterInfo {
RefPtr<FilterOperation> filter;
unsigned pass;
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp (295716 => 295717)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp 2022-06-22 03:00:34 UTC (rev 295716)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp 2022-06-22 03:09:26 UTC (rev 295717)
@@ -343,7 +343,7 @@
else if (m_contentsLayer || m_state.solidColor.isVisible())
localBoundingRect = m_state.contentsRect;
- if (m_currentFilters.hasOutsets() && !m_state.backdropLayer) {
+ if (m_currentFilters.hasOutsets() && !m_state.backdropLayer && !m_state.masksToBounds && !m_state.maskLayer) {
auto outsets = m_currentFilters.outsets();
localBoundingRect.move(-outsets.left(), -outsets.top());
localBoundingRect.expand(outsets.left() + outsets.right(), outsets.top() + outsets.bottom());
@@ -485,14 +485,16 @@
rootLayer().paintSelfAndChildren(options);
} else
paintSelfAndChildren(options);
- if (options.replicaLayer == this) {
- if (m_state.replicaLayer->m_state.maskLayer)
- m_state.replicaLayer->m_state.maskLayer->applyMask(options);
- }
- if (m_state.maskLayer)
+
+ bool hasMask = !!m_state.maskLayer;
+ bool hasReplicaMask = options.replicaLayer == this && m_state.replicaLayer->m_state.maskLayer;
+ bool defersLastFilter = !hasMask && !hasReplicaMask;
+ options.surface = options.surface->applyFilters(options.textureMapper, m_currentFilters, defersLastFilter);
+ options.textureMapper.bindSurface(options.surface.get());
+ if (hasMask)
m_state.maskLayer->applyMask(options);
- options.surface = options.surface->applyFilters(options.textureMapper, m_currentFilters);
- options.textureMapper.bindSurface(options.surface.get());
+ if (hasReplicaMask)
+ m_state.replicaLayer->m_state.maskLayer->applyMask(options);
}
static void commitSurface(TextureMapperPaintOptions& options, BitmapTexture& surface, const IntRect& rect, float opacity)