[BlackBerry] Add WebPageCompositor class to BlackBerry WebKit API
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 24 Mar 2012 01:12:23 +0000 (01:12 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 24 Mar 2012 01:12:23 +0000 (01:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=81121
RIM PR: 136687

Patch by Arvid Nilsson <anilsson@rim.com> on 2012-03-23
Reviewed by Rob Buis.

The idea is for the API client to use a WebPageCompositor object to
render the WebPage when there's no screen window available.

The WebPageCompositorPrivate becomes reference counted in order to be
kept alive either because it's used for accelerated compositing layers
or used for the WebPageCompositor API. It can still work standalone.

Clean up some code - no need to keep track of a separate boolean
WebPagePrivate::m_isAcceleratedCompositingActive when the state of
m_compositor can tell you.

Also remove duplicated code from WebPagePrivate - go directly to the
compositor object instead, if you need to draw the AC layers.

Reviewed internally by Robin Cao and the hasBlitJobs/blitOnIdle change
by Filip Spacek.

* Api/BackingStore.cpp:
(BlackBerry::WebKit::BackingStore::hasBlitJobs):
(BlackBerry::WebKit::BackingStore::blitOnIdle):
(BlackBerry::WebKit::BackingStorePrivate::blitContents):
(BlackBerry::WebKit::BackingStorePrivate::drawSubLayers):
(BlackBerry::WebKit::BackingStorePrivate::drawAndBlendLayersForDirectRendering):
(BlackBerry::WebKit::BackingStorePrivate::surfaceSize):
(BlackBerry::WebKit::BackingStorePrivate::buffer):
* Api/WebPage.cpp:
(BlackBerry::WebKit::WebPagePrivate::WebPagePrivate):
(BlackBerry::WebKit::WebPagePrivate::drawLayersOnCommit):
(BlackBerry::WebKit::WebPagePrivate::setCompositor):
(BlackBerry::WebKit::WebPagePrivate::setRootLayerCompositingThread):
(BlackBerry::WebKit::WebPagePrivate::createCompositor):
(BlackBerry::WebKit::WebPagePrivate::destroyCompositor):
* Api/WebPage.h:
* Api/WebPageCompositor.cpp:
(BlackBerry::WebKit::WebPageCompositorPrivate::WebPageCompositorPrivate):
(BlackBerry::WebKit::WebPageCompositorPrivate::setContext):
(BlackBerry::WebKit::WebPageCompositorPrivate::hardwareCompositing):
(BlackBerry::WebKit::WebPageCompositorPrivate::setRootLayer):
(BlackBerry::WebKit::WebPageCompositorPrivate::render):
(BlackBerry::WebKit::WebPageCompositorPrivate::drawLayers):
(BlackBerry::WebKit::WebPageCompositorPrivate::animationTimerFired):
(BlackBerry::WebKit::WebPageCompositorPrivate::compositorDestroyed):
(BlackBerry::WebKit::WebPageCompositor::WebPageCompositor):
(BlackBerry::WebKit::WebPageCompositor::~WebPageCompositor):
(BlackBerry::WebKit::WebPageCompositor::client):
(BlackBerry::WebKit::WebPageCompositor::prepareFrame):
(BlackBerry::WebKit::WebPageCompositor::render):
(BlackBerry::WebKit::WebPageCompositor::cleanup):
(BlackBerry::WebKit::WebPageCompositor::contextLost):
* Api/WebPageCompositor.h: Added.
* Api/WebPageCompositorClient.h: Added.
* Api/WebPageCompositor_p.h:
(BlackBerry::WebKit::WebPageCompositorPrivate::create):
(BlackBerry::WebKit::WebPageCompositorPrivate::context):
(BlackBerry::WebKit::WebPageCompositorPrivate::animationFrameTimestamp):
(BlackBerry::WebKit::WebPageCompositorPrivate::page):
(BlackBerry::WebKit::WebPageCompositorPrivate::client):
* Api/WebPage_p.h:
(BlackBerry::WebKit::WebPagePrivate::client):
(BlackBerry::WebKit::WebPagePrivate::isAcceleratedCompositingActive):
(BlackBerry::WebKit::WebPagePrivate::compositor):

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

Source/WebKit/blackberry/Api/BackingStore.cpp
Source/WebKit/blackberry/Api/WebPage.cpp
Source/WebKit/blackberry/Api/WebPage.h
Source/WebKit/blackberry/Api/WebPageCompositor.cpp
Source/WebKit/blackberry/Api/WebPageCompositor.h [new file with mode: 0644]
Source/WebKit/blackberry/Api/WebPageCompositorClient.h [new file with mode: 0644]
Source/WebKit/blackberry/Api/WebPageCompositor_p.h
Source/WebKit/blackberry/Api/WebPage_p.h
Source/WebKit/blackberry/ChangeLog

index e5806b3..9c321ed 100644 (file)
@@ -32,6 +32,8 @@
 #include "SurfacePool.h"
 #include "WebPage.h"
 #include "WebPageClient.h"
+#include "WebPageCompositorClient.h"
+#include "WebPageCompositor_p.h"
 #include "WebPage_p.h"
 #include "WebSettings.h"
 
@@ -1240,6 +1242,16 @@ void BackingStorePrivate::blitContents(const Platform::IntRect& dstRect,
     }
 
     if (m_defersBlit && !force) {
+#if USE(ACCELERATED_COMPOSITING)
+        // If there's a WebPageCompositorClient, let it schedule the blit.
+        if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor()) {
+            if (WebPageCompositorClient* client = compositor->client()) {
+                client->invalidate(compositor->animationFrameTimestamp());
+                return;
+            }
+        }
+#endif
+
         m_hasBlitJobs = true;
         return;
     }
@@ -1445,7 +1457,8 @@ void BackingStorePrivate::blitContents(const Platform::IntRect& dstRect,
     if (blittingDirectlyToCompositingWindow) {
         WebCore::FloatRect contentsRect = m_webPage->d->mapFromTransformedFloatRect(
             WebCore::FloatRect(WebCore::IntRect(contents)));
-        m_webPage->d->drawSubLayers(dstRect, contentsRect);
+        if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor())
+            compositor->drawLayers(dstRect, contentsRect);
     } else if (compositingSurface)
         blendCompositingSurface(dstRect);
 
@@ -2519,6 +2532,9 @@ bool BackingStorePrivate::drawSubLayers()
     if (m_suspendBackingStoreUpdates && !isOpenGLCompositing())
         return false;
 
+    if (!m_webPage->d->compositor())
+        return false;
+
     Platform::IntRect dst = m_webPage->client()->userInterfaceBlittedDestinationRect();
     if (dst.isEmpty())
         return false;
@@ -2526,7 +2542,7 @@ bool BackingStorePrivate::drawSubLayers()
     Platform::IntRect src = m_webPage->client()->userInterfaceBlittedVisibleContentsRect();
     WebCore::FloatRect contentsRect = m_webPage->d->mapFromTransformedFloatRect(
         WebCore::FloatRect(WebCore::IntRect(src)));
-    return m_webPage->d->drawSubLayers(dst, contentsRect);
+    return m_webPage->d->compositor()->drawLayers(dst, contentsRect);
 }
 
 bool BackingStorePrivate::drawLayersOnCommitIfNeeded()
@@ -2557,7 +2573,8 @@ void BackingStorePrivate::drawAndBlendLayersForDirectRendering(const Platform::I
 
     // Check if rendering caused a commit and we need to redraw the layers.
     m_needsDrawLayersOnCommit = false;
-    m_webPage->d->drawSubLayers(dstRect, untransformedContentsRect);
+    if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor())
+        compositor->drawLayers(dstRect, untransformedContentsRect);
 
 #if ENABLE_COMPOSITING_SURFACE
     // See above comment about sync calling, visibleContentsRect() is safe here.
@@ -2680,6 +2697,13 @@ void BackingStore::setDefersBlit(bool b)
 
 bool BackingStore::hasBlitJobs() const
 {
+#if USE(ACCELERATED_COMPOSITING)
+    // If there's a WebPageCompositorClient, let it schedule the blit.
+    WebPageCompositorPrivate* compositor = d->m_webPage->d->compositor();
+    if (compositor && compositor->client())
+        return false;
+#endif
+
     // Normally, this would be called from the compositing thread,
     // and the flag is set on the compositing thread, so no need for
     // synchronization.
@@ -2688,6 +2712,13 @@ bool BackingStore::hasBlitJobs() const
 
 void BackingStore::blitOnIdle()
 {
+#if USE(ACCELERATED_COMPOSITING)
+    // If there's a WebPageCompositorClient, let it schedule the blit.
+    WebPageCompositorPrivate* compositor = d->m_webPage->d->compositor();
+    if (compositor && compositor->client())
+        return;
+#endif
+
     d->blitVisibleContents(true /*force*/);
 }
 
@@ -2696,6 +2727,11 @@ Platform::IntSize BackingStorePrivate::surfaceSize() const
     if (Window* window = m_webPage->client()->window())
         return window->surfaceSize();
 
+#if USE(ACCELERATED_COMPOSITING)
+    if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor())
+        return compositor->context()->surfaceSize();
+#endif
+
     return Platform::IntSize();
 }
 
@@ -2704,6 +2740,11 @@ Platform::Graphics::Buffer* BackingStorePrivate::buffer() const
     if (Window* window = m_webPage->client()->window())
         return window->buffer();
 
+#if USE(ACCELERATED_COMPOSITING)
+    if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor())
+        return compositor->context()->buffer();
+#endif
+
     return 0;
 }
 
