1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
/*
* Copyright (C) 2011 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:
* 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"
#include "LayerTreeHostCAWin.h"
#if HAVE(WKQCA)
#include "DrawingAreaImpl.h"
#include "ShareableBitmap.h"
#include "UpdateInfo.h"
#include "WKCACFViewWindow.h"
#include "WebPage.h"
#include <WebCore/GraphicsLayerCA.h>
#include <WebCore/LayerChangesFlusher.h>
#include <WebCore/PlatformCALayer.h>
#include <WebCore/SoftLinking.h>
#include <WebCore/WebCoreInstanceHandle.h>
#include <WebKitQuartzCoreAdditions/WKCACFImage.h>
#include <WebKitQuartzCoreAdditions/WKCACFView.h>
#include <wtf/CurrentTime.h>
#include <wtf/MainThread.h>
#ifdef DEBUG_ALL
#define MODULE_NAME "WebKitQuartzCoreAdditions_debug"
#else
#define MODULE_NAME "WebKitQuartzCoreAdditions"
#endif
#pragma comment(lib, MODULE_NAME)
#if USE(AVFOUNDATION)
SOFT_LINK_LOADED_LIBRARY(MODULE_NAME, WKCACFViewGetD3DDevice9, IDirect3DDevice9*, _cdecl, (WKCACFViewRef view))
#endif
using namespace WebCore;
namespace WebKit {
bool LayerTreeHostCAWin::supportsAcceleratedCompositing()
{
static bool initialized;
static bool supportsAcceleratedCompositing;
if (initialized)
return supportsAcceleratedCompositing;
initialized = true;
RetainPtr<WKCACFViewRef> view(AdoptCF, WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow));
WKCACFViewWindow dummyWindow(view.get(), 0, 0);
CGRect fakeBounds = CGRectMake(0, 0, 10, 10);
WKCACFViewUpdate(view.get(), dummyWindow.window(), &fakeBounds);
supportsAcceleratedCompositing = WKCACFViewCanDraw(view.get());
WKCACFViewUpdate(view.get(), 0, 0);
return supportsAcceleratedCompositing;
}
PassRefPtr<LayerTreeHostCAWin> LayerTreeHostCAWin::create(WebPage* webPage)
{
RefPtr<LayerTreeHostCAWin> host = adoptRef(new LayerTreeHostCAWin(webPage));
host->initialize();
return host.release();
}
LayerTreeHostCAWin::LayerTreeHostCAWin(WebPage* webPage)
: LayerTreeHostCA(webPage)
, m_isFlushingLayerChanges(false)
{
}
LayerTreeHostCAWin::~LayerTreeHostCAWin()
{
}
void LayerTreeHostCAWin::platformInitialize()
{
m_view.adoptCF(WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow));
WKCACFViewSetContextUserData(m_view.get(), static_cast<AbstractCACFLayerTreeHost*>(this));
WKCACFViewSetLayer(m_view.get(), rootLayer()->platformLayer());
WKCACFViewSetContextDidChangeCallback(m_view.get(), contextDidChangeCallback, this);
// Passing WS_DISABLED makes the window invisible to mouse events, which lets WKView's normal
// event handling mechanism work even when this window is obscuring the entire WKView HWND.
// Note that m_webPage->nativeWindow() is owned by the UI process, so this creates a cross-
// process window hierarchy (and thus implicitly attaches the input queues of the UI and web
// processes' main threads).
m_window = adoptPtr(new WKCACFViewWindow(m_view.get(), m_webPage->nativeWindow(), WS_DISABLED));
CGRect bounds = m_webPage->bounds();
WKCACFViewUpdate(m_view.get(), m_window->window(), &bounds);
m_layerTreeContext.window = m_window->window();
}
void LayerTreeHostCAWin::invalidate()
{
LayerChangesFlusher::shared().cancelPendingFlush(this);
WKCACFViewSetContextUserData(m_view.get(), 0);
WKCACFViewSetLayer(m_view.get(), 0);
WKCACFViewSetContextDidChangeCallback(m_view.get(), 0, 0);
// The UI process will destroy m_window's HWND when it gets the message to switch out of
// accelerated compositing mode. We don't want to destroy the HWND before then or we will get a
// flash of white before the UI process has a chance to display the non-composited content.
// Since the HWND needs to outlive us, we leak m_window here and tell it to clean itself up
// when its HWND is destroyed.
WKCACFViewWindow* window = m_window.leakPtr();
window->setDeletesSelfWhenWindowDestroyed(true);
LayerTreeHostCA::invalidate();
}
void LayerTreeHostCAWin::scheduleLayerFlush()
{
if (!m_layerFlushSchedulingEnabled)
return;
LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this);
}
void LayerTreeHostCAWin::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled)
{
if (m_layerFlushSchedulingEnabled == layerFlushingEnabled)
return;
m_layerFlushSchedulingEnabled = layerFlushingEnabled;
if (m_layerFlushSchedulingEnabled) {
scheduleLayerFlush();
return;
}
LayerChangesFlusher::shared().cancelPendingFlush(this);
}
void LayerTreeHostCAWin::scheduleChildWindowGeometryUpdate(const WindowGeometry& geometry)
{
m_geometriesUpdater.addPendingUpdate(geometry);
}
void LayerTreeHostCAWin::sizeDidChange(const IntSize& newSize)
{
LayerTreeHostCA::sizeDidChange(newSize);
CGRect bounds = CGRectMake(0, 0, newSize.width(), newSize.height());
WKCACFViewUpdate(m_view.get(), m_window->window(), &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();
// Update child window geometries now so that they stay mostly in sync with the accelerated content.
// FIXME: We should really be doing this when the changes we just flushed appear on screen. <http://webkit.org/b/61867>
// We also bring the child windows (i.e., plugins) to the top of the z-order to ensure they are above m_window.
// FIXME: We could do this just once per window when it is first shown. Maybe that would be more efficient?
m_geometriesUpdater.updateGeometries(BringToTop);
}
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;
}
void LayerTreeHostCAWin::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
{
// Don't flush any changes when we don't have a root layer. This will prevent flashes of white
// when switching out of compositing mode.
setLayerFlushSchedulingEnabled(graphicsLayer);
// Resubmit all existing animations. CACF does not remember running animations
// When the layer tree is removed and then added back to the hierarchy
if (graphicsLayer)
static_cast<GraphicsLayerCA*>(graphicsLayer)->platformCALayer()->ensureAnimationsSubmitted();
LayerTreeHostCA::setRootCompositingLayer(graphicsLayer);
}
#if USE(AVFOUNDATION)
WebCore::GraphicsDeviceAdapter* LayerTreeHostCAWin::graphicsDeviceAdapter() const
{
if (!WKCACFViewGetD3DDevice9Ptr())
return 0;
return reinterpret_cast<GraphicsDeviceAdapter*>(WKCACFViewGetD3DDevice9Ptr()(m_view.get()));
}
#endif
} // namespace WebKit
#endif // HAVE(WKQCA)
|