[Texmap] Use glScissors for clipping in TextureMapperGL when possible
authornoam.rosenthal@nokia.com <noam.rosenthal@nokia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Feb 2012 02:42:14 +0000 (02:42 +0000)
committernoam.rosenthal@nokia.com <noam.rosenthal@nokia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Feb 2012 02:42:14 +0000 (02:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=77575

Reviewed by Martin Robinson.

Source/WebCore:

Maintain a clipping stack, that helps us use stencils in conjunction with scissors.
We apply scissors when the clip region is rectalinear, and stencil when it's not.

No behavior changes so no new tests.

* platform/graphics/opengl/TextureMapperGL.cpp:
(SharedGLData):
(WebCore::TextureMapperGLData::SharedGLData::SharedGLData):
(WebCore::TextureMapperGL::drawTexture):
(WebCore::TextureMapperGL::bindSurface):
(WebCore):
(WebCore::scissorClip):
(WebCore::TextureMapperGL::beginScissorClip):
(WebCore::TextureMapperGL::endScissorClip):
(WebCore::TextureMapperGL::beginClip):
(WebCore::TextureMapperGL::endClip):
* platform/graphics/opengl/TextureMapperGL.h:
(TextureMapperGL):

Source/WebKit2:

Instead of applying the scissor clip in QQuickWebPage, we trickle it down to
TextureMapperGL, and apply it there as part of beginClip(). All direct GL operations are
now cleaned out of QQuickWebPage.

* UIProcess/API/qt/qquickwebpage.cpp:
(QQuickWebPagePrivate::paintToCurrentGLContext):
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::paintToCurrentGLContext):
* UIProcess/DrawingAreaProxyImpl.cpp:
(WebKit::DrawingAreaProxyImpl::paintToCurrentGLContext):
* UIProcess/DrawingAreaProxyImpl.h:
(DrawingAreaProxyImpl):
* UIProcess/LayerTreeHostProxy.h:
(LayerTreeHostProxy):
* UIProcess/qt/LayerTreeHostProxyQt.cpp:
(WebKit::LayerTreeHostProxy::paintToCurrentGLContext):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@106524 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp
Source/WebCore/platform/graphics/opengl/TextureMapperGL.h
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp
Source/WebKit2/UIProcess/DrawingAreaProxy.h
Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp
Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h
Source/WebKit2/UIProcess/LayerTreeHostProxy.h
Source/WebKit2/UIProcess/qt/LayerTreeHostProxyQt.cpp

index 925c48c..1fbcd69 100644 (file)
@@ -1,3 +1,29 @@
+2012-02-01  No'am Rosenthal  <noam.rosenthal@nokia.com>
+
+        [Texmap] Use glScissors for clipping in TextureMapperGL when possible
+        https://bugs.webkit.org/show_bug.cgi?id=77575
+
+        Reviewed by Martin Robinson.
+
+        Maintain a clipping stack, that helps us use stencils in conjunction with scissors.
+        We apply scissors when the clip region is rectalinear, and stencil when it's not.
+
+        No behavior changes so no new tests.
+
+        * platform/graphics/opengl/TextureMapperGL.cpp:
+        (SharedGLData):
+        (WebCore::TextureMapperGLData::SharedGLData::SharedGLData):
+        (WebCore::TextureMapperGL::drawTexture):
+        (WebCore::TextureMapperGL::bindSurface):
+        (WebCore):
+        (WebCore::scissorClip):
+        (WebCore::TextureMapperGL::beginScissorClip):
+        (WebCore::TextureMapperGL::endScissorClip):
+        (WebCore::TextureMapperGL::beginClip):
+        (WebCore::TextureMapperGL::endClip):
+        * platform/graphics/opengl/TextureMapperGL.h:
+        (TextureMapperGL):
+
 2012-02-01  Anders Carlsson  <andersca@apple.com>
 
         Move the scrolling coordinator to page/scrolling
