[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

vangelis at chromium.org vangelis at chromium.org
Wed Dec 22 12:39:02 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 67e318c0891d0a66501d4daece51c7fc4579e12e
Author: vangelis at chromium.org <vangelis at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Aug 26 18:09:11 2010 +0000

    2010-08-24  Vangelis Kokkevis  <vangelis at chromium.org>
    
            Reviewed by Kenneth Russell.
    
            [chromium] Implementing clipping for composited layers. Two
            types of clipping are added: Scissoring for layers that don't
            contain any rotations and stencil-buffer based clipping for
            all other layers.
            https://bugs.webkit.org/show_bug.cgi?id=44573
    
            Tests: Compositor layout tests that test clipping such as
            compositing/geometry/{clip.html, clipping-foreground.html} now
            work properly.
    
            * platform/graphics/chromium/LayerChromium.cpp:
            (WebCore::LayerChromium::SharedValues::SharedValues):
            (WebCore::LayerChromium::getDrawRect):
            (WebCore::LayerChromium::drawAsMask):
            * platform/graphics/chromium/LayerChromium.h:
            * platform/graphics/chromium/LayerRendererChromium.cpp:
            (WebCore::LayerRendererChromium::drawLayers):
            (WebCore::LayerRendererChromium::drawLayerIntoStencilBuffer):
            (WebCore::LayerRendererChromium::drawLayersRecursive):
            (WebCore::LayerRendererChromium::scissorToRect):
            (WebCore::LayerRendererChromium::initializeSharedObjects):
            * platform/graphics/chromium/LayerRendererChromium.h:
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@66114 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index a0b816f..6978aab 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,30 @@
+2010-08-24  Vangelis Kokkevis  <vangelis at chromium.org>
+
+        Reviewed by Kenneth Russell.
+
+        [chromium] Implementing clipping for composited layers. Two
+        types of clipping are added: Scissoring for layers that don't
+        contain any rotations and stencil-buffer based clipping for
+        all other layers.
+        https://bugs.webkit.org/show_bug.cgi?id=44573
+
+        Tests: Compositor layout tests that test clipping such as
+        compositing/geometry/{clip.html, clipping-foreground.html} now
+        work properly.
+
+        * platform/graphics/chromium/LayerChromium.cpp:
+        (WebCore::LayerChromium::SharedValues::SharedValues):
+        (WebCore::LayerChromium::getDrawRect):
+        (WebCore::LayerChromium::drawAsMask):
+        * platform/graphics/chromium/LayerChromium.h:
+        * platform/graphics/chromium/LayerRendererChromium.cpp:
+        (WebCore::LayerRendererChromium::drawLayers):
+        (WebCore::LayerRendererChromium::drawLayerIntoStencilBuffer):
+        (WebCore::LayerRendererChromium::drawLayersRecursive):
+        (WebCore::LayerRendererChromium::scissorToRect):
+        (WebCore::LayerRendererChromium::initializeSharedObjects):
+        * platform/graphics/chromium/LayerRendererChromium.h:
+
 2010-08-25  Kenneth Russell  <kbr at google.com>
 
         Reviewed by Dimitri Glazkov.
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp
index 3553878..6519f1f 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -109,7 +109,7 @@ LayerChromium::SharedValues::SharedValues()
         "uniform vec4 color;                                 \n"
         "void main()                                         \n"
         "{                                                   \n"
-        "  gl_FragColor = color;                             \n"
+        "  gl_FragColor = vec4(color.xyz * color.w, color.w);\n"
         "}                                                   \n";
 
     m_borderShaderProgram = createShaderProgram(borderVertexShaderString, borderFragmentShaderString);
@@ -431,6 +431,37 @@ void LayerChromium::drawDebugBorder()
     GLC(glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, (void*)(6 * sizeof(unsigned short))));
 }
 