index e168943..4f2be62 100644 (file)
@@ -328,7 +328,6 @@ WebPagePrivate::WebPagePrivate(WebPage* webPage, WebPageClient* client, const In
     , m_geolocationClient(0)
     , m_inRegionScrollStartingNode(0)
 #if USE(ACCELERATED_COMPOSITING)
-    , m_isAcceleratedCompositingActive(false)
     , m_rootLayerCommitTimer(adoptPtr(new Timer<WebPagePrivate>(this, &WebPagePrivate::rootLayerCommitTimerFired)))
     , m_needsOneShotDrawingSynchronization(false)
     , m_needsCommit(false)
@@ -5194,7 +5193,7 @@ void WebPagePrivate::drawLayersOnCommit()
         return; // blitVisibleContents() includes drawSubLayers() in this case.
     }
 
-    if (!drawSubLayers())
+    if (!m_backingStore->d->drawSubLayers())
         return;
 
     // If we use the compositing surface, we need to re-blit the
@@ -5213,29 +5212,6 @@ void WebPagePrivate::drawLayersOnCommit()
     m_backingStore->d->blitVisibleContents();
 }
 
-bool WebPagePrivate::drawSubLayers(const IntRect& dstRect, const FloatRect& contents)
-{
-    ASSERT(Platform::userInterfaceThreadMessageClient()->isCurrentThread());
-    if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread())
-        return false;
-
-    if (m_compositor) {
-        m_compositor->setBackingStoreUsesOpenGL(m_backingStore->d->isOpenGLCompositing());
-        return m_compositor->drawLayers(dstRect, contents);
-    }
-
-    return false;
-}
-
-bool WebPagePrivate::drawSubLayers()
-{
-    ASSERT(Platform::userInterfaceThreadMessageClient()->isCurrentThread());
-    if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread())
-        return false;
-
-    return m_backingStore->d->drawSubLayers();
-}
-
 void WebPagePrivate::scheduleRootLayerCommit()
 {
     if (!m_frameLayers || !m_frameLayers->hasLayer())
@@ -5270,6 +5246,24 @@ LayerRenderingResults WebPagePrivate::lastCompositingResults() const
     return LayerRenderingResults();
 }
 
+void WebPagePrivate::setCompositor(PassRefPtr<WebPageCompositorPrivate> compositor)
+{
+    using namespace BlackBerry::Platform;
+
+    // The m_compositor member has to be modified during a sync call for thread
+    // safe access to m_compositor and its refcount.
+    if (!userInterfaceThreadMessageClient()->isCurrentThread()) {
+        userInterfaceThreadMessageClient()->dispatchSyncMessage(createMethodCallMessage(&WebPagePrivate::setCompositor, this, compositor));
+        return;
+    }
+
+    m_compositor = compositor;
+
+    // The previous compositor, if any, has now released it's OpenGL resources,
+    // so we can safely free the owned context, if any.
+    m_ownedContext.clear();
+}
+
 void WebPagePrivate::commitRootLayer(const IntRect& layoutRectForCompositing,
                                      const IntSize& contentsSizeForCompositing)
 {
@@ -5369,28 +5363,6 @@ void WebPagePrivate::rootLayerCommitTimerFired(Timer<WebPagePrivate>*)
         drawLayersOnCommit();
 }
 
