Skip to content

Instantly share code, notes, and snippets.

@noamr
Created April 9, 2013 12:51
Show Gist options
  • Save noamr/5345472 to your computer and use it in GitHub Desktop.
Save noamr/5345472 to your computer and use it in GitHub Desktop.
commit 9d43fe8d9d79a4d7b7c9cc4953aa465df8a26ed2
Author: Noam Rosenthal <[email protected]>
Date: Tue Apr 9 14:50:43 2013 +0200
WIP overlap clipping
diff --git a/LayoutTests/compositing/overlap-blending/nested-overlap-outline.html b/LayoutTests/compositing/overlap-blending/nested-overlap-outline.html
new file mode 100644
index 0000000..4c14f0a
--- /dev/null
+++ b/LayoutTests/compositing/overlap-blending/nested-overlap-outline.html
@@ -0,0 +1,26 @@
+<html>
+ <head>
+ <style>
+ div {
+ opacity: 0.5;
+ -webkit-transform: translateZ(0);
+ border-radius: 10px;
+ outline: solid 5px green;
+ width: 60%;
+ height: 50%;
+ margin: 0;
+ }
+
+ body > div {
+ width: 500px; height: 500px;
+ }
+ </style>
+ </head>
+ <body>
+ <div>
+ <div>
+ <div></div>
+ </div>
+ </div>
+ </body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/compositing/overlap-blending/nested-overlap-overflow.html b/LayoutTests/compositing/overlap-blending/nested-overlap-overflow.html
new file mode 100644
index 0000000..5186725
--- /dev/null
+++ b/LayoutTests/compositing/overlap-blending/nested-overlap-overflow.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ div {
+ opacity: 0.8;
+ -webkit-transform: translateZ(0px);
+ border-radius: 1px;
+ }
+ body > div > div > div {
+ width: 150px;
+ height: 150px;
+ margin-left: -10px;
+ position: relative;
+ top: 0;
+ background: green;
+ }
+ body > div {
+ height: 100px;
+ overflow: hidden;
+ }
+ body > div > div {
+ width: 200px;
+ height: 200px;
+ position: absolute;
+ }
+ </style>
+ </head>
+ <body>
+ <div>
+ <div>
+ <div></div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/LayoutTests/compositing/overlap-blending/nested-overlap.html b/LayoutTests/compositing/overlap-blending/nested-overlap.html
new file mode 100644
index 0000000..1c0222f
--- /dev/null
+++ b/LayoutTests/compositing/overlap-blending/nested-overlap.html
@@ -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>
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
index 3142015..7621595 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
@@ -179,6 +179,7 @@ TextureMapperGLData::~TextureMapperGLData()
void TextureMapperGL::ClipStack::reset(const IntRect& rect)
{
clipStack.clear();
+ size = rect.size();
clipState = TextureMapperGL::ClipState(rect);
clipStateDirty = true;
}
@@ -210,19 +211,13 @@ void TextureMapperGL::ClipStack::pop()
clipStateDirty = true;
}
-static void scissorClip(GraphicsContext3D* context, const IntRect& rect)
-{
- if (rect.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);
+ if (clipState.scissorBox.isEmpty())
+ context->scissor(0, 0, size.width(), size.height());
+ else
+ context->scissor(clipState.scissorBox.x(), size.height() - clipState.scissorBox.maxY(), 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)
@@ -233,6 +228,7 @@ void TextureMapperGL::ClipStack::apply(GraphicsContext3D* context)
void TextureMapperGL::ClipStack::applyIfNeeded(GraphicsContext3D* context)
{
+ clipStateDirty = true;
if (!clipStateDirty)
return;
@@ -240,7 +236,6 @@ void TextureMapperGL::ClipStack::applyIfNeeded(GraphicsContext3D* context)
apply(context);
}
-
void TextureMapperGLData::initializeStencil()
{
if (currentSurface) {
@@ -1075,7 +1070,7 @@ void BitmapTextureGL::bind(TextureMapperGL* textureMapper)
m_context3D->viewport(0, 0, m_textureSize.width(), m_textureSize.height());
clearIfNeeded();
textureMapper->data().projectionMatrix = createProjectionMatrix(m_textureSize, true /* mirrored */);
- m_clipStack.applyIfNeeded(m_context3D.get());
+ m_clipStack.apply(m_context3D.get());
}
BitmapTextureGL::~BitmapTextureGL()
@@ -1136,14 +1131,11 @@ bool TextureMapperGL::beginScissorClip(const TransformationMatrix& modelViewMatr
if (!modelViewMatrix.isAffine())
return false;
- FloatQuad quad = modelViewMatrix.projectQuad(targetRect);
- IntRect rect = quad.enclosingBoundingBox();
-
- // Only use scissors on rectilinear clips.
- if (!quad.isRectilinear() || rect.isEmpty())
+ FloatRect rect = modelViewMatrix.mapRect(targetRect);
+ if (rect.isEmpty() || !rect.isExpressibleAsIntRect())
return false;
- clipStack().intersect(rect);
+ clipStack().intersect(IntRect(rect));
clipStack().applyIfNeeded(m_context3D.get());
return true;
}
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
index e7d7982..086bacd 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
@@ -115,6 +115,7 @@ private:
ClipState clipState;
Vector<ClipState> clipStack;
bool clipStateDirty;
+ IntSize size;
};
TextureMapperGL();
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
index 61e975f..d5df3ae 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
@@ -157,8 +157,13 @@ void TextureMapperLayer::paintSelfAndChildren(const TextureMapperPaintOptions& o
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);
@@ -335,13 +340,9 @@ void TextureMapperLayer::paintUsingOverlapRegions(const TextureMapperPaintOption
return;
}
- Vector<IntRect> rects = nonOverlapRegion.rects();
- for (size_t i = 0; i < rects.size(); ++i) {
- options.textureMapper->beginClip(TransformationMatrix(), rects[i]);
- paintSelfAndChildrenWithReplica(options);
- options.textureMapper->endClip();
- }
+ Vector<IntRect> rects;
+ nonOverlapRegion.translate(options.offset);
rects = overlapRegion.rects();
IntSize maxTextureSize = options.textureMapper->maxTextureSize();
for (size_t i = 0; i < rects.size(); ++i) {
@@ -354,6 +355,14 @@ void TextureMapperLayer::paintUsingOverlapRegions(const TextureMapperPaintOption
}
}
}
+
+ rects = nonOverlapRegion.rects();
+ for (size_t i = 0; i < rects.size(); ++i) {
+ options.textureMapper->beginClip(TransformationMatrix(), rects[i]);
+ paintSelfAndChildrenWithReplica(options);
+ options.textureMapper->endClip();
+ }
+
}
void TextureMapperLayer::applyMask(const TextureMapperPaintOptions& options)
@@ -366,8 +375,10 @@ void TextureMapperLayer::applyMask(const TextureMapperPaintOptions& options)
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)
@@ -378,14 +389,14 @@ PassRefPtr<BitmapTexture> TextureMapperLayer::paintIntoSurface(const TextureMapp
return surface;
}
-static PassRefPtr<BitmapTexture> commitSurface(const TextureMapperPaintOptions& options, PassRefPtr<BitmapTexture> surface, const IntRect& rect, float opacity)
+static void commitSurface(const TextureMapperPaintOptions& options, PassRefPtr<BitmapTexture> surface, const IntRect& rect, float opacity)
{
options.textureMapper->bindSurface(options.surface.get());
TransformationMatrix targetTransform;
targetTransform.translate(options.offset.width(), options.offset.height());
targetTransform.multiply(options.transform);
options.textureMapper->drawTexture(*surface.get(), rect, targetTransform, opacity);
- return 0;
+ options.textureMapper->drawBorder(Color(255, 0, 0, 255), 5, rect, targetTransform);
}
void TextureMapperLayer::paintWithIntermediateSurface(const TextureMapperPaintOptions& options, const IntRect& rect)
@@ -404,8 +415,10 @@ void TextureMapperLayer::paintWithIntermediateSurface(const TextureMapperPaintOp
m_state.replicaLayer->m_state.maskLayer->applyMask(paintOptions);
}
- if (replicaSurface && options.opacity == 1)
- replicaSurface = commitSurface(options, replicaSurface, rect, 1);
+ if (replicaSurface && options.opacity == 1) {
+ commitSurface(options, replicaSurface, rect, 1);
+ replicaSurface.clear();
+ }
mainSurface = paintIntoSurface(paintOptions, rect.size());
if (replicaSurface) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment