Title: [148090] trunk
Revision
148090
Author
[email protected]
Date
2013-04-10 04:48:32 -0700 (Wed, 10 Apr 2013)

Log Message

[Texmap] Hierarchy of layers with opacity may result in wrong blending.
https://bugs.webkit.org/show_bug.cgi?id=113732

Patch by Noam Rosenthal <[email protected]> on 2013-04-10
Reviewed by Allan Sandfeld Jensen.

Source/WebCore:

This is a combination of three issues with nested intermediate surfaces:
- glScissor inside an intermediate surface should not be mirrored.
- The current surface should be passed to the next surface in paintOptions.
- When clipping for the non-overlap region, the containing surface offset
should be applied.

Though the changes are separate, they cannot be tested separately as neither
fixes a testable case on its own.

Tests: compositing/overlap-blending/nested-non-overlap-clipping.html
       compositing/overlap-blending/nested-overlap.html

* platform/graphics/texmap/TextureMapperGL.cpp:
(WebCore::TextureMapperGL::ClipStack::reset):
(WebCore::TextureMapperGL::ClipStack::apply):
(WebCore::TextureMapperGL::beginPainting):
(WebCore::BitmapTextureGL::clearIfNeeded):
* platform/graphics/texmap/TextureMapperGL.h:
(ClipStack):
    Do not mirror the scissor clip when painting to an FBO.
    Also a minor refactor to avoid reading the viewport values from the driver.

* platform/graphics/texmap/TextureMapperLayer.cpp:
(WebCore::TextureMapperLayer::paintUsingOverlapRegions):
    Apply the offset when clipping for a non-overlap region.
(WebCore::TextureMapperLayer::paintIntoSurface):
    Make sure the current surface is passed to the next one.

LayoutTests:

Added two ref-tests for nested composited overlaps.
This ref-test does not work on Mac due to a slight mismatch opacity value on CoreAnimation.
A new bug has been posted, and TestExpectations has been updated.

* compositing/overlap-blending/nested-non-overlap-clipping-expected.html: Added.
* compositing/overlap-blending/nested-non-overlap-clipping.html: Added.
* compositing/overlap-blending/nested-overlap-expected.html: Added.
* compositing/overlap-blending/nested-overlap.html: Added.
* platform/mac/TestExpectations: Skipped new tests and created bug.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (148089 => 148090)


--- trunk/LayoutTests/ChangeLog	2013-04-10 11:34:53 UTC (rev 148089)
+++ trunk/LayoutTests/ChangeLog	2013-04-10 11:48:32 UTC (rev 148090)
@@ -1,3 +1,20 @@
+2013-04-10  Noam Rosenthal  <[email protected]>
+
+        [Texmap] Hierarchy of layers with opacity may result in wrong blending.
+        https://bugs.webkit.org/show_bug.cgi?id=113732
+
+        Reviewed by Allan Sandfeld Jensen.
+
+        Added two ref-tests for nested composited overlaps.
+        This ref-test does not work on Mac due to a slight mismatch opacity value on CoreAnimation.
+        A new bug has been posted, and TestExpectations has been updated.
+
+        * compositing/overlap-blending/nested-non-overlap-clipping-expected.html: Added.
+        * compositing/overlap-blending/nested-non-overlap-clipping.html: Added.
+        * compositing/overlap-blending/nested-overlap-expected.html: Added.
+        * compositing/overlap-blending/nested-overlap.html: Added.
+        * platform/mac/TestExpectations: Skipped new tests and created bug.
+
 2013-04-10  Antti Koivisto  <[email protected]>
 
         Create fewer tiles when page is loading

Added: trunk/LayoutTests/compositing/overlap-blending/nested-non-overlap-clipping-expected.html (0 => 148090)


