[BlackBerry] Upstream LayerCompositingThread.{h, cpp}
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 26 Mar 2012 16:24:43 +0000 (16:24 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 26 Mar 2012 16:24:43 +0000 (16:24 +0000)
https://bugs.webkit.org/show_bug.cgi?id=79873

Patch by Robin Cao <robin.cao@torchmobile.com.cn> on 2012-03-26
Reviewed by Rob Buis.

Initial upstream, no new tests.

* platform/graphics/blackberry/LayerCompositingThread.cpp: Added.
(WebCore):
(WebCore::LayerCompositingThread::create):
(WebCore::LayerCompositingThread::LayerCompositingThread):
(WebCore::LayerCompositingThread::~LayerCompositingThread):
(WebCore::LayerCompositingThread::destroyOnCompositingThread):
(WebCore::LayerCompositingThread::setLayerRenderer):
(WebCore::LayerCompositingThread::deleteTextures):
(WebCore::LayerCompositingThread::setDrawTransform):
(WebCore::getTransformedRect):
(WebCore::LayerCompositingThread::getTransformedHolePunchRect):
(WebCore::LayerCompositingThread::drawTextures):
(WebCore::LayerCompositingThread::drawSurface):
(WebCore::LayerCompositingThread::drawMissingTextures):
(WebCore::LayerCompositingThread::releaseTextureResources):
(WebCore::LayerCompositingThread::setPluginView):
(WebCore::LayerCompositingThread::setMediaPlayer):
(WebCore::LayerCompositingThread::clearAnimations):
(WebCore::LayerCompositingThread::removeSublayer):
(WebCore::LayerCompositingThread::indexOfSublayer):
(WebCore::LayerCompositingThread::rootLayer):
(WebCore::LayerCompositingThread::removeFromSuperlayer):
(WebCore::LayerCompositingThread::setSublayers):
(WebCore::LayerCompositingThread::updateTextureContentsIfNeeded):
(WebCore::LayerCompositingThread::setVisible):
(WebCore::LayerCompositingThread::setNeedsCommit):
(WebCore::LayerCompositingThread::scheduleCommit):
(WebCore::LayerCompositingThread::updateAnimations):
(WebCore::LayerCompositingThread::hasVisibleHolePunchRect):
(WebCore::LayerCompositingThread::createLayerRendererSurface):
* platform/graphics/blackberry/LayerCompositingThread.h: Added.
(Graphics):
(WebCore):
(LayerCompositingThread):
(WebCore::LayerCompositingThread::bindContentsTexture):
(WebCore::LayerCompositingThread::getSublayers):
(WebCore::LayerCompositingThread::setSuperlayer):
(WebCore::LayerCompositingThread::superlayer):
(WebCore::LayerCompositingThread::drawTransform):
(WebCore::LayerCompositingThread::setDrawOpacity):
(WebCore::LayerCompositingThread::drawOpacity):
(WebCore::LayerCompositingThread::layerRendererSurface):
(WebCore::LayerCompositingThread::clearLayerRendererSurface):
(WebCore::LayerCompositingThread::setMaskLayer):
(WebCore::LayerCompositingThread::maskLayer):
(WebCore::LayerCompositingThread::setReplicaLayer):
(WebCore::LayerCompositingThread::replicaLayer):
(WebCore::LayerCompositingThread::getDrawRect):
(WebCore::LayerCompositingThread::getTransformedBounds):
(WebCore::LayerCompositingThread::hasMissingTextures):
(WebCore::LayerCompositingThread::isDirty):
(WebCore::LayerCompositingThread::isVisible):
(WebCore::LayerCompositingThread::setOpacity):
(WebCore::LayerCompositingThread::setTransform):
(WebCore::LayerCompositingThread::hasRunningAnimations):
(WebCore::LayerCompositingThread::numSublayers):

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

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h [new file with mode: 0644]

index 780f46babae0c5821f735ce34cf4eeb483c2051e..35c166532adaf11cf08b1235f24f859f97bcf60e 100644 (file)
@@ -1,3 +1,69 @@
+2012-03-26  Robin Cao  <robin.cao@torchmobile.com.cn>
+
+        [BlackBerry] Upstream LayerCompositingThread.{h, cpp}
+        https://bugs.webkit.org/show_bug.cgi?id=79873
+
+        Reviewed by Rob Buis.
+
+        Initial upstream, no new tests.
+
+        * platform/graphics/blackberry/LayerCompositingThread.cpp: Added.
+        (WebCore):
+        (WebCore::LayerCompositingThread::create):
+        (WebCore::LayerCompositingThread::LayerCompositingThread):
+        (WebCore::LayerCompositingThread::~LayerCompositingThread):
+        (WebCore::LayerCompositingThread::destroyOnCompositingThread):
+        (WebCore::LayerCompositingThread::setLayerRenderer):
+        (WebCore::LayerCompositingThread::deleteTextures):
+        (WebCore::LayerCompositingThread::setDrawTransform):
+        (WebCore::getTransformedRect):
+        (WebCore::LayerCompositingThread::getTransformedHolePunchRect):
+        (WebCore::LayerCompositingThread::drawTextures):
+        (WebCore::LayerCompositingThread::drawSurface):
+        (WebCore::LayerCompositingThread::drawMissingTextures):
+        (WebCore::LayerCompositingThread::releaseTextureResources):
+        (WebCore::LayerCompositingThread::setPluginView):
+        (WebCore::LayerCompositingThread::setMediaPlayer):
+        (WebCore::LayerCompositingThread::clearAnimations):
+        (WebCore::LayerCompositingThread::removeSublayer):
+        (WebCore::LayerCompositingThread::indexOfSublayer):
+        (WebCore::LayerCompositingThread::rootLayer):
+        (WebCore::LayerCompositingThread::removeFromSuperlayer):
+        (WebCore::LayerCompositingThread::setSublayers):
+        (WebCore::LayerCompositingThread::updateTextureContentsIfNeeded):
+        (WebCore::LayerCompositingThread::setVisible):
+        (WebCore::LayerCompositingThread::setNeedsCommit):
+        (WebCore::LayerCompositingThread::scheduleCommit):
+        (WebCore::LayerCompositingThread::updateAnimations):
+        (WebCore::LayerCompositingThread::hasVisibleHolePunchRect):
+        (WebCore::LayerCompositingThread::createLayerRendererSurface):
+        * platform/graphics/blackberry/LayerCompositingThread.h: Added.
+        (Graphics):
+        (WebCore):
+        (LayerCompositingThread):
+        (WebCore::LayerCompositingThread::bindContentsTexture):
+        (WebCore::LayerCompositingThread::getSublayers):
+        (WebCore::LayerCompositingThread::setSuperlayer):
+        (WebCore::LayerCompositingThread::superlayer):
+        (WebCore::LayerCompositingThread::drawTransform):
+        (WebCore::LayerCompositingThread::setDrawOpacity):
+        (WebCore::LayerCompositingThread::drawOpacity):
+        (WebCore::LayerCompositingThread::layerRendererSurface):
+        (WebCore::LayerCompositingThread::clearLayerRendererSurface):
+        (WebCore::LayerCompositingThread::setMaskLayer):
+        (WebCore::LayerCompositingThread::maskLayer):
+        (WebCore::LayerCompositingThread::setReplicaLayer):
+        (WebCore::LayerCompositingThread::replicaLayer):
+        (WebCore::LayerCompositingThread::getDrawRect):
+        (WebCore::LayerCompositingThread::getTransformedBounds):
+        (WebCore::LayerCompositingThread::hasMissingTextures):
+        (WebCore::LayerCompositingThread::isDirty):
+        (WebCore::LayerCompositingThread::isVisible):
+        (WebCore::LayerCompositingThread::setOpacity):
+        (WebCore::LayerCompositingThread::setTransform):
+        (WebCore::LayerCompositingThread::hasRunningAnimations):
+        (WebCore::LayerCompositingThread::numSublayers):
+
 2012-03-26  Kent Tamura  <tkent@chromium.org>
 
         Add a notification function for detaching to TextFieldDecorator
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp
new file mode 100644 (file)
index 0000000..89a9cf7
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerCompositingThread.h"
+
+#include "LayerMessage.h"
+#include "LayerRenderer.h"
+#include "LayerWebKitThread.h"
+#if ENABLE(VIDEO)
+#include "MediaPlayer.h"
+#include "MediaPlayerPrivateBlackBerry.h"
+#endif
+#include "PluginView.h"
+#include "TextureCacheCompositingThread.h"
+
+#include <BlackBerryPlatformGraphics.h>
+#include <BlackBerryPlatformLog.h>
+#include <wtf/Assertions.h>
+
+#define DEBUG_VIDEO_CLIPPING 0
+
+namespace WebCore {
+
+PassRefPtr<LayerCompositingThread> LayerCompositingThread::create(LayerType type, PassRefPtr<LayerTiler> tiler)
+{
+    return adoptRef(new LayerCompositingThread(type, tiler));
+}
+
+LayerCompositingThread::LayerCompositingThread(LayerType type, PassRefPtr<LayerTiler> tiler)
+    : LayerData(type)
+    , m_layerRenderer(0)
+    , m_superlayer(0)
+    , m_pluginBuffer(0)
+    , m_drawOpacity(0)
+    , m_visible(false)
+    , m_commitScheduled(false)
+    , m_tiler(tiler)
+{
+}
+
+LayerCompositingThread::~LayerCompositingThread()
+{
+    // Unfortunately, ThreadSafeShared<T> is hardwired to call T::~T().
+    // To switch threads in case the last reference is released on the
+    // WebKit thread, we send a sync message to the compositing thread.
+    destroyOnCompositingThread();
+}
+
+void LayerCompositingThread::destroyOnCompositingThread()
+{
+    if (!isCompositingThread()) {
+        dispatchSyncCompositingMessage(BlackBerry::Platform::createMethodCallMessage(
+            &LayerCompositingThread::destroyOnCompositingThread,
+            this));
+        return;
+    }
+
+    m_tiler->layerCompositingThreadDestroyed();
+
+    ASSERT(!superlayer());
+
+    // Remove the superlayer reference from all sublayers.
+    while (m_sublayers.size())
+        m_sublayers[0]->removeFromSuperlayer();
+
+    // Delete all allocated textures
+    deleteTextures();
+
+    // We just deleted all our textures, no need for the
+    // layer renderer to track us anymore
+    if (m_layerRenderer)
+        m_layerRenderer->removeLayer(this);
+}
+
+void LayerCompositingThread::setLayerRenderer(LayerRenderer* renderer)
+{
+    // It's not expected that layers will ever switch renderers.
+    ASSERT(!renderer || !m_layerRenderer || renderer == m_layerRenderer);
+
+    m_layerRenderer = renderer;
+    if (m_layerRenderer)
+        m_layerRenderer->addLayer(this);
+}
+
+void LayerCompositingThread::deleteTextures()
+{
+    releaseTextureResources();
+
+    m_tiler->deleteTextures();
+}
+
+void LayerCompositingThread::setDrawTransform(const TransformationMatrix& matrix)
+{
+    m_drawTransform = matrix;
+
+    float bx = m_bounds.width() / 2.0;
+    float by = m_bounds.height() / 2.0;
+    m_transformedBounds.setP1(matrix.mapPoint(FloatPoint(-bx, -by)));
+    m_transformedBounds.setP2(matrix.mapPoint(FloatPoint(-bx, by)));
+    m_transformedBounds.setP3(matrix.mapPoint(FloatPoint(bx, by)));
+    m_transformedBounds.setP4(matrix.mapPoint(FloatPoint(bx, -by)));
+
+    m_drawRect = m_transformedBounds.boundingBox();
+}
+
+static FloatQuad getTransformedRect(const IntSize& bounds, const IntRect& rect, const TransformationMatrix& drawTransform)
+{
+    float x = -bounds.width() / 2.0 + rect.x();
+    float y = -bounds.height() / 2.0 + rect.y();
+    float w = rect.width();
+    float h = rect.height();
+    FloatQuad result;
+    result.setP1(drawTransform.mapPoint(FloatPoint(x, y)));
+    result.setP2(drawTransform.mapPoint(FloatPoint(x, y + h)));
+    result.setP3(drawTransform.mapPoint(FloatPoint(x + w, y + h)));
+    result.setP4(drawTransform.mapPoint(FloatPoint(x + w, y)));
+
+    return result;
+}
+
+
+FloatQuad LayerCompositingThread::getTransformedHolePunchRect() const
+{
+    // FIXME: the following line disables clipping a video in an iframe i.e. the fix associated with PR 99638.
+    // Some revised test case (e.g. video-iframe.html) show that the original fix works correctly when scrolling
+    // the contents of the frame, but fails to clip correctly if the page (main frame) is scrolled.
+    static bool enableVideoClipping = false;
+
+    if (!mediaPlayer() || !enableVideoClipping) {
+        // m_holePunchClipRect is valid only when there's a media player.
+        return getTransformedRect(m_bounds, m_holePunchRect, m_drawTransform);
+    }
+
+    // The hole punch rectangle may need to be clipped,
+    // e.g. if the <video> is on a layer that's included and clipped by an <iframe>.
+
+    // In order to clip we need to determine the current position of this layer, which
+    // is encoded in the m_drawTransform value, which was used to initialize m_drawRect.
+    IntRect drawRect = m_layerRenderer->toWebKitDocumentCoordinates(m_drawRect);
+
+    // Assert that in this case, where the hole punch rectangle equals the size of the layer,
+    // the drawRect has the same size as the hole punch.
+    // ASSERT(drawRect.size() == m_holePunchRect.size());
+    // Don't assert it programtically though because there may be off-by-one error due to rounding when there's zooming.
+
+    // The difference between drawRect and m_holePunchRect is that drawRect has an accurate position
+    // in WebKit document coordinates, whereas the m_holePunchRect location is (0,0) i.e. it's relative to this layer.
+
+    // Clip the drawRect.
+    // Both drawRect and m_holePunchClipRect already have correct locations, in WebKit document coordinates.
+    IntPoint location = drawRect.location();
+    drawRect.intersect(m_holePunchClipRect);
+
+    // Shift the clipped drawRect to have the same kind of located-at-zero position as the original holePunchRect.
+    drawRect.move(-location.x(), -location.y());
+
+#if DEBUG_VIDEO_CLIPPING
+     IntRect drawRectInWebKitDocumentCoordination = m_layerRenderer->toWebKitDocumentCoordinates(m_drawRect);
+     BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "LayerCompositingThread::getTransformedHolePunchRect() - drawRect=(x=%d,y=%d,width=%d,height=%d) clipRect=(x=%d,y=%d,width=%d,height=%d) clippedRect=(x=%d,y=%d,width=%d,height=%d).",
+        drawRectInWebKitDocumentCoordination.x(), drawRectInWebKitDocumentCoordination.y(), drawRectInWebKitDocumentCoordination.width(), drawRectInWebKitDocumentCoordination.height(),
+        m_holePunchClipRect.x(), m_holePunchClipRect.y(), m_holePunchClipRect.width(), m_holePunchClipRect.height(),
+        drawRect.x(), drawRect.y(), drawRect.width(), drawRect.height());
+#endif
+
+    return getTransformedRect(m_bounds, drawRect, m_drawTransform);
+}
+
+void LayerCompositingThread::drawTextures(int positionLocation, int texCoordLocation, const FloatRect& visibleRect)
+{
+    float texcoords[4 * 2] = { 0, 0,  0, 1,  1, 1,  1, 0 };
+
+    if (m_pluginView) {
+        if (m_isVisible) {
+            // The layer contains Flash, video, or other plugin contents.
+            m_pluginBuffer = m_pluginView->lockFrontBufferForRead();
+
+            if (!m_pluginBuffer)
+                return;
+
+            if (!BlackBerry::Platform::Graphics::lockAndBindBufferGLTexture(m_pluginBuffer, GL_TEXTURE_2D)) {
+                m_pluginView->unlockFrontBuffer();
+                return;
+            }
+
+            m_layerRenderer->addLayerToReleaseTextureResourcesList(this);
+
+            glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, &m_transformedBounds);
+            glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
+            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+        }
+        return;
+    }
+#if ENABLE(VIDEO)
+    if (m_mediaPlayer) {
+        if (m_isVisible) {
+            // We need to specify the media player location in contents coordinates. The 'visibleRect'
+            // specifies the content region covered by our viewport. So we transform from our
+            // normalized device coordinates [-1, 1] to the 'visibleRect'.
+            float vrw2 = visibleRect.width() / 2.0;
+            float vrh2 = visibleRect.height() / 2.0;
+            float x = m_transformedBounds.p1().x() * vrw2 + vrw2 + visibleRect.x();
+            float y = -m_transformedBounds.p1().y() * vrh2 + vrh2 + visibleRect.y();
+            m_mediaPlayer->paint(0, IntRect((int)(x + 0.5), (int)(y + 0.5), m_bounds.width(), m_bounds.height()));
+            MediaPlayerPrivate* mpp = static_cast<MediaPlayerPrivate*>(m_mediaPlayer->platformMedia().media.qnxMediaPlayer);
+            mpp->drawBufferingAnimation(m_drawTransform, positionLocation, texCoordLocation);
+        }
+        return;
+    }
+#endif
+#if ENABLE(WEBGL)
+    if (layerType() == LayerData::WebGLLayer) {
+        pthread_mutex_lock(m_frontBufferLock);
+        glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, &m_transformedBounds);
+        float canvasWidthRatio = 1.0f;
+        float canvasHeightRatio = 1.0f;
+        float upsideDown[4 * 2] = { 0, 1,  0, 1 - canvasHeightRatio,  canvasWidthRatio, 1 - canvasHeightRatio,  canvasWidthRatio, 1 };
+        // Flip the texture Y axis because OpenGL and Skia have different origins
+        glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, upsideDown);
+        glBindTexture(GL_TEXTURE_2D, m_texID);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+        pthread_mutex_unlock(m_frontBufferLock);
+        // FIXME: If the canvas/texture is larger than 2048x2048, then we'll die here
+        return;
+    }
+#endif
+    if (m_texID) {
+        m_layerRenderer->addLayerToReleaseTextureResourcesList(this);
+        pthread_mutex_lock(m_frontBufferLock);
+
+        glDisable(GL_SCISSOR_TEST);
+        glBindTexture(GL_TEXTURE_2D, m_texID);
+        glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, &m_transformedBounds);
+        float upsideDown[4 * 2] = { 0, 1,  0, 0,  1, 0,  1, 1 };
+        glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, upsideDown);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+        return;
+    }
+
+    m_tiler->drawTextures(this, positionLocation, texCoordLocation);
+}
+
+void LayerCompositingThread::drawSurface(const TransformationMatrix& drawTransform, LayerCompositingThread* mask, int positionLocation, int texCoordLocation)
+{
+    if (m_layerRenderer->layerAlreadyOnSurface(this)) {
+        unsigned texID = layerRendererSurface()->texture()->textureId();
+        if (!texID) {
+            ASSERT_NOT_REACHED();
+            return;
+        }
+        textureCacheCompositingThread()->textureAccessed(layerRendererSurface()->texture());
+        glBindTexture(GL_TEXTURE_2D, texID);
+
+        if (mask) {
+            glActiveTexture(GL_TEXTURE1);
+            mask->bindContentsTexture();
+            glActiveTexture(GL_TEXTURE0);
+        }
+
+        FloatQuad surfaceQuad = getTransformedRect(m_bounds, IntRect(IntPoint::zero(), m_bounds), drawTransform);
+        glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, &surfaceQuad);
+
+        float texcoords[4 * 2] = { 0, 0,  0, 1,  1, 1,  1, 0 };
+        glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+    }
+}
+
+void LayerCompositingThread::drawMissingTextures(int positionLocation, int texCoordLocation, const FloatRect& visibleRect)
+{
+    if (m_pluginView || m_texID)
+        return;
+
+#if ENABLE(VIDEO)
+    if (m_mediaPlayer)
+        return;
+#endif
+
+    m_tiler->drawMissingTextures(this, positionLocation, texCoordLocation);
+}
+
+void LayerCompositingThread::releaseTextureResources()
+{
+    if (m_pluginView && m_pluginBuffer) {
+        BlackBerry::Platform::Graphics::releaseBufferGLTexture(m_pluginBuffer);
+        m_pluginBuffer = 0;
+        m_pluginView->unlockFrontBuffer();
+    }
+    if (m_texID && m_frontBufferLock)
+        pthread_mutex_unlock(m_frontBufferLock);
+}
+
+void LayerCompositingThread::setPluginView(PluginView* pluginView)
+{
+    if (!isCompositingThread()) {
+        dispatchSyncCompositingMessage(BlackBerry::Platform::createMethodCallMessage(
+            &LayerCompositingThread::setPluginView,
+            this,
+            pluginView));
+        return;
+    }
+
+    m_pluginView = pluginView;
+}
+
+#if ENABLE(VIDEO)
+void LayerCompositingThread::setMediaPlayer(MediaPlayer* mediaPlayer)
+{
+    if (!isCompositingThread()) {
+        dispatchSyncCompositingMessage(BlackBerry::Platform::createMethodCallMessage(
+            &LayerCompositingThread::setMediaPlayer,
+            this,
+            mediaPlayer));
+        return;
+    }
+
+    m_mediaPlayer = mediaPlayer;
+}
+#endif
+
+void LayerCompositingThread::clearAnimations()
+{
+    // Animations don't use thread safe refcounting, and must only be
+    // touched when the two threads are in sync.
+    if (!isCompositingThread()) {
+        dispatchSyncCompositingMessage(BlackBerry::Platform::createMethodCallMessage(
+            &LayerCompositingThread::clearAnimations,
+            this));
+        return;
+    }
+
+    m_runningAnimations.clear();
+    m_suspendedAnimations.clear();
+}
+
+void LayerCompositingThread::removeSublayer(LayerCompositingThread* sublayer)
+{
+    ASSERT(isCompositingThread());
+
+    int foundIndex = indexOfSublayer(sublayer);
+    if (foundIndex == -1)
+        return;
+
+    sublayer->setSuperlayer(0);
+    m_sublayers.remove(foundIndex);
+}
+
+int LayerCompositingThread::indexOfSublayer(const LayerCompositingThread* reference)
+{
+    for (size_t i = 0; i < m_sublayers.size(); i++) {
+        if (m_sublayers[i] == reference)
+            return i;
+    }
+    return -1;
+}
+
+const LayerCompositingThread* LayerCompositingThread::rootLayer() const
+{
+    const LayerCompositingThread* layer = this;
+    for (LayerCompositingThread* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
+    return layer;
+}
+
+void LayerCompositingThread::removeFromSuperlayer()
+{
+    if (m_superlayer)
+        m_superlayer->removeSublayer(this);
+}
+
+void LayerCompositingThread::setSublayers(const Vector<RefPtr<LayerCompositingThread> >& sublayers)
+{
+    if (sublayers == m_sublayers)
+        return;
+
+    while (m_sublayers.size()) {
+        RefPtr<LayerCompositingThread> layer = m_sublayers[0].get();
+        ASSERT(layer->superlayer());
+        layer->removeFromSuperlayer();
+    }
+
+    m_sublayers.clear();
+
+    size_t listSize = sublayers.size();
+    for (size_t i = 0; i < listSize; i++) {
+        RefPtr<LayerCompositingThread> sublayer = sublayers[i];
+        sublayer->removeFromSuperlayer();
+        sublayer->setSuperlayer(this);
+        m_sublayers.insert(i, sublayer);
+    }
+}
+
+void LayerCompositingThread::updateTextureContentsIfNeeded()
+{
+    if (m_texID || pluginView())
+        return;
+
+#if ENABLE(VIDEO)
+    if (mediaPlayer())
+        return;
+#endif
+
+    m_tiler->uploadTexturesIfNeeded();
+}
+
+void LayerCompositingThread::setVisible(bool visible)
+{
+    if (visible == m_visible)
+        return;
+
+    m_visible = visible;
+
+    if (m_texID || pluginView())
+        return;
+
+#if ENABLE(VIDEO)
+    if (mediaPlayer())
+        return;
+#endif
+
+    m_tiler->layerVisibilityChanged(visible);
+}
+
+void LayerCompositingThread::setNeedsCommit()
+{
+    if (m_layerRenderer)
+        m_layerRenderer->setNeedsCommit();
+}
+
+void LayerCompositingThread::scheduleCommit()
+{
+    if (!isWebKitThread()) {
+        if (m_commitScheduled)
+            return;
+
+        m_commitScheduled = true;
+
+        dispatchWebKitMessage(BlackBerry::Platform::createMethodCallMessage(&LayerCompositingThread::scheduleCommit, this));
+        return;
+    }
+
+    m_commitScheduled = false;
+
+    // FIXME: The only way to get at our LayerWebKitThread is to go through the tiler.
+    if (LayerWebKitThread* layer = m_tiler->layer())
+        layer->setNeedsCommit();
+}
+
+bool LayerCompositingThread::updateAnimations(double currentTime)
+{
+    // The commit mechanism always overwrites our state with state from the
+    // WebKit thread. This means we have to restore the last animated value for
+    // suspended animations.
+    for (size_t i = 0; i < m_suspendedAnimations.size(); ++i) {
+        LayerAnimation* animation = m_suspendedAnimations[i].get();
+        // From looking at the WebCore code, it appears that when the animation
+        // is paused, the timeOffset is modified so it will be an appropriate
+        // elapsedTime.
+        double elapsedTime = animation->timeOffset();
+        animation->apply(this, elapsedTime);
+    }
+
+    for (size_t i = 0; i < m_runningAnimations.size(); ++i) {
+        LayerAnimation* animation = m_runningAnimations[i].get();
+        double elapsedTime = (m_suspendTime ? m_suspendTime : currentTime) - animation->startTime() + animation->timeOffset();
+        animation->apply(this, elapsedTime);
+    }
+
+    return !m_runningAnimations.isEmpty();
+}
+
+bool LayerCompositingThread::hasVisibleHolePunchRect() const
+{
+    if (m_pluginView && !m_isVisible)
+        return false;
+
+#if ENABLE(VIDEO)
+    if (m_mediaPlayer && !m_isVisible)
+        return false;
+#endif
+
+    return hasHolePunchRect();
+}
+
+void LayerCompositingThread::createLayerRendererSurface()
+{
+    ASSERT(!m_layerRendererSurface);
+    m_layerRendererSurface = adoptPtr(new LayerRendererSurface(m_layerRenderer, this));
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h
new file mode 100644 (file)
index 0000000..e1de74e
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef LayerCompositingThread_h
+#define LayerCompositingThread_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatQuad.h"
+#include "LayerData.h"
+#include "LayerRendererSurface.h"
+#include "LayerTiler.h"
+
+#include <BlackBerryPlatformGuardedPointer.h>
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace BlackBerry {
+namespace Platform {
+namespace Graphics {
+class Buffer;
+}
+}
+}
+
+namespace WebCore {
+
+class DestroyOnCompositingThread;
+class LayerRenderer;
+
+class LayerCompositingThread : public ThreadSafeRefCounted<LayerCompositingThread>, public LayerData, public BlackBerry::Platform::GuardedPointerBase {
+public:
+    static PassRefPtr<LayerCompositingThread> create(LayerType, PassRefPtr<LayerTiler>);
+
+    ~LayerCompositingThread();
+
+    // Thread safe
+    void setPluginView(PluginView*);
+#if ENABLE(VIDEO)
+    void setMediaPlayer(MediaPlayer*);
+#endif
+    void clearAnimations();
+
+    // Not thread safe
+
+    // Returns true if we have an animation
+    bool updateAnimations(double currentTime);
+    void updateTextureContentsIfNeeded();
+    void bindContentsTexture()
+    {
+        if (m_tiler)
+            m_tiler->bindContentsTexture();
+    }
+
+    const LayerCompositingThread* rootLayer() const;
+    void setSublayers(const Vector<RefPtr<LayerCompositingThread> >&);
+    const Vector<RefPtr<LayerCompositingThread> >& getSublayers() const { return m_sublayers; }
+    void setSuperlayer(LayerCompositingThread* superlayer) { m_superlayer = superlayer; }
+    LayerCompositingThread* superlayer() const { return m_superlayer; }
+
+    // The layer renderer must be set if the layer has been rendered
+    void setLayerRenderer(LayerRenderer*);
+
+    void setDrawTransform(const TransformationMatrix&);
+    const TransformationMatrix& drawTransform() const { return m_drawTransform; }
+
+    void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
+    float drawOpacity() const { return m_drawOpacity; }
+
+    void createLayerRendererSurface();
+    LayerRendererSurface* layerRendererSurface() const { return m_layerRendererSurface.get(); }
+    void clearLayerRendererSurface() { m_layerRendererSurface.clear(); }
+
+    void setMaskLayer(LayerCompositingThread* maskLayer) { m_maskLayer = maskLayer; }
+    LayerCompositingThread* maskLayer() const { return m_maskLayer.get(); }
+
+    void setReplicaLayer(LayerCompositingThread* layer) { m_replicaLayer = layer; }
+    LayerCompositingThread* replicaLayer() const { return m_replicaLayer.get(); }
+
+    FloatRect getDrawRect() const { return m_drawRect; }
+    const FloatQuad& getTransformedBounds() const { return m_transformedBounds; }
+    FloatQuad getTransformedHolePunchRect() const;
+
+    void deleteTextures();
+
+    void drawTextures(int positionLocation, int texCoordLocation, const FloatRect& visibleRect);
+    bool hasMissingTextures() const { return m_tiler ? m_tiler->hasMissingTextures() : false; }
+    void drawMissingTextures(int positionLocation, int texCoordLocation, const FloatRect& visibleRect);
+    void drawSurface(const TransformationMatrix&, LayerCompositingThread* mask, int positionLocation, int texCoordLocation);
+    bool isDirty() const { return m_tiler ? m_tiler->hasDirtyTiles() : false; }
+
+    void releaseTextureResources();
+
+    // Layer visibility is determined by the LayerRenderer when drawing.
+    // So we don't have an accurate value for visibility until it's too late,
+    // but the attribute still is useful.
+    bool isVisible() const { return m_visible; }
+    void setVisible(bool);
+
+    // This will cause a commit of the whole layer tree on the WebKit thread,
+    // sometime after rendering is finished. Used when rendering results in a
+    // need for commit, for example when a dirty layer becomes visible.
+    void setNeedsCommit();
+
+    // Normally you would schedule a commit from the webkit thread, but
+    // this allows you to do it from the compositing thread.
+    void scheduleCommit();
+
+    // These two functions are used to update animated properties in LayerAnimation.
+    void setOpacity(float opacity) { m_opacity = opacity; }
+    void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; }
+
+    bool hasRunningAnimations() const { return !m_runningAnimations.isEmpty(); }
+
+    bool hasVisibleHolePunchRect() const;
+
+private:
+    LayerCompositingThread(LayerType, PassRefPtr<LayerTiler>);
+
+    friend class DestroyOnCompositingThread;
+    void destroyOnCompositingThread();
+
+    void updateTileContents(const IntRect& tile);
+
+    void removeFromSuperlayer();
+
+    size_t numSublayers() const { return m_sublayers.size(); }
+
+    // Returns the index of the sublayer or -1 if not found.
+    int indexOfSublayer(const LayerCompositingThread*);
+
+    // This should only be called from removeFromSuperlayer.
+    void removeSublayer(LayerCompositingThread*);
+
+    LayerRenderer* m_layerRenderer;
+
+    typedef Vector<RefPtr<LayerCompositingThread> > LayerList;
+    LayerList m_sublayers;
+    LayerCompositingThread* m_superlayer;
+
+    // Vertex data for the bounds of this layer
+    FloatQuad m_transformedBounds;
+    // The bounding rectangle of the transformed layer
+    FloatRect m_drawRect;
+
+    OwnPtr<LayerRendererSurface> m_layerRendererSurface;
+
+    RefPtr<LayerCompositingThread> m_maskLayer;
+    RefPtr<LayerCompositingThread> m_replicaLayer;
+
+    BlackBerry::Platform::Graphics::Buffer* m_pluginBuffer;
+
+    // The global property values, after concatenation with parent values
+    TransformationMatrix m_drawTransform;
+    float m_drawOpacity;
+
+    bool m_visible;
+    bool m_commitScheduled;
+
+    RefPtr<LayerTiler> m_tiler;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif