Title: [113325] trunk/Source/WebKit/blackberry
Revision
113325
Author
[email protected]
Date
2012-04-05 08:57:12 -0700 (Thu, 05 Apr 2012)

Log Message

[BlackBerry] Force compositing mode when backing store is not active
https://bugs.webkit.org/show_bug.cgi?id=83131

Patch by Arvid Nilsson <[email protected]> on 2012-04-05
Reviewed by George Staikos.

RIM PR: 136381
Normally, the BlackBerry WebKit port resorts to direct rendering when
the backing store is not active. However, direct rendering is broken
with the OpenGL code path. This prevented multiple web pages from being
displayed at once with the new WebPageCompositor API.

Fixed by using accelerated compositing layer to render the root layer
instead of backing store. This will give us a tiled layer backing the
root layer, which for some use cases is even better than direct
rendering.

Reviewed internally by Filip Spacek.

* Api/BackingStore.cpp:
(BlackBerry::WebKit::BackingStorePrivate::shouldDirectRenderingToWindow):
(BlackBerry::WebKit::BackingStorePrivate::blitContents):
* Api/WebPage.cpp:
(BlackBerry::WebKit::WebPagePrivate::setLoadState):
(BlackBerry::WebKit::WebPage::setVisible):
(BlackBerry::WebKit::WebPagePrivate::suspendBackingStore):
(BlackBerry::WebKit::WebPagePrivate::resumeBackingStore):
(BlackBerry::WebKit::WebPagePrivate::compositorDrawsRootLayer):
(WebKit):
(BlackBerry::WebKit::WebPagePrivate::setCompositorDrawsRootLayer):
(BlackBerry::WebKit::WebPagePrivate::drawLayersOnCommit):
(BlackBerry::WebKit::WebPagePrivate::scheduleRootLayerCommit):
(BlackBerry::WebKit::WebPagePrivate::commitRootLayer):
(BlackBerry::WebKit::WebPagePrivate::commitRootLayerIfNeeded):
(BlackBerry::WebKit::WebPagePrivate::rootLayerCommitTimerFired):
(BlackBerry::WebKit::WebPagePrivate::setRootLayerCompositingThread):
(BlackBerry::WebKit::WebPagePrivate::createCompositor):
(BlackBerry::WebKit::WebPagePrivate::suspendRootLayerCommit):
(BlackBerry::WebKit::WebPagePrivate::setNeedsOneShotDrawingSynchronization):
* Api/WebPageCompositor.cpp:
(BlackBerry::WebKit::WebPageCompositorPrivate::WebPageCompositorPrivate):
(BlackBerry::WebKit::WebPageCompositorPrivate::drawsRootLayer):
(WebKit):
(BlackBerry::WebKit::WebPageCompositorPrivate::drawLayers):
* Api/WebPageCompositor_p.h:
(BlackBerry::WebKit::WebPageCompositorPrivate::rootLayer):
(WebPageCompositorPrivate):
(BlackBerry::WebKit::WebPageCompositorPrivate::setDrawsRootLayer):
* Api/WebPage_p.h:
(WebPagePrivate):

Modified Paths

Diff

Modified: trunk/Source/WebKit/blackberry/Api/BackingStore.cpp (113324 => 113325)