index de041bf..ddff605 100644 (file)
@@ -238,8 +238,10 @@ struct TextureMapperGLData {
         ProgramInfo programs[ProgramCount];
 
         int stencilIndex;
+        Vector<IntRect> clipStack;
 
-        SharedGLData(GLContext glContext) : stencilIndex(1)
+        SharedGLData(GLContext glContext)
+            : stencilIndex(1)
         {
             glContextDataMap().add(glContext, this);
             initializeShaders();
@@ -321,12 +323,15 @@ struct TextureMapperGLData {
 
     TextureMapperGLData()
         : currentProgram(SharedGLData::NoProgram)
+        , previousProgram(0)
+        , previousScissorState(0)
         , m_sharedGLData(TextureMapperGLData::SharedGLData::currentSharedGLData())
     { }
 
     TransformationMatrix projectionMatrix;
     int currentProgram;
-    int previousProgram;
+    GLint previousProgram;
+    GLint previousScissorState;
     RefPtr<SharedGLData> m_sharedGLData;
 };
 
@@ -520,28 +525,40 @@ void TextureMapperGLData::SharedGLData::initializeShaders()
 
 void TextureMapperGL::beginPainting()
 {
-#if PLATFORM(QT)
+    // Make sure that no GL error code stays from previous operations.
+    glGetError();
+
     if (!initializeOpenGLShims())
         return;
 
-    glGetIntegerv(GL_CURRENT_PROGRAM, &m_data->previousProgram);
+    glGetIntegerv(GL_CURRENT_PROGRAM, &data().previousProgram);
+    data().previousScissorState = glIsEnabled(GL_SCISSOR_TEST);
+
+    glEnable(GL_SCISSOR_TEST);
+#if PLATFORM(QT)
     if (m_context) {
         QPainter* painter = m_context->platformContext();
         painter->save();
         painter->beginNativePainting();
     }
+#endif
     glClearStencil(0);
     glClear(GL_STENCIL_BUFFER_BIT);
     bindSurface(0);
-#endif
 }
 
 void TextureMapperGL::endPainting()
 {
-#if PLATFORM(QT)
     glClearStencil(1);
     glClear(GL_STENCIL_BUFFER_BIT);
-    glUseProgram(m_data->previousProgram);
+    glUseProgram(data().previousProgram);
+
+    if (data().previousScissorState)
+        glEnable(GL_SCISSOR_TEST);
+    else
+        glDisable(GL_SCISSOR_TEST);
+
+#if PLATFORM(QT)
     if (!m_context)
         return;
     QPainter* painter = m_context->platformContext();
@@ -620,6 +637,7 @@ void TextureMapperGL::drawTexture(uint32_t texture, bool opaque, const FloatSize
     }
 
     GL_CMD(glDisable(GL_DEPTH_TEST))
+
     GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4))
     GL_CMD(glDisableVertexAttribArray(programInfo.vertexAttrib))
 }
@@ -815,7 +833,6 @@ void BitmapTextureGL::bind()
     glStencilFunc(stencilIndex > 1 ? GL_GEQUAL : GL_ALWAYS, stencilIndex - 1, stencilIndex - 1);
     GL_CMD(glViewport(0, 0, size().width(), size().height()))
     m_textureMapper->data().projectionMatrix = createProjectionMatrix(size(), false);
-    glDisable(GL_SCISSOR_TEST);
 }
 
 void BitmapTextureGL::destroy()
@@ -860,14 +877,58 @@ void TextureMapperGL::bindSurface(BitmapTexture *surfacePointer)
         GL_CMD(glStencilFunc(data().sharedGLData().stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, data().sharedGLData().stencilIndex - 1, data().sharedGLData().stencilIndex - 1))
         GL_CMD(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP))
         GL_CMD(glViewport(0, 0, viewportSize().width(), viewportSize().height()))
+        data().sharedGLData().clipStack.append(IntRect(IntPoint::zero(), viewportSize()));
         return;
     }
 
     surface->bind();
 }
 
+static void scissorClip(const IntRect& rect)
+{
+    GLint viewport[4];
+    glGetIntegerv(GL_VIEWPORT, viewport);
+    glScissor(rect.x(), viewport[3] - rect.maxY(), rect.width(), rect.height());
+}
+
+bool TextureMapperGL::beginScissorClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
+{
+    FloatQuad quad = modelViewMatrix.projectQuad(targetRect);
+    IntRect rect = quad.enclosingBoundingBox();
+
+    // Only use scissors on rectilinear clips.
+    if (!quad.isRectilinear() || rect.isEmpty()) {
+        data().sharedGLData().clipStack.append(IntRect());
+        return false;
+    }
+
+    // Intersect with previous clip.
+    if (!data().sharedGLData().clipStack.isEmpty())
+        rect.intersect(data().sharedGLData().clipStack.last());
+
+    scissorClip(rect);
+    data().sharedGLData().clipStack.append(rect);
+
+    return true;
+}
+
+bool TextureMapperGL::endScissorClip()
+{
+    data().sharedGLData().clipStack.removeLast();
+    ASSERT(!data().sharedGLData().clipStack.isEmpty());
+
+    IntRect rect = data().sharedGLData().clipStack.last();
+    if (rect.isEmpty())
+        return false;
+
+    scissorClip(rect);
+    return true;
+}
+
 void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, const FloatRect& targetRect)
 {
+    if (beginScissorClip(modelViewMatrix, targetRect))
+        return;
     TextureMapperGLData::SharedGLData::ShaderProgramIndex program = TextureMapperGLData::SharedGLData::ClipProgram;
     const TextureMapperGLData::SharedGLData::ProgramInfo& programInfo = data().sharedGLData().programs[program];
     GL_CMD(glUseProgram(programInfo.id))
@@ -905,8 +966,16 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con
 
 void TextureMapperGL::endClip()
 {
+    if (endScissorClip())
+        return;
+
     data().sharedGLData().stencilIndex >>= 1;
-    glStencilFunc(data().sharedGLData().stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, data().sharedGLData().stencilIndex - 1, data().sharedGLData().stencilIndex - 1);
+    glStencilFunc(data().sharedGLData().stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, data().sharedGLData().stencilIndex - 1, data().sharedGLData().stencilIndex - 1);    
+
+    // After we've cleared the last non-rectalinear clip, we disable the stencil test.
+    if (data().sharedGLData().stencilIndex == 1)
+        GL_CMD(glDisable(GL_STENCIL_TEST))
+
 }
 
 PassRefPtr<BitmapTexture> TextureMapperGL::createTexture()
index dd2e1a7..1b41185 100644 (file)
@@ -55,6 +55,8 @@ public:
     virtual bool isOpenGLBacked() const { return true; }
 
 private:
+    bool beginScissorClip(const TransformationMatrix&, const FloatRect&);
+    bool endScissorClip();
     inline TextureMapperGLData& data() { return *m_data; }
     TextureMapperGLData* m_data;
     GraphicsContext* m_context;
index d4bca9c..65cc509 100644 (file)
@@ -1,3 +1,27 @@
+2012-02-01  No'am Rosenthal  <noam.rosenthal@nokia.com>
+
+        [Texmap] Use glScissors for clipping in TextureMapperGL when possible
+        https://bugs.webkit.org/show_bug.cgi?id=77575
+
+        Reviewed by Martin Robinson.
+
+        Instead of applying the scissor clip in QQuickWebPage, we trickle it down to
+        TextureMapperGL, and apply it there as part of beginClip(). All direct GL operations are
+        now cleaned out of QQuickWebPage.
+
+        * UIProcess/API/qt/qquickwebpage.cpp:
+        (QQuickWebPagePrivate::paintToCurrentGLContext):
+        * UIProcess/DrawingAreaProxy.h:
+        (WebKit::DrawingAreaProxy::paintToCurrentGLContext):
+        * UIProcess/DrawingAreaProxyImpl.cpp:
+        (WebKit::DrawingAreaProxyImpl::paintToCurrentGLContext):
+        * UIProcess/DrawingAreaProxyImpl.h:
+        (DrawingAreaProxyImpl):
+        * UIProcess/LayerTreeHostProxy.h:
+        (LayerTreeHostProxy):
+        * UIProcess/qt/LayerTreeHostProxyQt.cpp:
+        (WebKit::LayerTreeHostProxy::paintToCurrentGLContext):
+
 2012-02-01  Dan Bernstein  <mitz@apple.com>
 
         WebKit2 part of <rdar://problem/10442663> Paginated display does not respect page-break-{before,after}
index 6976f87..206ba25 100644 (file)
@@ -124,23 +124,7 @@ void QQuickWebPagePrivate::paintToCurrentGLContext()
     if (!drawingArea)
         return;
 
-    // Make sure that no GL error code stays from previous QT operations.
-    glGetError();
-
-    glEnable(GL_SCISSOR_TEST);
-    ASSERT(!glGetError());
-    const int left = clipRect.left();
-    const int width = clipRect.width();
-    const int bottom = q->canvas()->height() - (clipRect.bottom() + 1);
-    const int height = clipRect.height();
-
-    glScissor(left, bottom, width, height);
-    ASSERT(!glGetError());
-
-    drawingArea->paintToCurrentGLContext(transform, opacity);
-
-    glDisable(GL_SCISSOR_TEST);
-    ASSERT(!glGetError());
+    drawingArea->paintToCurrentGLContext(transform, opacity, clipRect);
 }
 
 struct PageProxyMaterial;
