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