--- trunk/Source/WebKit/blackberry/Api/BackingStore.cpp	2012-04-05 15:51:41 UTC (rev 113324)
+++ trunk/Source/WebKit/blackberry/Api/BackingStore.cpp	2012-04-05 15:57:12 UTC (rev 113325)
@@ -243,9 +243,21 @@
 
 bool BackingStorePrivate::shouldDirectRenderingToWindow() const
 {
-    if (m_webPage->settings()->isDirectRenderingToWindowEnabled() || !isActive())
+    // Direct rendering doesn't work with OpenGL compositing code paths due to
+    // a race condition on which thread's EGL context gets to make the surface
+    // current, see PR 105750.
+    // As a workaround, we will be using compositor to draw the root layer.
+    if (isOpenGLCompositing())
+        return false;
+
+    if (m_webPage->settings()->isDirectRenderingToWindowEnabled())
         return true;
 
+    // If the BackingStore is inactive, see if there's a compositor to do the
+    // work of rendering the root layer.
+    if (!isActive())
+        return !m_webPage->d->compositorDrawsRootLayer();
+
     const BackingStoreGeometry* currentState = frontState();
     const unsigned tilesNecessary = minimumNumberOfTilesWide() * minimumNumberOfTilesHigh();
     const unsigned tilesAvailable = currentState->numberOfTilesWide() * currentState->numberOfTilesHigh();
@@ -1222,7 +1234,7 @@
     if (shouldDirectRenderingToWindow())
         return;
 
-    if (!m_webPage->isVisible() || m_suspendScreenUpdates || !isActive()) {
+    if (!m_webPage->isVisible() || m_suspendScreenUpdates) {
         // Avoid client going into busy loop while blit is impossible.
         if (force)
             m_hasBlitJobs = false;
@@ -1258,7 +1270,6 @@
 
     m_hasBlitJobs = false;
 
-    BackingStoreGeometry* currentState = frontState();
     const Platform::IntRect contentsRect = Platform::IntRect(Platform::IntPoint(0, 0), m_client->transformedContentsSize());
 
 #if DEBUG_VISUALIZE
@@ -1267,7 +1278,7 @@
     // can visualize the entire backingstore and what it is doing when we
     // scroll and zoom!
     // FIXME: This should not explicitely depend on WebCore::.
-    WebCore::IntRect debugRect = currentState->backingStoreRect();
+    WebCore::IntRect debugRect = frontState()->backingStoreRect();
     debugRect.unite(m_webPage->client()->userInterfaceBlittedVisibleContentsRect());
     if (debugRect.width() < debugRect.height())
         debugRect.setWidth(ceil(double(srcRect.width()) * (double(debugRect.height()) / srcRect.height())));
@@ -1283,8 +1294,6 @@
     if (!contents.isEmpty())
         transformation = TransformationMatrix::rectToRect(FloatRect(FloatPoint(0.0, 0.0), WebCore::IntSize(contents.size())), WebCore::IntRect(dstRect));
 
-    bool blittingDirectlyToCompositingWindow = isOpenGLCompositing();
-
 #if DEBUG_BACKINGSTORE
     BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical,
                            "BackingStorePrivate::blitContents dstRect=(%d,%d %dx%d) srcRect=(%d,%d %dx%d)",
@@ -1295,161 +1304,168 @@
     Platform::IntPoint origin = contents.location();
     Platform::IntRect contentsClipped = contents;
 
-    paintDefaultBackground(contents, transformation, false /*flush*/);
+    Vector<TileBuffer*> blittedTiles;
 
-    TileMap currentMap = currentState->tileMap();
+    if (isActive() && !m_webPage->d->compositorDrawsRootLayer()) {
+        paintDefaultBackground(contents, transformation, false /*flush*/);
 
+        BackingStoreGeometry* currentState = frontState();
+        TileMap currentMap = currentState->tileMap();
+
 #if DEBUG_CHECKERBOARD
-    bool blitCheckered = false;
+        bool blitCheckered = false;
 #endif
 
-    // Don't clip to contents if it is empty so we can still paint default background.
-    if (!contentsRect.isEmpty()) {
-        contentsClipped.intersect(contentsRect);
-        if (contentsClipped.isEmpty()) {
-            invalidateWindow(dstRect);
-            return;
-        }
+        // Don't clip to contents if it is empty so we can still paint default background.
+        if (!contentsRect.isEmpty()) {
+            contentsClipped.intersect(contentsRect);
+            if (contentsClipped.isEmpty()) {
+                invalidateWindow(dstRect);
+                return;
+            }
 
-        Platform::IntRectRegion contentsRegion = contentsClipped;
-        Platform::IntRectRegion backingStoreRegion = currentState->backingStoreRect();
-        Platform::IntRectRegion checkeredRegion
-            = Platform::IntRectRegion::subtractRegions(contentsRegion, backingStoreRegion);
+            Platform::IntRectRegion contentsRegion = contentsClipped;
+            Platform::IntRectRegion backingStoreRegion = currentState->backingStoreRect();
+            Platform::IntRectRegion checkeredRegion
+                = Platform::IntRectRegion::subtractRegions(contentsRegion, backingStoreRegion);
 
-        // Blit checkered to those parts that are not covered by the backingStoreRect.
-        IntRectList checkeredRects = checkeredRegion.rects();
-        for (size_t i = 0; i < checkeredRects.size(); ++i) {
-            Platform::IntRect dstRect = transformation.mapRect(Platform::IntRect(
-                Platform::IntPoint(checkeredRects.at(i).x() - origin.x(), checkeredRects.at(i).y() - origin.y()),
-                                   checkeredRects.at(i).size()));
+            // Blit checkered to those parts that are not covered by the backingStoreRect.
+            IntRectList checkeredRects = checkeredRegion.rects();
+            for (size_t i = 0; i < checkeredRects.size(); ++i) {
+                Platform::IntRect dstRect = transformation.mapRect(Platform::IntRect(
+                    Platform::IntPoint(checkeredRects.at(i).x() - origin.x(), checkeredRects.at(i).y() - origin.y()),
+                                       checkeredRects.at(i).size()));
 #if DEBUG_CHECKERBOARD
-            blitCheckered = true;
+                blitCheckered = true;
 #endif
-            checkerWindow(dstRect, checkeredRects.at(i).location(), transformation.a());
+                checkerWindow(dstRect, checkeredRects.at(i).location(), transformation.a());
+            }
         }
-    }
 
-    Vector<TileBuffer*> blittedTiles;
+        // Get the list of tile rects that makeup the content.
+        TileRectList tileRectList = mapFromTransformedContentsToTiles(contentsClipped, currentState);
+        for (size_t i = 0; i < tileRectList.size(); ++i) {
+            TileRect tileRect = tileRectList[i];
+            TileIndex index = tileRect.first;
+            Platform::IntRect dirtyTileRect = tileRect.second;
+            BackingStoreTile* tile = currentMap.get(index);
+            TileBuffer* tileBuffer = tile->frontBuffer();
 
-    // Get the list of tile rects that makeup the content.
-    TileRectList tileRectList = mapFromTransformedContentsToTiles(contentsClipped, currentState);
-    for (size_t i = 0; i < tileRectList.size(); ++i) {
-        TileRect tileRect = tileRectList[i];
-        TileIndex index = tileRect.first;
-        Platform::IntRect dirtyTileRect = tileRect.second;
-        BackingStoreTile* tile = currentMap.get(index);
-        TileBuffer* tileBuffer = tile->frontBuffer();
+            // This dirty rect is in tile coordinates, but it needs to be in
+            // transformed contents coordinates.
+            Platform::IntRect dirtyRect
+                = mapFromTilesToTransformedContents(tileRect, currentState->backingStoreRect());
 
-        // This dirty rect is in tile coordinates, but it needs to be in
-        // transformed contents coordinates.
-        Platform::IntRect dirtyRect
-            = mapFromTilesToTransformedContents(tileRect, currentState->backingStoreRect());
+            // Don't clip to contents if it is empty so we can still paint default background.
+            if (!contentsRect.isEmpty()) {
+                // Otherwise we should clip the contents size and blit.
+                dirtyRect.intersect(contentsRect);
 
-        // Don't clip to contents if it is empty so we can still paint default background.
-        if (!contentsRect.isEmpty()) {
-            // Otherwise we should clip the contents size and blit.
-            dirtyRect.intersect(contentsRect);
+                // We probably have extra tiles since the contents size is so small.
+                // Save some cycles here...
+                if (dirtyRect.isEmpty())
+                    continue;
+            }
 
-            // We probably have extra tiles since the contents size is so small.
+            // Now, this dirty rect is in transformed coordinates relative to the
+            // transformed contents, but ultimately it needs to be transformed
+            // coordinates relative to the viewport.
+            dirtyRect.move(-origin.x(), -origin.y());
+
             // Save some cycles here...
-            if (dirtyRect.isEmpty())
+            if (dirtyRect.isEmpty() || dirtyTileRect.isEmpty())
                 continue;
-        }
 
-        // Now, this dirty rect is in transformed coordinates relative to the
-        // transformed contents, but ultimately it needs to be transformed
-        // coordinates relative to the viewport.
-        dirtyRect.move(-origin.x(), -origin.y());
+            TileRect wholeTileRect;
+            wholeTileRect.first = index;
+            wholeTileRect.second = this->tileRect();
 
-        // Save some cycles here...
-        if (dirtyRect.isEmpty() || dirtyTileRect.isEmpty())
-            continue;
+            bool committed = tile->isCommitted();
+            bool rendered = tileBuffer->isRendered(dirtyTileRect);
+            bool paintCheckered = !committed || !rendered;
 
-        TileRect wholeTileRect;
-        wholeTileRect.first = index;
-        wholeTileRect.second = this->tileRect();
+            if (paintCheckered) {
+                Platform::IntRect dirtyRectT = transformation.mapRect(dirtyRect);
 
-        bool committed = tile->isCommitted();
-        bool rendered = tileBuffer->isRendered(dirtyTileRect);
-        bool paintCheckered = !committed || !rendered;
-
-        if (paintCheckered) {
-            Platform::IntRect dirtyRectT = transformation.mapRect(dirtyRect);
-
-            if (!transformation.isIdentity()) {
-                // Because of rounding it is possible that dirtyRect could be off-by-one larger
-                // than the surface size of the dst buffer. We prevent this here, by clamping
-                // it to ensure that can't happen.
-                dirtyRectT.intersect(Platform::IntRect(Platform::IntPoint(0, 0), surfaceSize()));
-            }
-            const Platform::IntPoint contentsOrigin(dirtyRect.x() + origin.x(), dirtyRect.y() + origin.y());
+                if (!transformation.isIdentity()) {
+                    // Because of rounding it is possible that dirtyRect could be off-by-one larger
+                    // than the surface size of the dst buffer. We prevent this here, by clamping
+                    // it to ensure that can't happen.
+                    dirtyRectT.intersect(Platform::IntRect(Platform::IntPoint(0, 0), surfaceSize()));
+                }
+                const Platform::IntPoint contentsOrigin(dirtyRect.x() + origin.x(), dirtyRect.y() + origin.y());
 #if DEBUG_CHECKERBOARD
-            blitCheckered = true;
+                blitCheckered = true;
 #endif
-            checkerWindow(dirtyRectT, contentsOrigin, transformation.a());
-        }
+                checkerWindow(dirtyRectT, contentsOrigin, transformation.a());
+            }
 
-        // Blit the visible buffer here if we have visible zoom jobs.
-        if (m_renderQueue->hasCurrentVisibleZoomJob()) {
+            // Blit the visible buffer here if we have visible zoom jobs.
+            if (m_renderQueue->hasCurrentVisibleZoomJob()) {
 
-            // Needs to be in same coordinate system as dirtyRect.
-            Platform::IntRect visibleTileBufferRect = m_visibleTileBufferRect;
-            visibleTileBufferRect.move(-origin.x(), -origin.y());
+                // Needs to be in same coordinate system as dirtyRect.
+                Platform::IntRect visibleTileBufferRect = m_visibleTileBufferRect;
+                visibleTileBufferRect.move(-origin.x(), -origin.y());
 
-            // Clip to the visibleTileBufferRect.
-            dirtyRect.intersect(visibleTileBufferRect);
+                // Clip to the visibleTileBufferRect.
+                dirtyRect.intersect(visibleTileBufferRect);
 
-            // Clip to the dirtyRect.
-            visibleTileBufferRect.intersect(dirtyRect);
+                // Clip to the dirtyRect.
+                visibleTileBufferRect.intersect(dirtyRect);
 
-            if (!dirtyRect.isEmpty() && !visibleTileBufferRect.isEmpty()) {
-                BackingStoreTile* visibleTileBuffer
-                    = SurfacePool::globalSurfacePool()->visibleTileBuffer();
-                ASSERT(visibleTileBuffer->size() == visibleContentsRect().size());
+                if (!dirtyRect.isEmpty() && !visibleTileBufferRect.isEmpty()) {
+                    BackingStoreTile* visibleTileBuffer
+                        = SurfacePool::globalSurfacePool()->visibleTileBuffer();
+                    ASSERT(visibleTileBuffer->size() == visibleContentsRect().size());
 
-                // The offset of the current viewport with the visble tile buffer.
-                Platform::IntPoint difference = origin - m_visibleTileBufferRect.location();
-                Platform::IntSize offset = Platform::IntSize(difference.x(), difference.y());
+                    // The offset of the current viewport with the visble tile buffer.
+                    Platform::IntPoint difference = origin - m_visibleTileBufferRect.location();
+                    Platform::IntSize offset = Platform::IntSize(difference.x(), difference.y());
 
-                // Map to the visibleTileBuffer coordinates.
-                Platform::IntRect dirtyTileRect = visibleTileBufferRect;
-                dirtyTileRect.move(offset.width(), offset.height());
+                    // Map to the visibleTileBuffer coordinates.
+                    Platform::IntRect dirtyTileRect = visibleTileBufferRect;
+                    dirtyTileRect.move(offset.width(), offset.height());
 
-                Platform::IntRect dirtyRectT = transformation.mapRect(dirtyRect);
+                    Platform::IntRect dirtyRectT = transformation.mapRect(dirtyRect);
 
-                if (!transformation.isIdentity()) {
-                    // Because of rounding it is possible that dirtyRect could be off-by-one larger
-                    // than the surface size of the dst buffer. We prevent this here, by clamping
-                    // it to ensure that can't happen.
-                    dirtyRectT.intersect(Platform::IntRect(Platform::IntPoint(0, 0), surfaceSize()));
+                    if (!transformation.isIdentity()) {
+                        // Because of rounding it is possible that dirtyRect could be off-by-one larger
+                        // than the surface size of the dst buffer. We prevent this here, by clamping
+                        // it to ensure that can't happen.
+                        dirtyRectT.intersect(Platform::IntRect(Platform::IntPoint(0, 0), surfaceSize()));
+                    }
+
+                    blitToWindow(dirtyRectT,
+                                 visibleTileBuffer->frontBuffer()->nativeBuffer(),
+                                 dirtyTileRect,
+                                 false /*blend*/, 255);
                 }
-
-                blitToWindow(dirtyRectT,
-                             visibleTileBuffer->frontBuffer()->nativeBuffer(),
-                             dirtyTileRect,
-                             false /*blend*/, 255);
+            } else if (committed) {
+                // Intersect the rendered region.
+                Platform::IntRectRegion renderedRegion = tileBuffer->renderedRegion();
+                IntRectList dirtyRenderedRects = renderedRegion.rects();
+                for (size_t i = 0; i < dirtyRenderedRects.size(); ++i) {
+                    TileRect tileRect;
+                    tileRect.first = index;
+                    tileRect.second = intersection(dirtyTileRect, dirtyRenderedRects.at(i));
+                    if (tileRect.second.isEmpty())
+                        continue;
+                    // Blit the rendered parts.
+                    blitTileRect(tileBuffer, tileRect, origin, transformation, currentState);
+                }
+                blittedTiles.append(tileBuffer);
             }
-        } else if (committed) {
-            // Intersect the rendered region.
-            Platform::IntRectRegion renderedRegion = tileBuffer->renderedRegion();
-            IntRectList dirtyRenderedRects = renderedRegion.rects();
-            for (size_t i = 0; i < dirtyRenderedRects.size(); ++i) {
-                TileRect tileRect;
-                tileRect.first = index;
-                tileRect.second = intersection(dirtyTileRect, dirtyRenderedRects.at(i));
-                if (tileRect.second.isEmpty())
-                    continue;
-                // Blit the rendered parts.
-                blitTileRect(tileBuffer, tileRect, origin, transformation, currentState);
-            }
-            blittedTiles.append(tileBuffer);
         }
     }
 
+    bool blittingDirectlyToCompositingWindow = isOpenGLCompositing();
+
 #if USE(ACCELERATED_COMPOSITING)
     if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor()) {
         WebCore::FloatRect contentsRect = m_webPage->d->mapFromTransformedFloatRect(WebCore::FloatRect(WebCore::IntRect(contents)));
         compositor->drawLayers(dstRect, contentsRect);
+        if (compositor->drawsRootLayer())
+            paintDefaultBackground(contents, transformation, false /*flush*/);
     }
 
     if (!blittingDirectlyToCompositingWindow)
@@ -1514,7 +1530,7 @@
 
     invalidateWindow(dstRect);
 
-    if (blittingDirectlyToCompositingWindow) {
+    if (blittingDirectlyToCompositingWindow && !blittedTiles.isEmpty()) {
         pthread_mutex_lock(&m_blitGenerationLock);
 
         ++m_blitGeneration;

Modified: trunk/Source/WebKit/blackberry/Api/WebPage.cpp (113324 => 113325)


--- trunk/Source/WebKit/blackberry/Api/WebPage.cpp	2012-04-05 15:51:41 UTC (rev 113324)
+++ trunk/Source/WebKit/blackberry/Api/WebPage.cpp	2012-04-05 15:57:12 UTC (rev 113325)
@@ -83,6 +83,8 @@
 #include "PlatformWheelEvent.h"
 #include "PluginDatabase.h"
 #include "PluginView.h"
+#include "RenderLayerBacking.h"
+#include "RenderLayerCompositor.h"
 #include "RenderText.h"
 #include "RenderThemeBlackBerry.h"
 #include "RenderTreeAsText.h"
@@ -155,6 +157,7 @@
 #define DEBUG_BLOCK_ZOOM 0
 #define DEBUG_TOUCH_EVENTS 0
 #define DEBUG_WEBPAGE_LOAD 0
+#define DEBUG_AC_COMMIT 0
 
 using namespace std;
 using namespace WebCore;
@@ -805,12 +808,8 @@
 #endif
 
 #if USE(ACCELERATED_COMPOSITING)
-            // FIXME: compositor may only be touched on the compositing thread.
-            // However, it's created/destroyed by a sync command so this is harmless.
-            if (m_compositor) {
-                m_compositor->setLayoutRectForCompositing(IntRect());
-                m_compositor->setContentsSizeForCompositing(IntSize());
-            }
+            if (isAcceleratedCompositingActive() && !compositorDrawsRootLayer())
+                syncDestroyCompositorOnCompositingThread();
 #endif
             m_previousContentsSize = IntSize();
             m_backingStore->d->resetRenderQueue();
@@ -2991,6 +2990,7 @@
         // And release layer resources can reduce memory consumption.
         d->suspendRootLayerCommit();
 #endif
+
         return;
     }
 
@@ -3188,6 +3188,15 @@
 void WebPagePrivate::suspendBackingStore()
 {
 #if USE(ACCELERATED_COMPOSITING)
+    if (m_backingStore->d->isOpenGLCompositing()) {
+        // A visible web page's backing store can be suspended when another web
+        // page is taking over the backing store.
+        if (m_visible)
+            setCompositorDrawsRootLayer(true);
+
+        return;
+    }
+
     resetCompositingSurface();
 #endif
 }
@@ -3196,10 +3205,6 @@
 {
     ASSERT(m_webPage->isVisible());
 
-#if USE(ACCELERATED_COMPOSITING)
-    setNeedsOneShotDrawingSynchronization();
-#endif
-
     bool directRendering = m_backingStore->d->shouldDirectRenderingToWindow();
     if (!m_backingStore->d->isActive()
         || shouldResetTilesWhenShown()
@@ -3207,6 +3212,12 @@
         // We need to reset all tiles so that we do not show any tiles whose content may
         // have been replaced by another WebPage instance (i.e. another tab).
         BackingStorePrivate::setCurrentBackingStoreOwner(m_webPage);
+
+        // If we're OpenGL compositing, switching to accel comp drawing of the root layer
+        // is a good substitute for backingstore blitting.
+        if (m_backingStore->d->isOpenGLCompositing())
+            setCompositorDrawsRootLayer(!m_backingStore->d->isActive());
+
         m_backingStore->d->orientationChanged(); // Updates tile geometry and creates visible tile buffer.
         m_backingStore->d->resetTiles(true /* resetBackground */);
         m_backingStore->d->updateTiles(false /* updateVisible */, false /* immediate */);
@@ -3215,10 +3226,17 @@
         if (m_backingStore->d->renderVisibleContents() && !m_backingStore->d->isSuspended() && !directRendering)
             m_backingStore->d->blitVisibleContents();
     } else {
+        if (m_backingStore->d->isOpenGLCompositing())
+           setCompositorDrawsRootLayer(false);
+
         // Rendering was disabled while we were hidden, so we need to update all tiles.
         m_backingStore->d->updateTiles(true /* updateVisible */, false /* immediate */);
     }
 
+#if USE(ACCELERATED_COMPOSITING)
+    setNeedsOneShotDrawingSynchronization();
+#endif
+
     setShouldResetTilesWhenShown(false);
 }
 
@@ -5171,7 +5189,38 @@
     d->m_page->inspectorController()->dispatchMessageFromFrontend(stringMessage);
 }
 
+bool WebPagePrivate::compositorDrawsRootLayer() const
+{
 #if USE(ACCELERATED_COMPOSITING)
+    if (Platform::userInterfaceThreadMessageClient()->isCurrentThread())
+        return m_compositor && m_compositor->drawsRootLayer();
+
+    // WebKit thread implementation:
+    RenderView* renderView = m_mainFrame->contentRenderer();
+    if (!renderView || !renderView->layer() || !renderView->layer()->backing())
+        return false;
+
+    return !renderView->layer()->backing()->paintingGoesToWindow();
+#else
+    return false;
+#endif
+}
+
+void WebPagePrivate::setCompositorDrawsRootLayer(bool compositorDrawsRootLayer)
+{
+#if USE(ACCELERATED_COMPOSITING)
+    if (m_page->settings()->forceCompositingMode() == compositorDrawsRootLayer)
+        return;
+
+    // When the BlackBerry port forces compositing mode, the root layer stops
+    // painting to window and starts painting to layer instead.
+    m_page->settings()->setForceCompositingMode(compositorDrawsRootLayer);
+    if (FrameView* view = m_mainFrame->view())
+        view->updateCompositingLayers();
+#endif
+}
+
+#if USE(ACCELERATED_COMPOSITING)
 void WebPagePrivate::drawLayersOnCommit()
 {
     if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread()) {
@@ -5179,7 +5228,7 @@
         // animations. And only if we don't need a one shot drawing sync.
         ASSERT(!needsOneShotDrawingSynchronization());
 
-        if (!m_webPage->isVisible() || !m_backingStore->d->isActive())
+        if (!m_webPage->isVisible())
             return;
 
         m_backingStore->d->willDrawLayersOnCommit();
@@ -5189,6 +5238,10 @@
         return;
     }
 
+#if DEBUG_AC_COMMIT
+    Platform::log(Platform::LogLevelCritical, "%s", WTF_PRETTY_FUNCTION);
+#endif
+
     if (!m_backingStore->d->shouldDirectRenderingToWindow())
         m_backingStore->d->blitVisibleContents();
 }
@@ -5199,8 +5252,12 @@
         return;
 
     m_needsCommit = true;
-    if (!m_rootLayerCommitTimer->isActive())
+    if (!m_rootLayerCommitTimer->isActive()) {
+#if DEBUG_AC_COMMIT
+        Platform::log(Platform::LogLevelCritical, "%s: m_rootLayerCommitTimer->isActive() = %d", WTF_PRETTY_FUNCTION, m_rootLayerCommitTimer->isActive());
+#endif
         m_rootLayerCommitTimer->startOneShot(0);
+    }
 }
 
 static bool needsLayoutRecursive(FrameView* view)
@@ -5246,18 +5303,38 @@
 }
 
 void WebPagePrivate::commitRootLayer(const IntRect& layoutRectForCompositing,
-                                     const IntSize& contentsSizeForCompositing)
+                                     const IntSize& contentsSizeForCompositing,
+                                     bool drawsRootLayer)
 {
+#if DEBUG_AC_COMMIT
+    Platform::log(Platform::LogLevelCritical, "%s: m_compositor = 0x%x",
+            WTF_PRETTY_FUNCTION, m_compositor.get());
+#endif
+
     if (!m_frameLayers || !m_compositor)
         return;
 
+    if (m_frameLayers->rootLayer() && m_frameLayers->rootLayer()->layerCompositingThread() != m_compositor->rootLayer())
+        m_compositor->setRootLayer(m_frameLayers->rootLayer()->layerCompositingThread());
+
     m_compositor->setLayoutRectForCompositing(layoutRectForCompositing);
     m_compositor->setContentsSizeForCompositing(contentsSizeForCompositing);
+    m_compositor->setDrawsRootLayer(drawsRootLayer);
     m_compositor->commit(m_frameLayers->rootLayer());
 }
 
 bool WebPagePrivate::commitRootLayerIfNeeded()
 {
+#if DEBUG_AC_COMMIT
+    Platform::log(Platform::LogLevelCritical, "%s: m_suspendRootLayerCommit = %d, m_needsCommit = %d, m_frameLayers = 0x%x, m_frameLayers->hasLayer() = %d, needsLayoutRecursive() = %d",
+            WTF_PRETTY_FUNCTION,
+            m_suspendRootLayerCommit,
+            m_needsCommit,
+            m_frameLayers.get(),
+            m_frameLayers && m_frameLayers->hasLayer(),
+            m_mainFrame && m_mainFrame->view() && needsLayoutRecursive(m_mainFrame->view()));
+#endif
+
     if (m_suspendRootLayerCommit)
         return false;
 
@@ -5297,6 +5374,7 @@
     // and that's what the layer renderer wants.
     IntRect layoutRectForCompositing(scrollPosition(), actualVisibleSize());
     IntSize contentsSizeForCompositing = contentsSize();
+    bool drawsRootLayer = compositorDrawsRootLayer();
 
     // Commit changes made to the layers synchronously with the compositing thread.
     Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage(
@@ -5304,7 +5382,8 @@
             &WebPagePrivate::commitRootLayer,
             this,
             layoutRectForCompositing,
-            contentsSizeForCompositing));
+            contentsSizeForCompositing,
+            drawsRootLayer));
 
     return true;
 }
