summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp')
-rw-r--r--Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp270
1 files changed, 250 insertions, 20 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp
index 81db03e..699a1fe 100644
--- a/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp
@@ -24,46 +24,276 @@
*/
#include "config.h"
-#include "LayerTreeHostCA.h"
+#include "LayerTreeHostCAWin.h"
-#include <WebCore/NotImplemented.h>
+#if HAVE(WKQCA)
+
+#include "DrawingAreaImpl.h"
+#include "ShareableBitmap.h"
+#include "UpdateInfo.h"
+#include "WebPage.h"
+#include <WebCore/GraphicsLayerCA.h>
+#include <WebCore/LayerChangesFlusher.h>
+#include <WebCore/PlatformCALayer.h>
+#include <WebCore/WebCoreInstanceHandle.h>
+#include <WebKitQuartzCoreAdditions/WKCACFImage.h>
+#include <WebKitQuartzCoreAdditions/WKCACFView.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/Threading.h>
+
+#ifdef DEBUG_ALL
+#pragma comment(lib, "WebKitQuartzCoreAdditions_debug")
+#else
+#pragma comment(lib, "WebKitQuartzCoreAdditions")
+#endif
+
+using namespace WebCore;
namespace WebKit {
-void LayerTreeHostCA::platformInitialize()
+static HWND dummyWindow;
+static LPCWSTR dummyWindowClass = L"LayerTreeHostCAWindowClass";
+static size_t validLayerTreeHostCount;
+
+static void registerDummyWindowClass()
+{
+ static bool didRegister;
+ if (didRegister)
+ return;
+ didRegister = true;
+
+ WNDCLASSW wndClass = {0};
+ wndClass.lpszClassName = dummyWindowClass;
+ wndClass.lpfnWndProc = ::DefWindowProcW;
+ wndClass.hInstance = instanceHandle();
+
+ ::RegisterClassW(&wndClass);
+}
+
+// This window is never shown. It is only needed so that D3D can determine the display mode, etc.
+static HWND createDummyWindow()
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
+ registerDummyWindowClass();
+ return ::CreateWindowW(dummyWindowClass, 0, WS_POPUP, 0, 0, 10, 10, 0, 0, instanceHandle(), 0);
}
-void LayerTreeHostCA::scheduleLayerFlush()
+bool LayerTreeHostCAWin::supportsAcceleratedCompositing()
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
+ static bool initialized;
+ static bool supportsAcceleratedCompositing;
+ if (initialized)
+ return supportsAcceleratedCompositing;
+ initialized = true;
+
+ ASSERT(!dummyWindow);
+ dummyWindow = createDummyWindow();
+ RetainPtr<WKCACFViewRef> view(AdoptCF, WKCACFViewCreate(kWKCACFViewDrawingDestinationImage));
+ CGRect fakeBounds = CGRectMake(0, 0, 10, 10);
+ WKCACFViewUpdate(view.get(), dummyWindow, &fakeBounds);
+
+ supportsAcceleratedCompositing = WKCACFViewCanDraw(view.get());
+
+ WKCACFViewUpdate(view.get(), 0, 0);
+ ::DestroyWindow(dummyWindow);
+ dummyWindow = 0;
+
+ return supportsAcceleratedCompositing;
}
-void LayerTreeHostCA::platformInvalidate()
+PassRefPtr<LayerTreeHostCAWin> LayerTreeHostCAWin::create(WebPage* webPage)
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
+ RefPtr<LayerTreeHostCAWin> host = adoptRef(new LayerTreeHostCAWin(webPage));
+ host->initialize();
+ return host.release();
}
-void LayerTreeHostCA::platformSizeDidChange()
+LayerTreeHostCAWin::LayerTreeHostCAWin(WebPage* webPage)
+ : LayerTreeHostCA(webPage)
+ , m_isFlushingLayerChanges(false)
+ , m_nextDisplayTime(0)
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
}
-void LayerTreeHostCA::platformForceRepaint()
+LayerTreeHostCAWin::~LayerTreeHostCAWin()
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
}
-void LayerTreeHostCA::platformDidPerformScheduledLayerFlush()
+void LayerTreeHostCAWin::platformInitialize(LayerTreeContext&)
{
- // FIXME: <http://webkit.org/b/45567> Implement this!
- notImplemented();
+ ++validLayerTreeHostCount;
+ if (!dummyWindow)
+ dummyWindow = createDummyWindow();
+
+ m_view.adoptCF(WKCACFViewCreate(kWKCACFViewDrawingDestinationImage));
+ WKCACFViewSetContextUserData(m_view.get(), static_cast<AbstractCACFLayerTreeHost*>(this));
+ WKCACFViewSetLayer(m_view.get(), rootLayer()->platformLayer());
+ WKCACFViewSetContextDidChangeCallback(m_view.get(), contextDidChangeCallback, this);
+
+ CGRect bounds = m_webPage->bounds();
+ WKCACFViewUpdate(m_view.get(), dummyWindow, &bounds);
+}
+
+void LayerTreeHostCAWin::invalidate()
+{
+ LayerChangesFlusher::shared().cancelPendingFlush(this);
+
+ WKCACFViewUpdate(m_view.get(), 0, 0);
+ WKCACFViewSetContextUserData(m_view.get(), 0);
+ WKCACFViewSetLayer(m_view.get(), 0);
+ WKCACFViewSetContextDidChangeCallback(m_view.get(), 0, 0);
+
+ LayerTreeHostCA::invalidate();
+
+ if (--validLayerTreeHostCount)
+ return;
+ ::DestroyWindow(dummyWindow);
+ dummyWindow = 0;
+}
+
+void LayerTreeHostCAWin::scheduleLayerFlush()
+{
+ LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
+}
+
+bool LayerTreeHostCAWin::participatesInDisplay()
+{
+ return true;
+}
+
+bool LayerTreeHostCAWin::needsDisplay()
+{
+ return timeUntilNextDisplay() <= 0;
+}
+
+double LayerTreeHostCAWin::timeUntilNextDisplay()
+{
+ return m_nextDisplayTime - currentTime();
+}
+
+static IntSize size(WKCACFImageRef image)
+{
+ return IntSize(WKCACFImageGetWidth(image), WKCACFImageGetHeight(image));
+}
+
+static PassRefPtr<ShareableBitmap> toShareableBitmap(WKCACFImageRef image)
+{
+ size_t fileMappingSize;
+ HANDLE mapping = WKCACFImageCopyFileMapping(image, &fileMappingSize);
+ if (!mapping)
+ return 0;
+
+ RefPtr<SharedMemory> sharedMemory = SharedMemory::adopt(mapping, fileMappingSize, SharedMemory::ReadWrite);
+ if (!sharedMemory) {
+ ::CloseHandle(mapping);
+ return 0;
+ }
+
+ // WKCACFImage never has an alpha channel.
+ return ShareableBitmap::create(size(image), 0, sharedMemory.release());
+}
+
+void LayerTreeHostCAWin::display(UpdateInfo& updateInfo)
+{
+ CGPoint imageOrigin;
+ CFTimeInterval nextDrawTime;
+ RetainPtr<WKCACFImageRef> image(AdoptCF, WKCACFViewCopyDrawnImage(m_view.get(), &imageOrigin, &nextDrawTime));
+ m_nextDisplayTime = nextDrawTime - CACurrentMediaTime() + currentTime();
+ if (!image)
+ return;
+ RefPtr<ShareableBitmap> bitmap = toShareableBitmap(image.get());
+ if (!bitmap)
+ return;
+ if (!bitmap->createHandle(updateInfo.bitmapHandle))
+ return;
+ updateInfo.updateRectBounds = IntRect(IntPoint(imageOrigin.x, m_webPage->size().height() - imageOrigin.y - bitmap->size().height()), bitmap->size());
+ updateInfo.updateRects.append(updateInfo.updateRectBounds);
+}
+
+void LayerTreeHostCAWin::sizeDidChange(const IntSize& newSize)
+{
+ LayerTreeHostCA::sizeDidChange(newSize);
+ CGRect bounds = CGRectMake(0, 0, newSize.width(), newSize.height());
+ WKCACFViewUpdate(m_view.get(), dummyWindow, &bounds);
+ WKCACFViewFlushContext(m_view.get());
+}
+
+void LayerTreeHostCAWin::forceRepaint()
+{
+ LayerTreeHostCA::forceRepaint();
+ WKCACFViewFlushContext(m_view.get());
+}
+
+void LayerTreeHostCAWin::contextDidChangeCallback(WKCACFViewRef view, void* info)
+{
+ // This should only be called on a background thread when no changes have actually
+ // been committed to the context, eg. when a video frame has been added to an image
+ // queue, so return without triggering animations etc.
+ if (!isMainThread())
+ return;
+
+ LayerTreeHostCAWin* host = static_cast<LayerTreeHostCAWin*>(info);
+ ASSERT_ARG(view, view == host->m_view);
+ host->contextDidChange();
+}
+
+void LayerTreeHostCAWin::contextDidChange()
+{
+ // Send currentTime to the pending animations. This function is called by CACF in a callback
+ // which occurs after the drawInContext calls. So currentTime is very close to the time
+ // the animations actually start
+ double currentTime = WTF::currentTime();
+
+ HashSet<RefPtr<PlatformCALayer> >::iterator end = m_pendingAnimatedLayers.end();
+ for (HashSet<RefPtr<PlatformCALayer> >::iterator it = m_pendingAnimatedLayers.begin(); it != end; ++it)
+ (*it)->animationStarted(currentTime);
+
+ m_pendingAnimatedLayers.clear();
+
+ m_nextDisplayTime = 0;
+ static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->setLayerHostNeedsDisplay();
+}
+
+PlatformCALayer* LayerTreeHostCAWin::rootLayer() const
+{
+ return static_cast<GraphicsLayerCA*>(LayerTreeHostCA::rootLayer())->platformCALayer();
+}
+
+void LayerTreeHostCAWin::addPendingAnimatedLayer(PassRefPtr<PlatformCALayer> layer)
+{
+ m_pendingAnimatedLayers.add(layer);
+}
+
+void LayerTreeHostCAWin::layerTreeDidChange()
+{
+ if (m_isFlushingLayerChanges) {
+ // The layer tree is changing as a result of flushing GraphicsLayer changes to their
+ // underlying PlatformCALayers. We'll flush those changes to the context as part of that
+ // process, so there's no need to schedule another flush here.
+ return;
+ }
+
+ // The layer tree is changing as a result of someone modifying a PlatformCALayer that doesn't
+ // have a corresponding GraphicsLayer. Schedule a flush since we won't schedule one through the
+ // normal GraphicsLayer mechanisms.
+ LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
+}
+
+void LayerTreeHostCAWin::flushPendingLayerChangesNow()
+{
+ RefPtr<LayerTreeHostCA> protector(this);
+
+ m_isFlushingLayerChanges = true;
+
+ // Flush changes stored up in GraphicsLayers to their underlying PlatformCALayers, if
+ // requested.
+ performScheduledLayerFlush();
+
+ // Flush changes stored up in PlatformCALayers to the context so they will be rendered.
+ WKCACFViewFlushContext(m_view.get());
+
+ m_isFlushingLayerChanges = false;
}
} // namespace WebKit
+
+#endif // HAVE(WKQCA)