[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