@@ -5314,6 +5393,10 @@
     if (m_suspendRootLayerCommit)
         return;
 
+#if DEBUG_AC_COMMIT
+    Platform::log(Platform::LogLevelCritical, "%s", WTF_PRETTY_FUNCTION);
+#endif
+
     // The commit timer may have fired just before the layout timer, or for some
     // other reason we need layout. It's not allowed to commit when a layout is
     // pending, becaues a commit can cause parts of the web page to be rendered
@@ -5322,20 +5405,30 @@
     // to handle a one shot drawing synchronization after the layout.
     requestLayoutIfNeeded();
 
-    bool isSingleTargetWindow = SurfacePool::globalSurfacePool()->compositingSurface()
-        || m_backingStore->d->isOpenGLCompositing();
+    // If we transitioned to drawing the root layer using compositor instead of
+    // backing store, doing a one shot drawing synchronization with the
+    // backing store is never necessary, because the backing store draws
+    // nothing.
+    if (compositorDrawsRootLayer()) {
+        bool isSingleTargetWindow = SurfacePool::globalSurfacePool()->compositingSurface()
+            || m_backingStore->d->isOpenGLCompositing();
 
-    // If we are doing direct rendering and have a single rendering target,
-    // committing is equivalent to a one shot drawing synchronization.
-    // We need to re-render the web page, re-render the layers, and
-    // then blit them on top of the re-rendered web page.
-    if (isSingleTargetWindow && m_backingStore->d->shouldDirectRenderingToWindow())
-        setNeedsOneShotDrawingSynchronization();
+        // If we are doing direct rendering and have a single rendering target,
+        // committing is equivalent to a one shot drawing synchronization.
+        // We need to re-render the web page, re-render the layers, and
+        // then blit them on top of the re-rendered web page.
+        if (isSingleTargetWindow && m_backingStore->d->shouldDirectRenderingToWindow())
+            setNeedsOneShotDrawingSynchronization();
 
-    if (needsOneShotDrawingSynchronization()) {
-        const IntRect windowRect = IntRect(IntPoint::zero(), viewportSize());
-        m_backingStore->d->repaint(windowRect, true /*contentChanged*/, true /*immediate*/);
-        return;
+        if (needsOneShotDrawingSynchronization()) {
+#if DEBUG_AC_COMMIT
+            Platform::log(Platform::LogLevelCritical, "%s: OneShotDrawingSynchronization code path!", WTF_PRETTY_FUNCTION);
+#endif
+
+            const IntRect windowRect = IntRect(IntPoint::zero(), viewportSize());
+            m_backingStore->d->repaint(windowRect, true /*contentChanged*/, true /*immediate*/);
+            return;
+        }
     }
 
     // If the web page needs layout, the commit will fail.
@@ -5395,19 +5488,12 @@
         return;
     }
 