-void WebPagePrivate::setIsAcceleratedCompositingActive(bool active)
-{
-    // Backing store can be null here because it happens during teardown.
-    if (m_isAcceleratedCompositingActive == active || !m_backingStore)
-        return;
-
-    m_isAcceleratedCompositingActive = active;
-
-    if (!active) {
-        m_compositor.clear();
-        resetCompositingSurface();
-        return;
-    }
-
-    if (!m_compositor) {
-        m_compositor = adoptPtr(new WebPageCompositorPrivate(this));
-        m_isAcceleratedCompositingActive = m_compositor->hardwareCompositing();
-        if (!m_isAcceleratedCompositingActive)
-            m_compositor.clear();
-    }
-}
-
 void WebPagePrivate::resetCompositingSurface()
 {
     if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread()) {
@@ -5449,12 +5421,13 @@ void WebPagePrivate::setRootLayerCompositingThread(LayerCompositingThread* layer
          // the process of destruction of WebPage where we have already
          // called syncDestroyCompositorOnCompositingThread() to destroy
          // the compositor.
-         setIsAcceleratedCompositingActive(false);
+         destroyCompositor();
+         resetCompositingSurface();
          return;
     }
 
     if (!m_compositor)
-        setIsAcceleratedCompositingActive(true);
+        createCompositor();
 
     // Don't ASSERT(m_compositor) here because setIsAcceleratedCompositingActive(true)
     // may not turn accelerated compositing on since m_backingStore is 0.
@@ -5462,9 +5435,30 @@ void WebPagePrivate::setRootLayerCompositingThread(LayerCompositingThread* layer
         m_compositor->setRootLayer(layer);
 }
 
+bool WebPagePrivate::createCompositor()
+{
+    m_ownedContext = GLES2Context::create(this);
+    m_compositor = WebPageCompositorPrivate::create(this, 0);
+    m_compositor->setContext(m_ownedContext.get());
+
+    if (!m_compositor->hardwareCompositing()) {
+        destroyCompositor();
+        return false;
+    }
+
+    return true;
+}
+
 void WebPagePrivate::destroyCompositor()
 {
-     m_compositor.clear();
+    // We shouldn't release the compositor unless we created and own the
+    // context. If the compositor was created from the WebPageCompositor API,
+    // keep it around and reuse it later.
+    if (!m_ownedContext)
+        return;
+
+    m_compositor.clear();
+    m_ownedContext.clear();
 }
 
 void WebPagePrivate::syncDestroyCompositorOnCompositingThread()
index 5e3105c..3cd7dac 100644 (file)
@@ -62,6 +62,7 @@ class BackingStoreClient;
 class BackingStorePrivate;
 class RenderQueue;
 class WebPageClient;
+class WebPageCompositor;
 class WebPageGroupLoadDeferrer;
 class WebPagePrivate;
 class WebSettings;
@@ -335,6 +336,7 @@ private:
     friend class WebKit::BackingStoreClient;
     friend class WebKit::BackingStorePrivate;
     friend class WebKit::RenderQueue;
+    friend class WebKit::WebPageCompositor;
     friend class WebKit::WebPageGroupLoadDeferrer;
     friend class WebKit::WebPagePrivate;
     friend class WebCore::ChromeClientBlackBerry;
index 2f717df..eff6ae6 100644 (file)
 
 #include "config.h"
 
+#include "WebPageCompositor.h"
+
 #if USE(ACCELERATED_COMPOSITING)
+#include "WebPageCompositorClient.h"
 #include "WebPageCompositor_p.h"
 
 #include "BackingStore_p.h"
 #include "LayerWebKitThread.h"
 #include "WebPage_p.h"
 
+#include <BlackBerryPlatformDebugMacros.h>
 #include <BlackBerryPlatformExecutableMessage.h>
 #include <BlackBerryPlatformMessage.h>
 #include <BlackBerryPlatformMessageClient.h>
@@ -36,13 +40,12 @@ using namespace WebCore;
 namespace BlackBerry {
 namespace WebKit {
 
-WebPageCompositorPrivate::WebPageCompositorPrivate(WebPagePrivate* page)
-    : m_webPage(page)
-    , m_context(GLES2Context::create(page))
-    , m_layerRenderer(LayerRenderer::create(m_context.get()))
-    , m_backingStoreUsesOpenGL(false)
+WebPageCompositorPrivate::WebPageCompositorPrivate(WebPagePrivate* page, WebPageCompositorClient* client)
+    : m_client(client)
+    , m_webPage(page)
     , m_animationTimer(this, &WebPageCompositorPrivate::animationTimerFired)
     , m_timerClient(new Platform::GenericTimerClient(Platform::userInterfaceThreadTimerClient()))
+    , m_pendingAnimationFrame(0.0)
 {
     m_animationTimer.setClient(m_timerClient);
 }
@@ -53,21 +56,32 @@ WebPageCompositorPrivate::~WebPageCompositorPrivate()
     delete m_timerClient;
 }
 
+void WebPageCompositorPrivate::setContext(Platform::Graphics::GLES2Context* context)
+{
+    if (m_context == context)
+        return;
+
+    m_context = context;
+    if (!m_context) {
+        m_layerRenderer.clear();
+        return;
+    }
+
+    m_layerRenderer = LayerRenderer::create(m_context);
+}
+
 bool WebPageCompositorPrivate::hardwareCompositing() const
 {
-    return m_layerRenderer->hardwareCompositing();
+    return m_layerRenderer && m_layerRenderer->hardwareCompositing();
 }
 
 void WebPageCompositorPrivate::setRootLayer(LayerCompositingThread* rootLayer)
 {
     m_rootLayer = rootLayer;
-    m_layerRenderer->setRootLayer(m_rootLayer.get());
-}
 
-void WebPageCompositorPrivate::setBackingStoreUsesOpenGL(bool backingStoreUsesOpenGL)
-{
-    m_backingStoreUsesOpenGL = backingStoreUsesOpenGL;
-    m_layerRenderer->setClearSurfaceOnDrawLayers(!backingStoreUsesOpenGL);
+    ASSERT(m_layerRenderer);
+    if (m_layerRenderer)
+        m_layerRenderer->setRootLayer(m_rootLayer.get());
 }
 
 void WebPageCompositorPrivate::commit(LayerWebKitThread* rootLayer)
@@ -78,15 +92,47 @@ void WebPageCompositorPrivate::commit(LayerWebKitThread* rootLayer)
     rootLayer->commitOnCompositingThread();
 }
 
+void WebPageCompositorPrivate::render(const IntRect& dstRect, const IntRect& transformedContents)
+{
+    // It's not safe to call into the BackingStore if the compositor hasn't been set yet.
+    // For thread safety, we have to do it using a round-trip to the WebKit thread, so the
+    // embedder might call this before the round-trip to WebPagePrivate::setCompositor() is
+    // done.
+    if (m_webPage->compositor() != this)
+        return;
+
+    // The BackingStore is the root layer
+    if (BackingStore* backingStore = m_webPage->m_backingStore)
+        backingStore->d->blitContents(dstRect, transformedContents, true);
+    else {
+        FloatRect contents = m_webPage->mapFromTransformedFloatRect(FloatRect(transformedContents));
+        drawLayers(dstRect, contents);
+    }
+}
+
 bool WebPageCompositorPrivate::drawLayers(const IntRect& dstRect, const FloatRect& contents)
 {
+    if (!m_layerRenderer)
+        return false;
+
+    m_pendingAnimationFrame = 0.0;
+
+    bool shouldClear = false;
+    if (BackingStore* backingStore = m_webPage->m_backingStore)
+        shouldClear = !backingStore->d->isOpenGLCompositing();
+    m_layerRenderer->setClearSurfaceOnDrawLayers(shouldClear);
+
     m_layerRenderer->drawLayers(contents, m_layoutRectForCompositing, m_contentsSizeForCompositing, dstRect);
     m_lastCompositingResults = m_layerRenderer->lastRenderingResults();
 
     if (m_lastCompositingResults.needsAnimationFrame) {
         // Using a timeout of 0 actually won't start a timer, it will send a message.
-        m_animationTimer.start(1.0 / 60.0);
-        m_webPage->updateDelegatedOverlays();
+        if (m_client)
+            m_pendingAnimationFrame = m_client->requestAnimationFrame();
+        else {
+            m_animationTimer.start(1.0 / 60.0);
+            m_webPage->updateDelegatedOverlays();
+        }
     }
 
     return true;
@@ -99,19 +145,127 @@ void WebPageCompositorPrivate::releaseLayerResources()
 
 void WebPageCompositorPrivate::animationTimerFired()
 {
-    if (m_webPage->m_backingStore->d->shouldDirectRenderingToWindow()) {
-        if (m_webPage->m_backingStore->d->isDirectRenderingAnimationMessageScheduled())
+    BackingStore* backingStore = m_webPage->m_backingStore;
+    if (!backingStore) {
+        drawLayers(m_webPage->client()->userInterfaceBlittedDestinationRect(),
+                   IntRect(m_webPage->client()->userInterfaceBlittedVisibleContentsRect()));
+        return;
+    }
+
+    if (backingStore->d->shouldDirectRenderingToWindow()) {
+        if (backingStore->d->isDirectRenderingAnimationMessageScheduled())
             return; // don't send new messages as long as we haven't rerendered
 
-        m_webPage->m_backingStore->d->setDirectRenderingAnimationMessageScheduled();
-        BlackBerry::Platform::webKitThreadMessageClient()->dispatchMessage(
-            BlackBerry::Platform::createMethodCallMessage(
-                &BackingStorePrivate::renderVisibleContents, m_webPage->m_backingStore->d));
+        using namespace BlackBerry::Platform;
+
+        backingStore->d->setDirectRenderingAnimationMessageScheduled();
+        webKitThreadMessageClient()->dispatchMessage(createMethodCallMessage(&BackingStorePrivate::renderVisibleContents, backingStore->d));
         return;
     }
     m_webPage->blitVisibleContents();
 }
 
+void WebPageCompositorPrivate::compositorDestroyed()
+{
+    if (m_client)
+        m_client->compositorDestroyed();
+
+    m_client = 0;
+}
+
+WebPageCompositor::WebPageCompositor(WebPage* page, WebPageCompositorClient* client)
+{
+    using namespace BlackBerry::Platform;
+
+    RefPtr<WebPageCompositorPrivate> tmp = WebPageCompositorPrivate::create(page->d, client);
+
+    // Keep one ref ourselves...
+    d = tmp.get();
+    d->ref();
+
+    // ...And pass one ref to the web page.
+    // This ensures that the compositor will be around for as long as it's
+    // needed. Unfortunately RefPtr<T> is not public, so we have declare to
+    // resort to manual refcounting.
+    webKitThreadMessageClient()->dispatchMessage(createMethodCallMessage(&WebPagePrivate::setCompositor, d->page(), tmp));
+}
+
+WebPageCompositor::~WebPageCompositor()
+{
+    using namespace BlackBerry::Platform;
+
+    webKitThreadMessageClient()->dispatchMessage(createMethodCallMessage(&WebPagePrivate::setCompositor, d->page(), PassRefPtr<WebPageCompositorPrivate>(0)));
+    d->compositorDestroyed();
+    d->deref();
+}
+
+WebPageCompositorClient* WebPageCompositor::client() const
+{
+    return 0;
+}
+
+void WebPageCompositor::prepareFrame(Platform::Graphics::GLES2Context* context, double timestamp)
+{
+    d->setContext(context);
+}
+
+void WebPageCompositor::render(Platform::Graphics::GLES2Context* context, const Platform::IntRect& dstRect, const Platform::IntRect& contents)
+{
+    d->setContext(context);
+    d->render(dstRect, contents);
+}
+
+void WebPageCompositor::cleanup(Platform::Graphics::GLES2Context* context)
+{
+    d->setContext(0);
+}
+
+void WebPageCompositor::contextLost()
+{
+    // This method needs to delete the compositor in a way that not tries to
+    // use any OpenGL calls (the context is gone, so we can't and don't need to
+    // free any OpenGL resources.
+    notImplemented();
+}
+
+} // namespace WebKit
+} // namespace BlackBerry
+
+#else // USE(ACCELERATED_COMPOSITING)
+
+namespace BlackBerry {
+namespace WebKit {
+
+WebPageCompositor::WebPageCompositor(WebPage*, WebPageCompositorClient*)
+    : d(0)
+{
+}
+
+WebPageCompositor::~WebPageCompositor()
+{
+}
+
+WebPageCompositorClient* WebPageCompositor::client() const
+{
+    return 0;
+}
+
+void WebPageCompositor::prepareFrame(Platform::Graphics::GLES2Context*, double)
+{
+}
+
+void WebPageCompositor::render(Platform::Graphics::GLES2Context*, const Platform::IntRect&, const Platform::IntRect&)
+{
+}
+
+void WebPageCompositor::cleanup(Platform::Graphics::GLES2Context*)
+{
+}
+
+void WebPageCompositor::contextLost()
+{
+}
+
 } // namespace WebKit
 } // namespace BlackBerry
 
diff --git a/Source/WebKit/blackberry/Api/WebPageCompositor.h b/Source/WebKit/blackberry/Api/WebPageCompositor.h
new file mode 100644 (file)
index 0000000..11bf284
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef WebPageCompositor_h
+#define WebPageCompositor_h
+
+#include "BlackBerryGlobal.h"
+
+#include <BlackBerryPlatformGLES2Context.h>
+#include <BlackBerryPlatformGraphics.h>
+#include <BlackBerryPlatformPrimitives.h>
+
+namespace BlackBerry {
+namespace WebKit {
+
+class WebPage;
+class WebPageCompositorClient;
+class WebPageCompositorPrivate;
+
+class BLACKBERRY_EXPORT WebPageCompositor {
+public:
+    WebPageCompositor(WebPage*, WebPageCompositorClient*);
+    virtual ~WebPageCompositor();
+
+    WebPageCompositorClient* client() const;
+
+    void prepareFrame(Platform::Graphics::GLES2Context*, double timestamp);
+
+    // FIXME: dstRect should be a Platform::TransformationMatrix instead. PR142628
+    void render(Platform::Graphics::GLES2Context*, const Platform::IntRect& dstRect, const Platform::IntRect& contents);
+
+    void cleanup(Platform::Graphics::GLES2Context*);
+
+    void contextLost();
+
+private:
+    WebPageCompositorPrivate *d;
+};
+
+} // namespace WebKit
+} // namespace BlackBerry
+
+#endif // WebPageCompositor_h
diff --git a/Source/WebKit/blackberry/Api/WebPageCompositorClient.h b/Source/WebKit/blackberry/Api/WebPageCompositorClient.h
new file mode 100644 (file)
index 0000000..00497ee
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef WebPageCompositorClient_h
+#define WebPageCompositorClient_h
+
+#include "BlackBerryGlobal.h"
+
+namespace BlackBerry {
+namespace WebKit {
+
+class BLACKBERRY_EXPORT WebPageCompositorClient {
+public:
+    virtual ~WebPageCompositorClient() { }
+
+    virtual void compositorDestroyed() = 0;
+
+    virtual double requestAnimationFrame() = 0;
+    virtual void invalidate(double animationFrameTimestamp) = 0;
+    virtual void requestCleanup() = 0;
+};
+
+} // namespace WebKit
+} // namespace BlackBerry
+
+#endif // WebPageCompositorClient_h
index 0001c53..2cac924 100644 (file)
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#include "GLES2Context.h"
 #include "LayerCompositingThread.h"
 #include "LayerRenderer.h"
 
+#include <BlackBerryPlatformGLES2Context.h>
 #include <BlackBerryPlatformTimer.h>
 #include <wtf/OwnPtr.h>
+#include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
@@ -36,22 +37,32 @@ class LayerWebKitThread;
 namespace BlackBerry {
 namespace WebKit {
 
+class WebPageCompositorClient;
 class WebPagePrivate;
 
-// This class may only be used on the compositing thread.
-class WebPageCompositorPrivate {
+// This class may only be used on the compositing thread. So it does not need to be threadsaferefcounted.
+class WebPageCompositorPrivate : public RefCounted<WebPageCompositorPrivate> {
 public:
-    WebPageCompositorPrivate(WebPagePrivate*);
+    static PassRefPtr<WebPageCompositorPrivate> create(WebPagePrivate* page, WebPageCompositorClient* client)
+    {
+        return adoptRef(new WebPageCompositorPrivate(page, client));
+    }
+
     ~WebPageCompositorPrivate();
 
     bool hardwareCompositing() const;
 
-    void setRootLayer(WebCore::LayerCompositingThread*);
+    Platform::Graphics::GLES2Context* context() const { return m_context; }
+    void setContext(Platform::Graphics::GLES2Context*);
 
-    void setBackingStoreUsesOpenGL(bool);
+    void setRootLayer(WebCore::LayerCompositingThread*);
 
     void commit(WebCore::LayerWebKitThread* rootLayerProxy);
 
+    // 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
     bool drawLayers(const WebCore::IntRect& dstRect, const WebCore::FloatRect& contents);
 
     WebCore::IntRect layoutRectForCompositing() const { return m_layoutRectForCompositing; }
@@ -63,22 +74,31 @@ public:
     WebCore::LayerRenderingResults lastCompositingResults() const { return m_lastCompositingResults; }
     void setLastCompositingResults(const WebCore::LayerRenderingResults& results) { m_lastCompositingResults = results; }
 
+    double animationFrameTimestamp() const { return m_pendingAnimationFrame; }
+
     void releaseLayerResources();
 
+    WebPagePrivate* page() const { return m_webPage; }
+    WebPageCompositorClient* client() const { return m_client; }
+    void compositorDestroyed();
+
+protected:
+    WebPageCompositorPrivate(WebPagePrivate*, WebPageCompositorClient*);
+
 private:
     void animationTimerFired();
 
+    WebPageCompositorClient* m_client;
     WebPagePrivate* m_webPage;
-    // Please maintain this order since m_layerRenderer depends on m_context in initialization list.
-    OwnPtr<GLES2Context> m_context;
+    Platform::Graphics::GLES2Context* m_context;
     OwnPtr<WebCore::LayerRenderer> m_layerRenderer;
     RefPtr<WebCore::LayerCompositingThread> m_rootLayer;
     WebCore::IntRect m_layoutRectForCompositing;
     WebCore::IntSize m_contentsSizeForCompositing;
     WebCore::LayerRenderingResults m_lastCompositingResults;
-    bool m_backingStoreUsesOpenGL;
     BlackBerry::Platform::Timer<WebPageCompositorPrivate> m_animationTimer;
     BlackBerry::Platform::TimerClient* m_timerClient;
+    double m_pendingAnimationFrame;
 };
 
 } // namespace WebKit
index eb50b06..6966451 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "ChromeClient.h"
 #if USE(ACCELERATED_COMPOSITING)
+#include "GLES2Context.h"
 #include "LayerRenderer.h"
 #endif
 #include "PageClientBlackBerry.h"
@@ -82,6 +83,8 @@ public:
 
     static WebCore::Page* core(const WebPage*);
 
+    WebPageClient* client() const { return m_client; }
+
     void init(const WebString& pageGroupName);
     bool handleMouseEvent(WebCore::PlatformMouseEvent&);
     bool handleWheelEvent(WebCore::PlatformWheelEvent&);
@@ -368,14 +371,14 @@ public:
     // Thread safe.
     void resetCompositingSurface();
     void drawLayersOnCommit(); // Including backing store blit.
-    bool drawSubLayers(const WebCore::IntRect& dstRect, const WebCore::FloatRect& contents);
-    bool drawSubLayers(); // Draw them at last known position.
 
     // Compositing thread.
     void setRootLayerCompositingThread(WebCore::LayerCompositingThread*);
     void commitRootLayer(const WebCore::IntRect&, const WebCore::IntSize&);
-    void setIsAcceleratedCompositingActive(bool);
-    bool isAcceleratedCompositingActive() const { return m_isAcceleratedCompositingActive; }
+    bool isAcceleratedCompositingActive() const { return m_compositor; }
+    WebPageCompositorPrivate* compositor() const { return m_compositor.get(); }
+    void setCompositor(PassRefPtr<WebPageCompositorPrivate>);
+    bool createCompositor();
     void destroyCompositor();
     void syncDestroyCompositorOnCompositingThread();
     void destroyLayerResources();
@@ -502,7 +505,12 @@ public:
 #if USE(ACCELERATED_COMPOSITING)
     bool m_isAcceleratedCompositingActive;
     OwnPtr<FrameLayers> m_frameLayers; // WebKit thread only.
-    OwnPtr<WebPageCompositorPrivate> m_compositor; // Compositing thread only.
+
+    // Compositing thread only, used only when the WebKit layer created the context.
+    // If the API client created the context, this will be null.
+    OwnPtr<GLES2Context> m_ownedContext;
+
+    RefPtr<WebPageCompositorPrivate> m_compositor; // Compositing thread only.
     OwnPtr<WebCore::Timer<WebPagePrivate> > m_rootLayerCommitTimer;
     bool m_needsOneShotDrawingSynchronization;
     bool m_needsCommit;
index 05e69f0..a4a25fb 100644 (file)
@@ -1,3 +1,73 @@
+2012-03-23  Arvid Nilsson  <anilsson@rim.com>
+
+        [BlackBerry] Add WebPageCompositor class to BlackBerry WebKit API
+        https://bugs.webkit.org/show_bug.cgi?id=81121
+        RIM PR: 136687
+
+        Reviewed by Rob Buis.
+
+        The idea is for the API client to use a WebPageCompositor object to
+        render the WebPage when there's no screen window available.
+
+        The WebPageCompositorPrivate becomes reference counted in order to be
+        kept alive either because it's used for accelerated compositing layers
+        or used for the WebPageCompositor API. It can still work standalone.
+
+        Clean up some code - no need to keep track of a separate boolean
+        WebPagePrivate::m_isAcceleratedCompositingActive when the state of
+        m_compositor can tell you.
+
+        Also remove duplicated code from WebPagePrivate - go directly to the
+        compositor object instead, if you need to draw the AC layers.
+
+        Reviewed internally by Robin Cao and the hasBlitJobs/blitOnIdle change
+        by Filip Spacek.
+
+        * Api/BackingStore.cpp:
+        (BlackBerry::WebKit::BackingStore::hasBlitJobs):
+        (BlackBerry::WebKit::BackingStore::blitOnIdle):
+        (BlackBerry::WebKit::BackingStorePrivate::blitContents):
+        (BlackBerry::WebKit::BackingStorePrivate::drawSubLayers):
+        (BlackBerry::WebKit::BackingStorePrivate::drawAndBlendLayersForDirectRendering):
+        (BlackBerry::WebKit::BackingStorePrivate::surfaceSize):
+        (BlackBerry::WebKit::BackingStorePrivate::buffer):
+        * Api/WebPage.cpp:
+        (BlackBerry::WebKit::WebPagePrivate::WebPagePrivate):
+        (BlackBerry::WebKit::WebPagePrivate::drawLayersOnCommit):
+        (BlackBerry::WebKit::WebPagePrivate::setCompositor):
+        (BlackBerry::WebKit::WebPagePrivate::setRootLayerCompositingThread):
+        (BlackBerry::WebKit::WebPagePrivate::createCompositor):
+        (BlackBerry::WebKit::WebPagePrivate::destroyCompositor):
+        * Api/WebPage.h:
+        * Api/WebPageCompositor.cpp:
+        (BlackBerry::WebKit::WebPageCompositorPrivate::WebPageCompositorPrivate):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::setContext):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::hardwareCompositing):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::setRootLayer):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::render):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::drawLayers):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::animationTimerFired):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::compositorDestroyed):
+        (BlackBerry::WebKit::WebPageCompositor::WebPageCompositor):
+        (BlackBerry::WebKit::WebPageCompositor::~WebPageCompositor):
+        (BlackBerry::WebKit::WebPageCompositor::client):
+        (BlackBerry::WebKit::WebPageCompositor::prepareFrame):
+        (BlackBerry::WebKit::WebPageCompositor::render):
+        (BlackBerry::WebKit::WebPageCompositor::cleanup):
+        (BlackBerry::WebKit::WebPageCompositor::contextLost):
+        * Api/WebPageCompositor.h: Added.
+        * Api/WebPageCompositorClient.h: Added.
+        * Api/WebPageCompositor_p.h:
+        (BlackBerry::WebKit::WebPageCompositorPrivate::create):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::context):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::animationFrameTimestamp):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::page):
+        (BlackBerry::WebKit::WebPageCompositorPrivate::client):
+        * Api/WebPage_p.h:
+        (BlackBerry::WebKit::WebPagePrivate::client):
+        (BlackBerry::WebKit::WebPagePrivate::isAcceleratedCompositingActive):
+        (BlackBerry::WebKit::WebPagePrivate::compositor):
+
 2012-03-22  Charles Wei  <charles.wei@torchmobile.com.cn>
 
         [BlackBerry] Need to store the meta info of a page in the ViewState of the history