--- trunk/LayoutTests/compositing/overlap-blending/nested-non-overlap-clipping-expected.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/overlap-blending/nested-non-overlap-clipping-expected.html	2013-04-10 11:48:32 UTC (rev 148090)
@@ -0,0 +1,27 @@
+<html>
+    <head>
+        <style>
+            div {
+                opacity: 0.5;
+                height: 50%;
+                width: 50%;
+            }
+
+            body > div > div {
+                background-color: green;
+            }
+
+            .composited {
+                width: 100%;
+                height: 50%;
+            }
+        </style>
+    </head>
+    <body>
+        <div><span></span>
+            <div><span></span>
+                <div class="composited"><span></span></div>
+            </div>
+        </div>
+    </body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/compositing/overlap-blending/nested-non-overlap-clipping.html (0 => 148090)


--- trunk/LayoutTests/compositing/overlap-blending/nested-non-overlap-clipping.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/overlap-blending/nested-non-overlap-clipping.html	2013-04-10 11:48:32 UTC (rev 148090)
@@ -0,0 +1,28 @@
+<html>
+    <head>
+        <style>
+            div {
+                opacity: 0.5;
+                height: 50%;
+                width: 50%;
+            }
+
+            body > div > div {
+                background-color: green;
+            }
+
+            .composited {
+                -webkit-transform: translateZ(0);
+                width: 100%;
+                height: 50%;
+            }
+        </style>
+    </head>
+    <body>
+        <div><span></span>
+            <div><span></span>
+                <div class="composited"><span></span></div>
+            </div>
+        </div>
+    </body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/compositing/overlap-blending/nested-overlap-expected.html (0 => 148090)


--- trunk/LayoutTests/compositing/overlap-blending/nested-overlap-expected.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/overlap-blending/nested-overlap-expected.html	2013-04-10 11:48:32 UTC (rev 148090)
@@ -0,0 +1,33 @@
+<html>
+    <head>
+        <style>
+            div {
+                width: 200px;
+                height: 200px;
+            }
+
+            span {
+                position: absolute;
+                opacity: 0;
+            }
+
+            .child {
+                opacity: 0.7;
+                background: green;
+            }
+            .container {
+                opacity: 0.7;
+            }
+            body > div {
+                opacity: 0.7;
+            }
+        </style>
+    </head>
+    <body>
+        <div><span></span>
+            <div class="container"><span></span>
+                <div class="child"><span></span></div>
+            </div>
+        </div>
+    </body>
+</html>

Added: trunk/LayoutTests/compositing/overlap-blending/nested-overlap.html (0 => 148090)


--- trunk/LayoutTests/compositing/overlap-blending/nested-overlap.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/overlap-blending/nested-overlap.html	2013-04-10 11:48:32 UTC (rev 148090)
@@ -0,0 +1,34 @@
+<html>
+    <head>
+        <style>
+            div {
+                -webkit-transform: translateZ(0);
+                width: 200px;
+                height: 200px;
+            }
+
+            span {
+                position: absolute;
+                opacity: 0;
+            }
+
+            .child {
+                opacity: 0.7;
+                background: green;
+            }
+            .container {
+                opacity: 0.7;
+            }
+            body > div {
+                opacity: 0.7;
+            }
+        </style>
+    </head>
+    <body>
+        <div><span></span>
+            <div class="container"><span></span>
+                <div class="child"><span></span></div>
+            </div>
+        </div>
+    </body>
+</html>

Modified: trunk/LayoutTests/platform/mac/TestExpectations (148089 => 148090)


--- trunk/LayoutTests/platform/mac/TestExpectations	2013-04-10 11:34:53 UTC (rev 148089)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2013-04-10 11:48:32 UTC (rev 148090)
@@ -937,6 +937,10 @@
 # https://bugs.webkit.org/show_bug.cgi?id=110871
 compositing/overlap-blending/reflection-opacity-huge.html
 
+# https://bugs.webkit.org/show_bug.cgi?id=114340
+compositing/overlap-blending/nested-overlap.html
+compositing/overlap-blending/nested-non-overlap-clipping.html
+
 # https://bugs.webkit.org/show_bug.cgi?id=95027
 fast/block/float/016.html
 

Modified: trunk/Source/WebCore/ChangeLog (148089 => 148090)


