Diff
Modified: trunk/Source/WebKit2/ChangeLog (177275 => 177276)
--- trunk/Source/WebKit2/ChangeLog 2014-12-15 09:58:39 UTC (rev 177275)
+++ trunk/Source/WebKit2/ChangeLog 2014-12-15 10:39:49 UTC (rev 177276)
@@ -1,3 +1,41 @@
+2014-12-15 Gwang Yoon Hwang <y...@igalia.com>
+
+ Add initial implementation of ThreadSafeCoordinatedSurface, ThreadedCompositor, and SimpleViewportController
+ https://bugs.webkit.org/show_bug.cgi?id=118383
+
+ Reviewed by Martin Robinson.
+
+ Implements an initial version of the Threaded Compositor.
+
+ Threaded Compositor is a variant of Coordinated Graphics implementation.
+ Basic structure of the implementaion is simliar, thus, Threaded
+ Compositor reuses lots of classes from Coordinated Graphics. However,
+ instead of compositing on UI Process, Threaded Compositor performs
+ compositing on a dedicate thread of Web Process.
+
+ No new test, because it is in experimental stage.
+
+ * Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp:
+ (WebKit::CoordinatedGraphicsScene::CoordinatedGraphicsScene):
+ Removed a assertion not to force its creation in the main thread. In
+ the Threaded Compositor, it can be created in the dedicated thread.
+
+ * Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.cpp: Added.
+ * Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.h: Added.
+ Implements a surface using ImageBuffer as a backend to use in the Web
+ Process.
+
+ * Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h: Added.
+ * Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp: Added.
+ Implements a compositor which runs on the created thread. It owns
+ SimpleViewportController and CoordinatedGraphicsScene to render scene on the
+ actual surface.
+
+ * Shared/CoordinatedGraphics/SimpleViewportController.cpp: Added.
+ * Shared/CoordinatedGraphics/SimpleViewportController.h: Added.
+ This class is responsible to handle scale factor and scrolling position
+ with a simplifed logic in the compositing thread.
+
2014-12-14 Andreas Kling <akl...@apple.com>
Replace PassRef with Ref/Ref&& across the board.
Modified: trunk/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp (177275 => 177276)
--- trunk/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp 2014-12-15 09:58:39 UTC (rev 177275)
+++ trunk/Source/WebKit2/Shared/CoordinatedGraphics/CoordinatedGraphicsScene.cpp 2014-12-15 10:39:49 UTC (rev 177276)
@@ -54,7 +54,6 @@
, m_rootLayerID(InvalidCoordinatedLayerID)
, m_viewBackgroundColor(Color::white)
{
- ASSERT(isMainThread());
}
CoordinatedGraphicsScene::~CoordinatedGraphicsScene()
Added: trunk/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp (0 => 177276)
--- trunk/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp (rev 0)
+++ trunk/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp 2014-12-15 10:39:49 UTC (rev 177276)
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Benjamin Poulain <benja...@webkit.org>
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+#include "SimpleViewportController.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+SimpleViewportController::SimpleViewportController(Client* client)
+ : m_client(client)
+ , m_contentsPosition(FloatPoint())
+ , m_contentsSize(FloatSize())
+ , m_viewportSize(FloatSize())
+ , m_allowsUserScaling(false)
+ , m_initiallyFitToViewport(true)
+ , m_hasViewportAttribute(false)
+{
+ resetViewportToDefaultState();
+}
+
+void SimpleViewportController::didChangeViewportSize(const FloatSize& newSize)
+{
+ if (newSize.isEmpty())
+ return;
+
+ m_viewportSize = newSize;
+ updateMinimumScaleToFit();
+ syncVisibleContents();
+}
+
+void SimpleViewportController::didChangeContentsSize(const IntSize& newSize)
+{
+ m_contentsSize = newSize;
+
+ updateMinimumScaleToFit();
+
+ if (m_initiallyFitToViewport) {
+ // Restrict scale factors to m_minimumScaleToFit.
+ ASSERT(m_minimumScaleToFit > 0);
+ m_rawAttributes.initialScale = m_minimumScaleToFit;
+ restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes);
+ }
+
+ syncVisibleContents();
+}
+
+void SimpleViewportController::didChangeViewportAttribute(const ViewportAttributes& newAttributes)
+{
+ if (newAttributes.layoutSize.isEmpty()) {
+ resetViewportToDefaultState();
+ return;
+ }
+
+ m_hasViewportAttribute = true;
+
+ m_rawAttributes = newAttributes;
+ m_allowsUserScaling = m_rawAttributes.userScalable;
+ m_initiallyFitToViewport = m_rawAttributes.initialScale < 0;
+
+ if (!m_initiallyFitToViewport)
+ restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes);
+
+ updateMinimumScaleToFit();
+
+ syncVisibleContents();
+}
+
+void SimpleViewportController::scrollBy(const IntSize& scrollOffset)
+{
+ m_contentsPosition.move(scrollOffset);
+ m_contentsPosition = boundContentsPosition(m_contentsPosition);
+
+ syncVisibleContents();
+}
+
+void SimpleViewportController::scrollTo(const IntPoint& position)
+{
+ if (m_contentsPosition == boundContentsPosition(position))
+ return;
+
+ m_contentsPosition = boundContentsPosition(position);
+ syncVisibleContents();
+}
+
+void SimpleViewportController::syncVisibleContents()
+{
+ if (m_viewportSize.isEmpty() || m_contentsSize.isEmpty())
+ return;
+
+ m_client->didChangeVisibleRect();
+}
+
+FloatRect SimpleViewportController::visibleContentsRect() const
+{
+ FloatRect visibleContentsRect(boundContentsPosition(m_contentsPosition), visibleContentsSize());
+ visibleContentsRect.intersect(FloatRect(FloatPoint::zero(), m_contentsSize));
+
+ return visibleContentsRect;
+}
+
+FloatSize SimpleViewportController::visibleContentsSize() const
+{
+ return FloatSize(m_viewportSize.width() / m_pageScaleFactor, m_viewportSize.height() / m_pageScaleFactor);
+}
+
+FloatPoint SimpleViewportController::boundContentsPositionAtScale(const FloatPoint& framePosition, float scale) const
+{
+ // We need to floor the viewport here as to allow aligning the content in device units. If not,
+ // it might not be possible to scroll the last pixel and that affects fixed position elements.
+ return FloatPoint(
+ clampTo(framePosition.x(), .0f, std::max(.0f, m_contentsSize.width() - floorf(m_viewportSize.width() / scale))),
+ clampTo(framePosition.y(), .0f, std::max(.0f, m_contentsSize.height() - floorf(m_viewportSize.height() / scale))));
+}
+
+FloatPoint SimpleViewportController::boundContentsPosition(const FloatPoint& framePosition) const
+{
+ return boundContentsPositionAtScale(framePosition, m_pageScaleFactor);
+}
+
+bool fuzzyCompare(float a, float b, float epsilon)
+{
+ return std::abs(a - b) < epsilon;
+}
+
+bool SimpleViewportController::updateMinimumScaleToFit()
+{
+ if (m_viewportSize.isEmpty() || m_contentsSize.isEmpty() || !m_hasViewportAttribute)
+ return false;
+
+ bool currentlyScaledToFit = fuzzyCompare(m_pageScaleFactor, m_minimumScaleToFit, 0.0001);
+
+ float minimumScale = computeMinimumScaleFactorForContentContained(m_rawAttributes, roundedIntSize(m_viewportSize), roundedIntSize(m_contentsSize));
+
+ if (minimumScale <= 0)
+ return false;
+
+ if (!fuzzyCompare(minimumScale, m_minimumScaleToFit, 0.0001)) {
+ m_minimumScaleToFit = minimumScale;
+
+ if (currentlyScaledToFit)
+ m_pageScaleFactor = m_minimumScaleToFit;
+ else {
+ // Ensure the effective scale stays within bounds.
+ float boundedScale = innerBoundedViewportScale(m_pageScaleFactor);
+ if (!fuzzyCompare(boundedScale, m_pageScaleFactor, 0.0001))
+ m_pageScaleFactor = boundedScale;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+float SimpleViewportController::innerBoundedViewportScale(float viewportScale) const
+{
+ return clampTo(viewportScale, m_minimumScaleToFit, m_rawAttributes.maximumScale);
+}
+
+void SimpleViewportController::resetViewportToDefaultState()
+{
+ m_hasViewportAttribute = false;
+ m_pageScaleFactor = 1;
+ m_minimumScaleToFit = 1;
+
+ // Initializing Viewport Raw Attributes to avoid random negative or infinity scale factors
+ // if there is a race condition between the first layout and setting the viewport attributes for the first time.
+ m_rawAttributes.minimumScale = 1;
+ m_rawAttributes.maximumScale = 1;
+ m_rawAttributes.userScalable = m_allowsUserScaling;
+
+ // The initial scale might be implicit and set to -1, in this case we have to infer it
+ // using the viewport size and the final layout size.
+ // To be able to assert for valid scale we initialize it to -1.
+ m_rawAttributes.initialScale = -1;
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
Added: trunk/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.h (0 => 177276)
--- trunk/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.h (rev 0)
+++ trunk/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.h 2014-12-15 10:39:49 UTC (rev 177276)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Benjamin Poulain <benja...@webkit.org>
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SimpleViewportController_h
+#define SimpleViewportController_h
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatRect.h>
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/IntSize.h>
+#include <WebCore/ViewportArguments.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebKit {
+
+class SimpleViewportController {
+ WTF_MAKE_NONCOPYABLE(SimpleViewportController);
+public:
+ class Client {
+ public:
+ virtual void didChangeVisibleRect() = 0;
+ };
+
+ explicit SimpleViewportController(Client*);
+
+ void didChangeViewportSize(const WebCore::FloatSize&);
+ void didChangeContentsSize(const WebCore::IntSize&);
+ void didChangeViewportAttribute(const WebCore::ViewportAttributes&);
+
+ void scrollBy(const WebCore::IntSize&);
+ void scrollTo(const WebCore::IntPoint&);
+
+ WebCore::FloatRect visibleContentsRect() const;
+ float pageScaleFactor() const { return m_pageScaleFactor; }
+
+private:
+
+ WebCore::FloatSize visibleContentsSize() const;
+
+ void syncVisibleContents();
+
+ void applyScaleAfterRenderingContents(float scale);
+ void applyPositionAfterRenderingContents(const WebCore::FloatPoint& pos);
+
+ WebCore::FloatPoint boundContentsPosition(const WebCore::FloatPoint&) const;
+ WebCore::FloatPoint boundContentsPositionAtScale(const WebCore::FloatPoint&, float scale) const;
+
+ bool updateMinimumScaleToFit();
+ float innerBoundedViewportScale(float) const;
+
+ void resetViewportToDefaultState();
+
+ Client* m_client;
+
+ WebCore::FloatPoint m_contentsPosition;
+ WebCore::FloatSize m_contentsSize;
+ WebCore::FloatSize m_viewportSize;
+ float m_pageScaleFactor;
+
+ bool m_allowsUserScaling;
+ float m_minimumScaleToFit;
+ bool m_initiallyFitToViewport;
+
+ bool m_hasViewportAttribute;
+ WebCore::ViewportAttributes m_rawAttributes;
+};
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
+
+#endif // SimpleViewportController_h
Added: trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.cpp (0 => 177276)
--- trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.cpp (rev 0)
+++ trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.cpp 2014-12-15 10:39:49 UTC (rev 177276)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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(COORDINATED_GRAPHICS)
+#include "ThreadSafeCoordinatedSurface.h"
+
+#include <WebCore/TextureMapperGL.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+PassRefPtr<ThreadSafeCoordinatedSurface> ThreadSafeCoordinatedSurface::create(const IntSize& size, CoordinatedSurface::Flags flags)
+{
+ return adoptRef(new ThreadSafeCoordinatedSurface(size, flags, ImageBuffer::create(size)));
+}
+
+PassRefPtr<ThreadSafeCoordinatedSurface> ThreadSafeCoordinatedSurface::create(const IntSize& size, CoordinatedSurface::Flags flags, std::unique_ptr<ImageBuffer> buffer)
+{
+ return adoptRef(new ThreadSafeCoordinatedSurface(size, flags, WTF::move(buffer)));
+}
+
+ThreadSafeCoordinatedSurface::ThreadSafeCoordinatedSurface(const IntSize& size, CoordinatedSurface::Flags flags, std::unique_ptr<ImageBuffer> buffer)
+ : CoordinatedSurface(size, flags)
+ , m_imageBuffer(WTF::move(buffer))
+{
+}
+
+ThreadSafeCoordinatedSurface::~ThreadSafeCoordinatedSurface()
+{
+}
+
+void ThreadSafeCoordinatedSurface::paintToSurface(const IntRect& rect, CoordinatedSurface::Client* client)
+{
+ ASSERT(client);
+
+ GraphicsContext* context = beginPaint(rect);
+ client->paintToSurfaceContext(context);
+ endPaint();
+}
+
+GraphicsContext* ThreadSafeCoordinatedSurface::beginPaint(const IntRect& rect)
+{
+ ASSERT(m_imageBuffer);
+ GraphicsContext* graphicsContext = m_imageBuffer->context();
+ graphicsContext->save();
+ graphicsContext->clip(rect);
+ graphicsContext->translate(rect.x(), rect.y());
+ return graphicsContext;
+}
+
+void ThreadSafeCoordinatedSurface::endPaint()
+{
+ ASSERT(m_imageBuffer);
+ m_imageBuffer->context()->restore();
+}
+
+void ThreadSafeCoordinatedSurface::copyToTexture(PassRefPtr<BitmapTexture> passTexture, const IntRect& target, const IntPoint& sourceOffset)
+{
+ RefPtr<BitmapTexture> texture(passTexture);
+
+ ASSERT(m_imageBuffer);
+ RefPtr<Image> image = m_imageBuffer->copyImage(DontCopyBackingStore);
+ texture->updateContents(image.get(), target, sourceOffset, BitmapTexture::UpdateCanModifyOriginalImageData);
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS)
Added: trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.h (0 => 177276)
--- trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.h (rev 0)
+++ trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadSafeCoordinatedSurface.h 2014-12-15 10:39:49 UTC (rev 177276)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 ThreadSafeCoordinatedSurface_h
+#define ThreadSafeCoordinatedSurface_h
+
+#if USE(COORDINATED_GRAPHICS)
+#include <WebCore/CoordinatedSurface.h>
+#include <WebCore/ImageBuffer.h>
+
+namespace WebKit {
+
+class ThreadSafeCoordinatedSurface : public WebCore::CoordinatedSurface {
+public:
+ virtual ~ThreadSafeCoordinatedSurface();
+
+ // Create a new ThreadSafeCoordinatedSurface and allocate either a GraphicsSurface or a ImageBuffer as backing.
+ static PassRefPtr<ThreadSafeCoordinatedSurface> create(const WebCore::IntSize&, WebCore::CoordinatedSurface::Flags);
+
+ virtual void paintToSurface(const WebCore::IntRect&, WebCore::CoordinatedSurface::Client*) override;
+ virtual void copyToTexture(PassRefPtr<WebCore::BitmapTexture>, const WebCore::IntRect& target, const WebCore::IntPoint& sourceOffset) override;
+
+private:
+ ThreadSafeCoordinatedSurface(const WebCore::IntSize&, WebCore::CoordinatedSurface::Flags, std::unique_ptr<WebCore::ImageBuffer>);
+
+ WebCore::GraphicsContext* beginPaint(const WebCore::IntRect&);
+ void endPaint();
+
+ // Create a ThreadSafeCoordinatedSurface referencing an exisiting ImageBuffer
+ static PassRefPtr<ThreadSafeCoordinatedSurface> create(const WebCore::IntSize&, WebCore::CoordinatedSurface::Flags, std::unique_ptr<WebCore::ImageBuffer>);
+
+ std::unique_ptr<WebCore::ImageBuffer> m_imageBuffer;
+};
+
+} // namespace WebKit
+
+#endif // USE(COORDINATED_GRAPHICS)
+
+#endif // ThreadSafeCoordinatedSurface_h
Added: trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp (0 => 177276)
--- trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp (rev 0)
+++ trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp 2014-12-15 10:39:49 UTC (rev 177276)
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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(COORDINATED_GRAPHICS_THREADED)
+#include "ThreadedCompositor.h"
+
+#include <WebCore/TransformationMatrix.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/RunLoop.h>
+#include <wtf/StdLibExtras.h>
+
+#if USE(OPENGL_ES_2)
+#include <GLES2/gl2.h>
+#else
+#include <GL/gl.h>
+#endif
+
+using namespace WebCore;
+
+namespace WebKit {
+
+class CompositingRunLoop {
+ WTF_MAKE_NONCOPYABLE(CompositingRunLoop);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ CompositingRunLoop(std::function<void()> updateFunction)
+ : m_runLoop(RunLoop::current())
+ , m_updateTimer(m_runLoop, this, &CompositingRunLoop::updateTimerFired)
+ , m_updateFunction(WTF::move(updateFunction))
+ {
+ }
+
+ void callOnCompositingRunLoop(std::function<void()> function)
+ {
+ if (&m_runLoop == &RunLoop::current()) {
+ function();
+ return;
+ }
+
+ m_runLoop.dispatch(WTF::move(function));
+ }
+
+ void setUpdateTimer(double interval = 0)
+ {
+ if (m_updateTimer.isActive())
+ return;
+
+ m_updateTimer.startOneShot(interval);
+ }
+
+ void stopUpdateTimer()
+ {
+ if (m_updateTimer.isActive())
+ m_updateTimer.stop();
+ }
+
+ RunLoop& runLoop()
+ {
+ return m_runLoop;
+ }
+
+private:
+
+ void updateTimerFired()
+ {
+ m_updateFunction();
+ }
+
+ RunLoop& m_runLoop;
+ RunLoop::Timer<CompositingRunLoop> m_updateTimer;
+ std::function<void()> m_updateFunction;
+};
+
+PassRefPtr<ThreadedCompositor> ThreadedCompositor::create(Client* client)
+{
+ return adoptRef(new ThreadedCompositor(client));
+}
+
+ThreadedCompositor::ThreadedCompositor(Client* client)
+ : m_client(client)
+ , m_scene(adoptRef(new CoordinatedGraphicsScene(this)))
+ , m_viewportController(std::make_unique<SimpleViewportController>(this))
+ , m_threadIdentifier(0)
+{
+ createCompositingThread();
+}
+
+ThreadedCompositor::~ThreadedCompositor()
+{
+ terminateCompositingThread();
+}
+
+void ThreadedCompositor::setNeedsDisplay()
+{
+ RefPtr<ThreadedCompositor> protector(this);
+ callOnCompositingThread([=] {
+ protector->scheduleDisplayIfNeeded();
+ });
+}
+
+void ThreadedCompositor::setNativeSurfaceHandleForCompositing(uint64_t handle)
+{
+ RefPtr<ThreadedCompositor> protector(this);
+ callOnCompositingThread([=] {
+ protector->m_nativeSurfaceHandle = handle;
+ protector->m_scene->setActive(true);
+ });
+}
+
+
+void ThreadedCompositor::didChangeViewportSize(const IntSize& newSize)
+{
+ RefPtr<ThreadedCompositor> protector(this);
+ callOnCompositingThread([=] {
+ protector->viewportController()->didChangeViewportSize(newSize);
+ });
+}
+
+void ThreadedCompositor::didChangeViewportAttribute(const ViewportAttributes& attr)
+{
+ RefPtr<ThreadedCompositor> protector(this);
+ callOnCompositingThread([=] {
+ protector->viewportController()->didChangeViewportAttribute(attr);
+ });
+}
+
+void ThreadedCompositor::didChangeContentsSize(const IntSize& size)
+{
+ RefPtr<ThreadedCompositor> protector(this);
+ callOnCompositingThread([=] {
+ protector->viewportController()->didChangeContentsSize(size);
+ });
+}
+
+void ThreadedCompositor::scrollTo(const IntPoint& position)
+{
+ RefPtr<ThreadedCompositor> protector(this);
+ callOnCompositingThread([=] {
+ protector->viewportController()->scrollTo(position);
+ });
+}
+
+void ThreadedCompositor::scrollBy(const IntSize& delta)
+{
+ RefPtr<ThreadedCompositor> protector(this);
+ callOnCompositingThread([=] {
+ protector->viewportController()->scrollBy(delta);
+ });
+}
+
+void ThreadedCompositor::purgeBackingStores()
+{
+ m_client->purgeBackingStores();
+}
+
+void ThreadedCompositor::renderNextFrame()
+{
+ m_client->renderNextFrame();
+}
+
+void ThreadedCompositor::updateViewport()
+{
+ setNeedsDisplay();
+}
+
+void ThreadedCompositor::commitScrollOffset(uint32_t layerID, const IntSize& offset)
+{
+ m_client->commitScrollOffset(layerID, offset);
+}
+
+bool ThreadedCompositor::ensureGLContext()
+{
+ if (!glContext())
+ return false;
+
+ glContext()->makeContextCurrent();
+ // The window size may be out of sync with the page size at this point, and getting
+ // the viewport parameters incorrect, means that the content will be misplaced. Thus
+ // we set the viewport parameters directly from the window size.
+ IntSize contextSize = glContext()->defaultFrameBufferSize();
+ if (m_viewportSize != contextSize) {
+ glViewport(0, 0, contextSize.width(), contextSize.height());
+ m_viewportSize = contextSize;
+ }
+
+ return true;
+}
+
+GLContext* ThreadedCompositor::glContext()
+{
+ if (m_context)
+ return m_context.get();
+
+ if (!m_nativeSurfaceHandle)
+ return 0;
+
+ m_context = GLContext::createContextForWindow(m_nativeSurfaceHandle, GLContext::sharingContext());
+ return m_context.get();
+}
+
+void ThreadedCompositor::scheduleDisplayIfNeeded(double interval)
+{
+ m_compositingRunLoop->setUpdateTimer(interval);
+}
+
+void ThreadedCompositor::didChangeVisibleRect()
+{
+ FloatRect visibleRect = viewportController()->visibleContentsRect();
+ float scale = viewportController()->pageScaleFactor();
+ callOnMainThread([=] {
+ m_client->setVisibleContentsRect(visibleRect, FloatPoint::zero(), scale);
+ });
+
+ setNeedsDisplay();
+}
+
+void ThreadedCompositor::renderLayerTree()
+{
+ if (!m_scene)
+ return;
+
+ if (!ensureGLContext())
+ return;
+
+ FloatRect clipRect(0, 0, m_viewportSize.width(), m_viewportSize.height());
+
+ TransformationMatrix viewportTransform;
+ FloatPoint scrollPostion = viewportController()->visibleContentsRect().location();
+ viewportTransform.scale(viewportController()->pageScaleFactor());
+ viewportTransform.translate(-scrollPostion.x(), -scrollPostion.y());
+
+ m_scene->paintToCurrentGLContext(viewportTransform, 1, clipRect, Color::white, false, scrollPostion);
+
+ glContext()->swapBuffers();
+}
+
+void ThreadedCompositor::updateSceneState(const CoordinatedGraphicsState& state)
+{
+ m_scene->appendUpdate(bind(&CoordinatedGraphicsScene::commitSceneState, m_scene.get(), state));
+ setNeedsDisplay();
+}
+
+void ThreadedCompositor::callOnCompositingThread(std::function<void()> function)
+{
+ m_compositingRunLoop->callOnCompositingRunLoop(WTF::move(function));
+}
+
+void ThreadedCompositor::compositingThreadEntry(void* coordinatedCompositor)
+{
+ static_cast<ThreadedCompositor*>(coordinatedCompositor)->runCompositingThread();
+}
+
+void ThreadedCompositor::createCompositingThread()
+{
+ if (m_threadIdentifier)
+ return;
+
+ MutexLocker locker(m_initializeRunLoopConditionMutex);
+ m_threadIdentifier = createThread(compositingThreadEntry, this, "WebCore: ThreadedCompositor");
+
+ m_initializeRunLoopCondition.wait(m_initializeRunLoopConditionMutex);
+}
+
+void ThreadedCompositor::runCompositingThread()
+{
+ {
+ MutexLocker locker(m_initializeRunLoopConditionMutex);
+
+ m_compositingRunLoop = std::make_unique<CompositingRunLoop>([&] {
+ renderLayerTree();
+ });
+
+ m_initializeRunLoopCondition.signal();
+ }
+
+ m_compositingRunLoop->runLoop().run();
+
+ m_compositingRunLoop->stopUpdateTimer();
+ m_scene->purgeGLResources();
+
+ {
+ MutexLocker locker(m_terminateRunLoopConditionMutex);
+ m_compositingRunLoop = nullptr;
+ m_context.clear();
+ m_terminateRunLoopCondition.signal();
+ }
+
+ detachThread(m_threadIdentifier);
+}
+
+void ThreadedCompositor::terminateCompositingThread()
+{
+ MutexLocker locker(m_terminateRunLoopConditionMutex);
+
+ m_scene->detach();
+ m_compositingRunLoop->runLoop().stop();
+
+ m_terminateRunLoopCondition.wait(m_terminateRunLoopConditionMutex);
+}
+
+}
+#endif // USE(COORDINATED_GRAPHICS_THREADED)
Added: trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h (0 => 177276)
--- trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h (rev 0)
+++ trunk/Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h 2014-12-15 10:39:49 UTC (rev 177276)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 ThreadedCompositor_h
+#define ThreadedCompositor_h
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include "CoordinatedGraphicsScene.h"
+#include "SimpleViewportController.h"
+#include <WebCore/GLContext.h>
+#include <WebCore/IntSize.h>
+#include <WebCore/TransformationMatrix.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/Threading.h>
+
+namespace WebCore {
+class CoordinatedGraphicsState;
+}
+
+namespace WebKit {
+class CoordinatedGraphicsScene;
+class CoordinatedGraphicsSceneClient;
+
+class CompositingRunLoop;
+
+class ThreadedCompositor : public SimpleViewportController::Client, public CoordinatedGraphicsSceneClient, public ThreadSafeRefCounted<ThreadedCompositor> {
+ WTF_MAKE_NONCOPYABLE(ThreadedCompositor);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ class Client {
+ public:
+ virtual void setVisibleContentsRect(const WebCore::FloatRect&, const WebCore::FloatPoint&, float) = 0;
+ virtual void purgeBackingStores() = 0;
+ virtual void renderNextFrame() = 0;
+ virtual void commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset) = 0;
+ };
+
+ static PassRefPtr<ThreadedCompositor> create(Client*);
+ virtual ~ThreadedCompositor();
+
+ void setNeedsDisplay();
+
+ void setNativeSurfaceHandleForCompositing(uint64_t);
+
+ void updateSceneState(const WebCore::CoordinatedGraphicsState&);
+
+ void didChangeViewportSize(const WebCore::IntSize&);
+ void didChangeViewportAttribute(const WebCore::ViewportAttributes&);
+ void didChangeContentsSize(const WebCore::IntSize&);
+ void scrollTo(const WebCore::IntPoint&);
+ void scrollBy(const WebCore::IntSize&);
+
+private:
+ ThreadedCompositor(Client*);
+
+ // CoordinatedGraphicsSceneClient
+ virtual void purgeBackingStores() override;
+ virtual void renderNextFrame() override;
+ virtual void updateViewport() override;
+ virtual void commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset) override;
+
+ void renderLayerTree();
+ void scheduleDisplayIfNeeded(double interval = 0);
+ virtual void didChangeVisibleRect() override;
+
+ bool ensureGLContext();
+ WebCore::GLContext* glContext();
+ SimpleViewportController* viewportController() { return m_viewportController.get(); }
+
+ void callOnCompositingThread(std::function<void()>);
+ void createCompositingThread();
+ void runCompositingThread();
+ void terminateCompositingThread();
+ static void compositingThreadEntry(void*);
+
+ Client* m_client;
+ RefPtr<CoordinatedGraphicsScene> m_scene;
+ std::unique_ptr<SimpleViewportController> m_viewportController;
+
+ OwnPtr<WebCore::GLContext> m_context;
+
+ WebCore::IntSize m_viewportSize;
+ uint64_t m_nativeSurfaceHandle;
+
+ std::unique_ptr<CompositingRunLoop> m_compositingRunLoop;
+
+ ThreadIdentifier m_threadIdentifier;
+ ThreadCondition m_initializeRunLoopCondition;
+ Mutex m_initializeRunLoopConditionMutex;
+ ThreadCondition m_terminateRunLoopCondition;
+ Mutex m_terminateRunLoopConditionMutex;
+};
+
+} // namespace WebKit
+
+#endif
+
+#endif // ThreadedCompositor_h