+const FloatRect LayerChromium::getDrawRect() const
+{
+    // Form the matrix used by the shader to map the corners of the layer's
+    // bounds into the view space.
+    TransformationMatrix renderMatrix = drawTransform();
+    renderMatrix.scale3d(bounds().width(), bounds().height(), 1);
+
+    FloatRect layerRect(-0.5, -0.5, 1, 1);
+    FloatRect mappedRect = renderMatrix.mapRect(layerRect);
+    return mappedRect;
+}
+
+// Draws the layer with a single colored shader. This method is used to do
+// quick draws into the stencil buffer.
+void LayerChromium::drawAsMask()
+{
+    ASSERT(layerRenderer());
+    const SharedValues* sv = layerRenderer()->layerSharedValues();
+    ASSERT(sv && sv->initialized());
+    layerRenderer()->useShader(sv->borderShaderProgram());
+
+    // We reuse the border shader here as all we need a single colored shader pass.
+    // The color specified here is only for debug puproses as typically when we call this
+    // method, writes to the color channels are disabled.
+    GLC(glUniform4f(sv->borderShaderColorLocation(), 0, 1 , 0, 0.7));
+
+    drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(),
+        bounds().width(), bounds().height(), drawOpacity(),
+        sv->borderShaderMatrixLocation(), -1);
+}
+
 // static
 void LayerChromium::prepareForDraw(const SharedValues* sv)
 {
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h
index 0d0d362..ba15088 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -151,6 +151,9 @@ public:
 
     bool contentsDirty() { return m_contentsDirty; }
 
+    // Returns the rect containtaining this layer in the current view's coordinate system.
+    const FloatRect getDrawRect() const;
+
     // These methods typically need to be overwritten by derived classes.
     virtual bool drawsContent() { return false; }
     virtual void updateContents() { };
@@ -158,6 +161,9 @@ public:
 
     void drawDebugBorder();
 
+    // Draws the layer without a texture. This is used for stencil operations.
+    void drawAsMask();
+
     // Stores values that are shared between instances of this class that are
     // associated with the same LayerRendererChromium (and hence the same GL
     // context).
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index cf23871..e87d63e 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -183,9 +183,11 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect&
     // Bind the common vertex attributes used for drawing all the layers.
     LayerChromium::prepareForDraw(layerSharedValues());
 
+    // FIXME: These calls can be made once, when the compositor context is initialized.
     GLC(glDisable(GL_DEPTH_TEST));
     GLC(glDisable(GL_CULL_FACE));
     GLC(glDepthFunc(GL_LEQUAL));
+    GLC(glClearStencil(0));
 
     if (m_scrollPosition == IntPoint(-1, -1))
         m_scrollPosition = scrollPosition;
@@ -299,14 +301,23 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect&
     for (i = 0; i < sublayers.size(); i++)
         updateLayersRecursive(sublayers[i].get(), matrix, opacity);
 
+    m_rootVisibleRect = visibleRect;
+
     // Enable scissoring to avoid rendering composited layers over the scrollbars.
     GLC(glEnable(GL_SCISSOR_TEST));
-    GLC(glScissor(0, visibleRect.height() - contentRect.height(), contentRect.width(), contentRect.height()));
+    FloatRect scissorRect(contentRect);
+    // The scissorRect should not include the scroll offset.
+    scissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y());
+    scissorToRect(scissorRect);
+
+    // Clear the stencil buffer to 0.
+    GLC(glClear(GL_STENCIL_BUFFER_BIT));
+    // Disable writes to the stencil buffer.
+    GLC(glStencilMask(0));
 
     // Traverse the layer tree one more time to draw the layers.
-    m_visibleRect = visibleRect;
     for (i = 0; i < sublayers.size(); i++)
-        drawLayersRecursive(sublayers[i].get());
+        drawLayersRecursive(sublayers[i].get(), scissorRect);
 
     GLC(glDisable(GL_SCISSOR_TEST));
 
@@ -419,13 +430,37 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
     layer->setLayerRenderer(this);
 }
 
+// Does a quick draw of the given layer into the stencil buffer. If decrement
+// is true then it decrements the current stencil values otherwise it increments them.
+void LayerRendererChromium::drawLayerIntoStencilBuffer(LayerChromium* layer, bool decrement)
+{
+    // Enable writes to the stencil buffer and increment the stencil values
+    // by one for every pixel under the current layer.
+    GLC(glStencilMask(0xff));
+    GLC(glStencilFunc(GL_ALWAYS, 1, 0xff));
+    if (decrement)
+        GLC(glStencilOp(GL_DECR, GL_DECR, GL_DECR));
+    else
+        GLC(glStencilOp(GL_INCR, GL_INCR, GL_INCR));
+
+    GLC(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE));
+
+    layer->drawAsMask();
+
+    // Disable writes to the stencil buffer.
+    GLC(glStencilMask(0));
+    GLC(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
+}
+
 // Recursively walk the layer tree and draw the layers.
-void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer)
+void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const FloatRect& scissorRect)
 {
     static bool depthTestEnabledForSubtree = false;
+    static int currentStencilValue = 0;
 
     // Check if the layer falls within the visible bounds of the page.
-    bool layerVisible = isLayerVisible(layer, layer->drawTransform(), m_visibleRect);
+    FloatRect layerRect = layer->getDrawRect();
+    bool isLayerVisible = scissorRect.intersects(layerRect);
 
     // Enable depth testing for this layer and all its descendants if preserves3D is set.
     bool mustClearDepth = false;
@@ -439,9 +474,50 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer)
         }
     }
 
-    if (layerVisible)
+    if (isLayerVisible)
         drawLayer(layer);
 
+    // FIXME: We should check here if the layer has descendants that draw content
+    // before we setup for clipping.
+    FloatRect currentScissorRect = scissorRect;
+    bool mustResetScissorRect = false;
+    bool didStencilDraw = false;
+    if (layer->masksToBounds()) {
+        // If the layer isn't rotated then we can use scissoring otherwise we need
+        // to clip using the stencil buffer.
+        if (layer->drawTransform().isIdentityOrTranslation()) {
+            currentScissorRect.intersect(layerRect);
+            if (currentScissorRect != scissorRect) {
+                scissorToRect(currentScissorRect);
+                mustResetScissorRect = true;
+            }
+        } else if (currentStencilValue < ((1 << m_numStencilBits) - 1)) {
+            // Clipping using the stencil buffer works as follows: When we encounter
+            // a clipping layer we increment the stencil buffer values for all the pixels
+            // the layer touches. As a result 1's will be stored in the stencil buffer for pixels under
+            // the first clipping layer found in a traversal, 2's for pixels in the intersection
+            // of two nested clipping layers, etc. When the sublayers of a clipping layer are drawn
+            // we turn on stencil testing to render only pixels that have the correct stencil
+            // value (one that matches the value of currentStencilValue). As the recursion unravels,
+            // we decrement the stencil buffer values for each clipping layer. When the entire layer tree
+            // is rendered, the stencil values should be all back to zero. An 8 bit stencil buffer
+            // will allow us up to 255 nested clipping layers which is hopefully enough.
+            if (!currentStencilValue)
+                GLC(glEnable(GL_STENCIL_TEST));
+
+            drawLayerIntoStencilBuffer(layer, false);
+
+            currentStencilValue++;
+            didStencilDraw = true;
+        }
+    }
+    // Sublayers will render only if the value in the stencil buffer is equal to
+    // currentStencilValue.
+    if (didStencilDraw) {
+        // The sublayers will render only if the stencil test passes.
+        GLC(glStencilFunc(GL_EQUAL, currentStencilValue, 0xff));
+    }
+
     // If we're using depth testing then we need to sort the children in Z to
     // get the transparency to work properly.
     if (depthTestEnabledForSubtree) {
@@ -456,11 +532,27 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer)
         std::stable_sort(sublayerList.begin(), sublayerList.end(), compareLayerZ);
 
         for (i = 0; i < sublayerList.size(); i++)
-            drawLayersRecursive(sublayerList[i]);
+            drawLayersRecursive(sublayerList[i], currentScissorRect);
     } else {
         const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
         for (size_t i = 0; i < sublayers.size(); i++)
-            drawLayersRecursive(sublayers[i].get());
+            drawLayersRecursive(sublayers[i].get(), currentScissorRect);
+    }
+
+    if (didStencilDraw) {
+        // Draw into the stencil buffer subtracting 1 for every pixel hit
+        // effectively removing this mask
+        drawLayerIntoStencilBuffer(layer, true);
+        currentStencilValue--;
+        if (!currentStencilValue) {
+            // Disable stencil testing.
+            GLC(glDisable(GL_STENCIL_TEST));
+            GLC(glStencilFunc(GL_ALWAYS, 0, 0xff));
+        }
+    }
+
+    if (mustResetScissorRect) {
+        scissorToRect(scissorRect);
     }
 
     if (mustClearDepth) {
@@ -494,6 +586,15 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer)
     layer->drawDebugBorder();
 }
 
+// Sets the scissor region to the given rectangle. The coordinate system for the
+// scissorRect has its origin at the top left corner of the current visible rect.
+void LayerRendererChromium::scissorToRect(const FloatRect& scissorRect)
+{
+    // Compute the lower left corner of the scissor rect.
+    float bottom = std::max((float)m_rootVisibleRect.height() - scissorRect.bottom(), 0.f);
+    GLC(glScissor(scissorRect.x(), bottom, scissorRect.width(), scissorRect.height()));
+}
+
 bool LayerRendererChromium::makeContextCurrent()
 {
     return m_gles2Context->makeCurrent();
@@ -565,6 +666,9 @@ bool LayerRendererChromium::initializeSharedObjects()
     // Get the max texture size supported by the system.
     GLC(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize));
 
+    // Get the number of bits available in the stencil buffer.
+    GLC(glGetIntegerv(GL_STENCIL_BITS, &m_numStencilBits));
+
     m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues());
     m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues());
     m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues());
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
index 24bbe65..8f44afe 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -93,12 +93,16 @@ public:
 private:
     void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity);
 
-    void drawLayersRecursive(LayerChromium*);
+    void drawLayersRecursive(LayerChromium*, const FloatRect& scissorRect);
 
     void drawLayer(LayerChromium*);
 
     bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect);
 
+    void drawLayerIntoStencilBuffer(LayerChromium*, bool decrement);
+
+    void scissorToRect(const FloatRect&);
+
     bool makeContextCurrent();
 
     bool initializeSharedObjects();
@@ -135,10 +139,12 @@ private:
 
     IntSize m_rootLayerCanvasSize;
 
-    IntRect m_visibleRect;
+    IntRect m_rootVisibleRect;
 
     int m_maxTextureSize;
 
+    int m_numStencilBits;
+
     // Store values that are shared between instances of each layer type
     // associated with this instance of the compositor. Since there can be
     // multiple instances of the compositor running in the same renderer process

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list