--- trunk/Source/WebCore/ChangeLog	2013-04-10 11:34:53 UTC (rev 148089)
+++ trunk/Source/WebCore/ChangeLog	2013-04-10 11:48:32 UTC (rev 148090)
@@ -1,3 +1,38 @@
+2013-04-10  Noam Rosenthal  <[email protected]>
+
+        [Texmap] Hierarchy of layers with opacity may result in wrong blending.
+        https://bugs.webkit.org/show_bug.cgi?id=113732
+
+        Reviewed by Allan Sandfeld Jensen.
+
+        This is a combination of three issues with nested intermediate surfaces:
+        - glScissor inside an intermediate surface should not be mirrored.
+        - The current surface should be passed to the next surface in paintOptions.
+        - When clipping for the non-overlap region, the containing surface offset 
+        should be applied.
+
+        Though the changes are separate, they cannot be tested separately as neither
+        fixes a testable case on its own. 
+
+        Tests: compositing/overlap-blending/nested-non-overlap-clipping.html
+               compositing/overlap-blending/nested-overlap.html
+
+        * platform/graphics/texmap/TextureMapperGL.cpp:
+        (WebCore::TextureMapperGL::ClipStack::reset):
+        (WebCore::TextureMapperGL::ClipStack::apply):
+        (WebCore::TextureMapperGL::beginPainting):
+        (WebCore::BitmapTextureGL::clearIfNeeded):
+        * platform/graphics/texmap/TextureMapperGL.h:
+        (ClipStack):
+            Do not mirror the scissor clip when painting to an FBO.
+            Also a minor refactor to avoid reading the viewport values from the driver.
+
+        * platform/graphics/texmap/TextureMapperLayer.cpp:
+        (WebCore::TextureMapperLayer::paintUsingOverlapRegions):
+            Apply the offset when clipping for a non-overlap region.
+        (WebCore::TextureMapperLayer::paintIntoSurface):
+            Make sure the current surface is passed to the next one.
+
 2013-04-10  Antti Koivisto  <[email protected]>
 
         Create fewer tiles when page is loading

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp (148089 => 148090)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp	2013-04-10 11:34:53 UTC (rev 148089)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp	2013-04-10 11:48:32 UTC (rev 148090)
@@ -174,9 +174,11 @@
         context->deleteBuffer(it->value);
 }
 
-void TextureMapperGL::ClipStack::reset(const IntRect& rect)
+void TextureMapperGL::ClipStack::reset(const IntRect& rect, TextureMapperGL::ClipStack::YAxisMode mode)
 {
     clipStack.clear();
+    size = rect.size();
+    yAxisMode = mode;
     clipState = TextureMapperGL::ClipState(rect);
     clipStateDirty = true;
 }
@@ -208,19 +210,14 @@
     clipStateDirty = true;
 }
 
-static void scissorClip(GraphicsContext3D* context, const IntRect& rect)
+void TextureMapperGL::ClipStack::apply(GraphicsContext3D* context)
 {
-    if (rect.isEmpty())
+    if (clipState.scissorBox.isEmpty())
         return;
 
-    GC3Dint viewport[4];
-    context->getIntegerv(GraphicsContext3D::VIEWPORT, viewport);
-    context->scissor(rect.x(), viewport[3] - rect.maxY(), rect.width(), rect.height());
-}
-
-void TextureMapperGL::ClipStack::apply(GraphicsContext3D* context)
-{
-    scissorClip(context, clipState.scissorBox);
+    context->scissor(clipState.scissorBox.x(),
+        (yAxisMode == InvertedYAxis) ? size.height() - clipState.scissorBox.maxY() : clipState.scissorBox.y(),
+        clipState.scissorBox.width(), clipState.scissorBox.height());
     context->stencilOp(GraphicsContext3D::KEEP, GraphicsContext3D::KEEP, GraphicsContext3D::KEEP);
     context->stencilFunc(GraphicsContext3D::EQUAL, clipState.stencilIndex - 1, clipState.stencilIndex - 1);
     if (clipState.stencilIndex == 1)
@@ -238,7 +235,6 @@
     apply(context);
 }
 