-    // Depending on whether we have a root layer or not,
-    // this method will turn on or off accelerated compositing.
     if (!layer) {
-         // Don't ASSERT(m_compositor) here because we may be called in
-         // the process of destruction of WebPage where we have already
-         // called syncDestroyCompositorOnCompositingThread() to destroy
-         // the compositor.
-         destroyCompositor();
-         resetCompositingSurface();
-         return;
-    }
-
-    if (!m_compositor)
+        // Keep the compositor around, a single web page will frequently enter
+        // and leave compositing mode many times. Instead we destroy it when
+        // navigating to a new page.
+        resetCompositingSurface();
+    } else if (!m_compositor)
         createCompositor();
 
     // Don't ASSERT(m_compositor) here because setIsAcceleratedCompositingActive(true)
@@ -5418,6 +5504,10 @@
 
 bool WebPagePrivate::createCompositor()
 {
+    // If there's no window, the compositor will be supplied by the API client
+    if (!m_client->window())
+        return false;
+
     m_ownedContext = GLES2Context::create(this);
     m_compositor = WebPageCompositorPrivate::create(this, 0);
     m_compositor->setContext(m_ownedContext.get());
@@ -5464,7 +5554,7 @@
 
     m_suspendRootLayerCommit = true;
 
-    if (!m_frameLayers || !m_frameLayers->hasLayer() || !m_compositor)
+    if (!m_compositor)
         return;
 
     Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage(
@@ -5490,6 +5580,11 @@
 
 void WebPagePrivate::setNeedsOneShotDrawingSynchronization()
 {
+    if (compositorDrawsRootLayer()) {
+        scheduleRootLayerCommit();
+        return;
+    }
+
     // This means we have to commit layers on next render, or render on the next commit,
     // whichever happens first.
     m_needsCommit = true;

Modified: trunk/Source/WebKit/blackberry/Api/WebPageCompositor.cpp (113324 => 113325)


--- trunk/Source/WebKit/blackberry/Api/WebPageCompositor.cpp	2012-04-05 15:51:41 UTC (rev 113324)
+++ trunk/Source/WebKit/blackberry/Api/WebPageCompositor.cpp	2012-04-05 15:57:12 UTC (rev 113325)
@@ -44,6 +44,7 @@
     : m_client(client)
     , m_webPage(page)
     , m_pendingAnimationFrame(0.0)
+    , m_drawsRootLayer(false)
 {
     setOneShot(true); // one-shot animation client
 }
@@ -107,6 +108,11 @@
     }
 }
 
+bool WebPageCompositorPrivate::drawsRootLayer() const
+{
+    return m_drawsRootLayer;
+}
+
 bool WebPageCompositorPrivate::drawLayers(const IntRect& dstRect, const FloatRect& contents)
 {
     if (!m_layerRenderer)
@@ -114,9 +120,9 @@
 
     m_pendingAnimationFrame = 0.0;
 
-    bool shouldClear = false;
+    bool shouldClear = drawsRootLayer();
     if (BackingStore* backingStore = m_webPage->m_backingStore)
-        shouldClear = !backingStore->d->isOpenGLCompositing();
+        shouldClear = shouldClear || !backingStore->d->isOpenGLCompositing();
     m_layerRenderer->setClearSurfaceOnDrawLayers(shouldClear);
 
     m_layerRenderer->drawLayers(contents, m_layoutRectForCompositing, m_contentsSizeForCompositing, dstRect);

Modified: trunk/Source/WebKit/blackberry/Api/WebPageCompositor_p.h (113324 => 113325)


--- trunk/Source/WebKit/blackberry/Api/WebPageCompositor_p.h	2012-04-05 15:51:41 UTC (rev 113324)
+++ trunk/Source/WebKit/blackberry/Api/WebPageCompositor_p.h	2012-04-05 15:57:12 UTC (rev 113325)
@@ -55,6 +55,7 @@
     Platform::Graphics::GLES2Context* context() const { return m_context; }
     void setContext(Platform::Graphics::GLES2Context*);
 
+    WebCore::LayerCompositingThread* rootLayer() const { return m_rootLayer.get(); }
     void setRootLayer(WebCore::LayerCompositingThread*);
 
     void commit(WebCore::LayerWebKitThread* rootLayerProxy);
@@ -62,7 +63,11 @@
     // This is mapped from the public API, thus takes transformed contents
     void render(const WebCore::IntRect& dstRect, const WebCore::IntRect& transformedContents);
 
-    // Render everything but the root layer
+    // Returns true if the WebPageCompositor draws the root layer, false if the BackingStore draws the root layer
+    bool drawsRootLayer() const;
+    void setDrawsRootLayer(bool drawsRootLayer) { m_drawsRootLayer = drawsRootLayer; }
+
+    // Render everything but the root layer, or everything if drawsRootLayer() is true.
     bool drawLayers(const WebCore::IntRect& dstRect, const WebCore::FloatRect& contents);
 
     WebCore::IntRect layoutRectForCompositing() const { return m_layoutRectForCompositing; }
@@ -97,6 +102,7 @@
     WebCore::IntSize m_contentsSizeForCompositing;
     WebCore::LayerRenderingResults m_lastCompositingResults;
     double m_pendingAnimationFrame;
+    bool m_drawsRootLayer;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/blackberry/Api/WebPage_p.h (113324 => 113325)


--- trunk/Source/WebKit/blackberry/Api/WebPage_p.h	2012-04-05 15:51:41 UTC (rev 113324)
+++ trunk/Source/WebKit/blackberry/Api/WebPage_p.h	2012-04-05 15:57:12 UTC (rev 113325)
@@ -356,6 +356,9 @@
         return m_transformationMatrix;
     }
 
+    bool compositorDrawsRootLayer() const; // Thread safe
+    void setCompositorDrawsRootLayer(bool); // WebKit thread only
+
 #if USE(ACCELERATED_COMPOSITING)
     // WebKit thread.
     bool needsOneShotDrawingSynchronization();
@@ -374,7 +377,7 @@
 
     // Compositing thread.
     void setRootLayerCompositingThread(WebCore::LayerCompositingThread*);
-    void commitRootLayer(const WebCore::IntRect&, const WebCore::IntSize&);
+    void commitRootLayer(const WebCore::IntRect&, const WebCore::IntSize&, bool);
     bool isAcceleratedCompositingActive() const { return m_compositor; }
     WebPageCompositorPrivate* compositor() const { return m_compositor.get(); }
     void setCompositor(PassRefPtr<WebPageCompositorPrivate>);

Modified: trunk/Source/WebKit/blackberry/ChangeLog (113324 => 113325)


--- trunk/Source/WebKit/blackberry/ChangeLog	2012-04-05 15:51:41 UTC (rev 113324)
+++ trunk/Source/WebKit/blackberry/ChangeLog	2012-04-05 15:57:12 UTC (rev 113325)
@@ -1,3 +1,55 @@
+2012-04-05  Arvid Nilsson  <[email protected]>
+
+        [BlackBerry] Force compositing mode when backing store is not active
+        https://bugs.webkit.org/show_bug.cgi?id=83131
+
+        Reviewed by George Staikos.
+
+        RIM PR: 136381
+        Normally, the BlackBerry WebKit port resorts to direct rendering when
+        the backing store is not active. However, direct rendering is broken
+        with the OpenGL code path. This prevented multiple web pages from being
+        displayed at once with the new WebPageCompositor API.
+
+        Fixed by using accelerated compositing layer to render the root layer
+        instead of backing store. This will give us a tiled layer backing the
+        root layer, which for some use cases is even better than direct
+        rendering.
+
+        Reviewed internally by Filip Spacek.
+
+        * Api/BackingStore.cpp:
+        (BlackBerry::WebKit::BackingStorePrivate::shouldDirectRenderingToWindow):
+        (BlackBerry::WebKit::BackingStorePrivate::blitContents):
+        * Api/WebPage.cpp:
+        (BlackBerry::WebKit::WebPagePrivate::setLoadState):
+        (BlackBerry::WebKit::WebPage::setVisible):
+        (BlackBerry::WebKit::WebPagePrivate::suspendBackingStore):
+        (BlackBerry::WebKit::WebPagePrivate::resumeBackingStore):
+        (BlackBerry::WebKit::WebPagePrivate::compositorDrawsRootLayer):
+        (WebKit):
+        (BlackBerry::WebKit::WebPagePrivate::setCompositorDrawsRootLayer):
+        (BlackBerry::WebKit::WebPagePrivate::drawLayersOnCommit):
+        (BlackBerry::WebKit::WebPagePrivate::scheduleRootLayerCommit):
+        (BlackBerry::WebKit::WebPagePrivate::commitRootLayer):
+        (BlackBerry::WebKit::WebPagePrivate::commitRootLayerIfNeeded):
+        (BlackBerry::WebKit::WebPagePrivate::rootLayerCommitTimerFired):
+        (BlackBerry::WebKit::WebPagePrivate::setRootLayerCompositingThread):
+        (BlackBerry::WebKit::WebPagePrivate::createCompositor):
+        (BlackBerry::WebKit::WebPagePrivate::suspendRootLayerCommit):
+        (BlackBerry::WebKit::WebPagePrivate::setNeedsOneShotDrawingSynchronization):
+        * Api/WebPageCompositor.cpp:
+        (BlackBerry::WebKit::WebPageCompositorPrivate::WebPageCompositorPrivate):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::drawsRootLayer):
+        (WebKit):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::drawLayers):
+        * Api/WebPageCompositor_p.h:
+        (BlackBerry::WebKit::WebPageCompositorPrivate::rootLayer):
+        (WebPageCompositorPrivate):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::setDrawsRootLayer):
+        * Api/WebPage_p.h:
+        (WebPagePrivate):
+
 2012-04-05  Jonathan Dong  <[email protected]>
 
         [BlackBerry] Clear local storage won't take effect until browser exit and relaunch
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to