index ac711f6..617c175 100644 (file)
@@ -88,7 +88,7 @@ public:
     virtual WebCore::IntRect viewportVisibleRect() const { return contentsRect(); }
     virtual WebCore::IntRect contentsRect() const;
     virtual bool isBackingStoreReady() const { return true; }
-    virtual void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float opacity) { }
+    virtual void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float, const WebCore::FloatRect&) { }
     virtual void paintLayerTree(BackingStore::PlatformGraphicsContext) { }
     LayerTreeHostProxy* layerTreeHostProxy() const { return m_layerTreeHostProxy.get(); }
 
index 0e3bdb6..24a5aed 100644 (file)
@@ -366,10 +366,10 @@ void DrawingAreaProxyImpl::paintLayerTree(BackingStore::PlatformGraphicsContext
         m_layerTreeHostProxy->paintToGraphicsContext(context);
 }
 
-void DrawingAreaProxyImpl::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity)
+void DrawingAreaProxyImpl::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect)
 {
     if (m_layerTreeHostProxy)
-        m_layerTreeHostProxy->paintToCurrentGLContext(matrix, opacity);
+        m_layerTreeHostProxy->paintToCurrentGLContext(matrix, opacity, clipRect);
 }
 #endif
 
index 22f97a5..5fcf24c 100644 (file)
@@ -80,7 +80,7 @@ private:
 #if USE(TILED_BACKING_STORE)
     virtual void setVisibleContentsRectAndScale(const WebCore::IntRect& visibleContentsRect, float scale);
     virtual void setVisibleContentRectTrajectoryVector(const WebCore::FloatPoint&);
-    virtual void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float opacity);
+    virtual void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float opacity, const WebCore::FloatRect&);
     virtual void paintLayerTree(BackingStore::PlatformGraphicsContext);
     void didReceiveLayerTreeHostProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
 #endif
index f5afa96..4c97187 100644 (file)
@@ -52,7 +52,7 @@ public:
     void deleteCompositingLayer(WebLayerID);
     void setRootCompositingLayer(WebLayerID);
     void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
-    void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float);
+    void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float, const WebCore::FloatRect&);
     void paintToGraphicsContext(BackingStore::PlatformGraphicsContext);
     void purgeGLResources();
     void setVisibleContentsRectAndScale(const WebCore::IntRect&, float);
index 1f6065e..8969bbb 100644 (file)
@@ -168,7 +168,7 @@ LayerTreeHostProxy::~LayerTreeHostProxy()
 }
 
 // This function needs to be reentrant.
-void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity)
+void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect)
 {
     if (!m_textureMapper)
         m_textureMapper = TextureMapperGL::create();
@@ -190,6 +190,7 @@ void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& mat
     node->setTextureMapper(m_textureMapper.get());
     m_textureMapper->beginPainting();
     m_textureMapper->bindSurface(0);
+    m_textureMapper->beginClip(TransformationMatrix(), clipRect);
 
     if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) {
         currentRootLayer->setOpacity(opacity);
@@ -198,6 +199,7 @@ void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& mat
     }
 
     node->paint();
+    m_textureMapper->endClip();
     m_textureMapper->endPainting();
 
     if (node->descendantsOrSelfHaveRunningAnimations()) {