-
 void TextureMapperGLData::initializeStencil()
 {
     if (currentSurface) {
@@ -293,7 +289,7 @@
     m_context3D->depthMask(0);
     m_context3D->getIntegerv(GraphicsContext3D::VIEWPORT, data().viewport);
     m_context3D->getIntegerv(GraphicsContext3D::SCISSOR_BOX, data().previousScissor);
-    m_clipStack.reset(IntRect(0, 0, data().viewport[2], data().viewport[3]));
+    m_clipStack.reset(IntRect(0, 0, data().viewport[2], data().viewport[3]), ClipStack::InvertedYAxis);
     m_context3D->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &data().targetFrameBuffer);
     data().PaintFlags = flags;
     bindSurface(0);
@@ -1040,7 +1036,7 @@
     if (!m_shouldClear)
         return;
 
-    m_clipStack.reset(IntRect(IntPoint::zero(), m_textureSize));
+    m_clipStack.reset(IntRect(IntPoint::zero(), m_textureSize), TextureMapperGL::ClipStack::DefaultYAxis);
     m_clipStack.applyIfNeeded(m_context3D.get());
     m_context3D->clearColor(0, 0, 0, 0);
     m_context3D->clear(GraphicsContext3D::COLOR_BUFFER_BIT);

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h (148089 => 148090)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h	2013-04-10 11:34:53 UTC (rev 148089)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h	2013-04-10 11:48:32 UTC (rev 148090)
@@ -94,12 +94,18 @@
             : clipStateDirty(false)
         { }
 
+        // Y-axis should be inverted only when painting into the window.
+        enum YAxisMode {
+            DefaultYAxis,
+            InvertedYAxis
+        };
+
         void push();
         void pop();
         void apply(GraphicsContext3D*);
         void applyIfNeeded(GraphicsContext3D*);
         inline ClipState& current() { return clipState; }
-        void reset(const IntRect&);
+        void reset(const IntRect&, YAxisMode);
         void intersect(const IntRect&);
         void setStencilIndex(int);
         inline int getStencilIndex() const
@@ -115,6 +121,8 @@
         ClipState clipState;
         Vector<ClipState> clipStack;
         bool clipStateDirty;
+        IntSize size;
+        YAxisMode yAxisMode;
     };
 
     TextureMapperGL();

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp (148089 => 148090)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp	2013-04-10 11:34:53 UTC (rev 148089)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp	2013-04-10 11:48:32 UTC (rev 148090)
@@ -156,8 +156,13 @@
         return;
 
     bool shouldClip = m_state.masksToBounds && !m_state.preserves3D;
-    if (shouldClip)
-        options.textureMapper->beginClip(TransformationMatrix(options.transform).multiply(m_currentTransform.combined()), layerRect());
+    if (shouldClip) {
+        TransformationMatrix clipTransform;
+        clipTransform.translate(options.offset.width(), options.offset.height());
+        clipTransform.multiply(options.transform);
+        clipTransform.multiply(m_currentTransform.combined());
+        options.textureMapper->beginClip(clipTransform, layerRect());
+    }
 
     for (size_t i = 0; i < m_children.size(); ++i)
         m_children[i]->paintRecursive(options);
@@ -333,7 +338,10 @@
         return;
     }
 
-    Vector<IntRect> rects = nonOverlapRegion.rects();
+    Vector<IntRect> rects;
+
+    nonOverlapRegion.translate(options.offset);
+    rects = nonOverlapRegion.rects();
     for (size_t i = 0; i < rects.size(); ++i) {
         options.textureMapper->beginClip(TransformationMatrix(), rects[i]);
         paintSelfAndChildrenWithReplica(options);
@@ -365,8 +373,10 @@
 PassRefPtr<BitmapTexture> TextureMapperLayer::paintIntoSurface(const TextureMapperPaintOptions& options, const IntSize& size)
 {
     RefPtr<BitmapTexture> surface = options.textureMapper->acquireTextureFromPool(size);
+    TextureMapperPaintOptions paintOptions(options);
+    paintOptions.surface = surface;
     options.textureMapper->bindSurface(surface.get());
-    paintSelfAndChildren(options);
+    paintSelfAndChildren(paintOptions);
     if (m_state.maskLayer)
         m_state.maskLayer->applyMask(options);
 #if ENABLE(CSS_FILTERS)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to