1/* 2 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 * Copyright (C) 2012 Company 100, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 17 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 25 * THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "config.h" 29 30#if USE(COORDINATED_GRAPHICS) 31#include "CoordinatedLayerTreeHost.h" 32 33#include "CoordinatedGraphicsArgumentCoders.h" 34#include "CoordinatedLayerTreeHostProxyMessages.h" 35#include "DrawingAreaImpl.h" 36#include "GraphicsContext.h" 37#include "WebCoordinatedSurface.h" 38#include "WebCoreArgumentCoders.h" 39#include "WebPage.h" 40#include "WebPageProxyMessages.h" 41#include <WebCore/Frame.h> 42#include <WebCore/FrameView.h> 43#include <WebCore/GraphicsSurface.h> 44#include <WebCore/InspectorController.h> 45#include <WebCore/Page.h> 46#include <WebCore/RenderLayer.h> 47#include <WebCore/RenderLayerBacking.h> 48#include <WebCore/RenderLayerCompositor.h> 49#include <WebCore/RenderView.h> 50#include <WebCore/Settings.h> 51#include <WebCore/SurfaceUpdateInfo.h> 52#include <WebCore/TextureMapperPlatformLayer.h> 53#include <wtf/CurrentTime.h> 54#include <wtf/TemporaryChange.h> 55 56#if ENABLE(CSS_SHADERS) 57#include "CustomFilterValidatedProgram.h" 58#include "ValidatedCustomFilterOperation.h" 59#endif 60 61using namespace WebCore; 62 63namespace WebKit { 64 65PassRefPtr<CoordinatedLayerTreeHost> CoordinatedLayerTreeHost::create(WebPage* webPage) 66{ 67 return adoptRef(new CoordinatedLayerTreeHost(webPage)); 68} 69 70CoordinatedLayerTreeHost::~CoordinatedLayerTreeHost() 71{ 72#if ENABLE(CSS_SHADERS) 73 disconnectCustomFilterPrograms(); 74#endif 75 purgeBackingStores(); 76 77 LayerMap::iterator end = m_registeredLayers.end(); 78 for (LayerMap::iterator it = m_registeredLayers.begin(); it != end; ++it) 79 it->value->setCoordinator(0); 80} 81 82CoordinatedLayerTreeHost::CoordinatedLayerTreeHost(WebPage* webPage) 83 : LayerTreeHost(webPage) 84 , m_rootCompositingLayer(0) 85 , m_notifyAfterScheduledLayerFlush(false) 86 , m_isValid(true) 87 , m_isPurging(false) 88 , m_isFlushingLayerChanges(false) 89 , m_waitingForUIProcess(true) 90 , m_isSuspended(false) 91 , m_shouldSyncFrame(false) 92 , m_didInitializeRootCompositingLayer(false) 93 , m_layerFlushTimer(this, &CoordinatedLayerTreeHost::layerFlushTimerFired) 94 , m_releaseInactiveAtlasesTimer(this, &CoordinatedLayerTreeHost::releaseInactiveAtlasesTimerFired) 95 , m_layerFlushSchedulingEnabled(true) 96 , m_forceRepaintAsyncCallbackID(0) 97 , m_animationsLocked(false) 98#if ENABLE(REQUEST_ANIMATION_FRAME) 99 , m_lastAnimationServiceTime(0) 100#endif 101{ 102 m_webPage->corePage()->settings()->setApplyDeviceScaleFactorInCompositor(true); 103 104 // Create a root layer. 105 m_rootLayer = GraphicsLayer::create(this, this); 106#ifndef NDEBUG 107 m_rootLayer->setName("CoordinatedLayerTreeHost root layer"); 108#endif 109 m_rootLayer->setDrawsContent(false); 110 m_rootLayer->setSize(m_webPage->size()); 111 m_layerTreeContext.coordinatedLayerID = toCoordinatedGraphicsLayer(m_rootLayer.get())->id(); 112 113 CoordinatedSurface::setFactory(createCoordinatedSurface); 114 115 // This is a temporary way to enable this only in the GL case, until TextureMapperImageBuffer is removed. 116 // See https://bugs.webkit.org/show_bug.cgi?id=114869 117 CoordinatedGraphicsLayer::setShouldSupportContentsTiling(true); 118 119 if (m_webPage->hasPageOverlay()) 120 createPageOverlayLayer(); 121 122 scheduleLayerFlush(); 123} 124 125void CoordinatedLayerTreeHost::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled) 126{ 127 if (m_layerFlushSchedulingEnabled == layerFlushingEnabled) 128 return; 129 130 m_layerFlushSchedulingEnabled = layerFlushingEnabled; 131 132 if (m_layerFlushSchedulingEnabled) { 133 scheduleLayerFlush(); 134 return; 135 } 136 137 cancelPendingLayerFlush(); 138} 139 140void CoordinatedLayerTreeHost::scheduleLayerFlush() 141{ 142 if (!m_layerFlushSchedulingEnabled) 143 return; 144 145 if (!m_layerFlushTimer.isActive() || m_layerFlushTimer.nextFireInterval() > 0) 146 m_layerFlushTimer.startOneShot(0); 147} 148 149void CoordinatedLayerTreeHost::cancelPendingLayerFlush() 150{ 151 m_layerFlushTimer.stop(); 152} 153 154void CoordinatedLayerTreeHost::setShouldNotifyAfterNextScheduledLayerFlush(bool notifyAfterScheduledLayerFlush) 155{ 156 m_notifyAfterScheduledLayerFlush = notifyAfterScheduledLayerFlush; 157} 158 159void CoordinatedLayerTreeHost::setRootCompositingLayer(WebCore::GraphicsLayer* graphicsLayer) 160{ 161 if (m_rootCompositingLayer) 162 m_rootCompositingLayer->removeFromParent(); 163 164 m_rootCompositingLayer = graphicsLayer; 165 if (m_rootCompositingLayer) 166 m_rootLayer->addChildAtIndex(m_rootCompositingLayer, 0); 167} 168 169void CoordinatedLayerTreeHost::invalidate() 170{ 171 cancelPendingLayerFlush(); 172 173 ASSERT(m_isValid); 174 m_rootLayer = nullptr; 175 m_isValid = false; 176} 177 178void CoordinatedLayerTreeHost::forceRepaint() 179{ 180 // This is necessary for running layout tests. Since in this case we are not waiting for a UIProcess to reply nicely. 181 // Instead we are just triggering forceRepaint. But we still want to have the scripted animation callbacks being executed. 182 syncDisplayState(); 183 184 // We need to schedule another flush, otherwise the forced paint might cancel a later expected flush. 185 // This is aligned with LayerTreeHostCA. 186 scheduleLayerFlush(); 187 flushPendingLayerChanges(); 188} 189 190bool CoordinatedLayerTreeHost::forceRepaintAsync(uint64_t callbackID) 191{ 192 // We expect the UI process to not require a new repaint until the previous one has finished. 193 ASSERT(!m_forceRepaintAsyncCallbackID); 194 m_forceRepaintAsyncCallbackID = callbackID; 195 scheduleLayerFlush(); 196 return true; 197} 198 199void CoordinatedLayerTreeHost::sizeDidChange(const WebCore::IntSize& newSize) 200{ 201 m_rootLayer->setSize(newSize); 202 scheduleLayerFlush(); 203} 204 205void CoordinatedLayerTreeHost::didInstallPageOverlay(PageOverlay* pageOverlay) 206{ 207 ASSERT(!m_pageOverlay); 208 m_pageOverlay = pageOverlay; 209 210 createPageOverlayLayer(); 211 scheduleLayerFlush(); 212} 213 214void CoordinatedLayerTreeHost::didUninstallPageOverlay(PageOverlay*) 215{ 216 m_pageOverlay = 0; 217 218 destroyPageOverlayLayer(); 219 scheduleLayerFlush(); 220} 221 222void CoordinatedLayerTreeHost::setPageOverlayNeedsDisplay(PageOverlay*, const WebCore::IntRect& rect) 223{ 224 ASSERT(m_pageOverlayLayer); 225 m_pageOverlayLayer->setNeedsDisplayInRect(rect); 226 scheduleLayerFlush(); 227} 228 229void CoordinatedLayerTreeHost::setPageOverlayOpacity(PageOverlay*, float value) 230{ 231 ASSERT(m_pageOverlayLayer); 232 m_pageOverlayLayer->setOpacity(value); 233 scheduleLayerFlush(); 234} 235 236bool CoordinatedLayerTreeHost::flushPendingLayerChanges() 237{ 238 if (m_waitingForUIProcess) 239 return false; 240 241 TemporaryChange<bool> protector(m_isFlushingLayerChanges, true); 242 243 initializeRootCompositingLayerIfNeeded(); 244 245 m_rootLayer->flushCompositingStateForThisLayerOnly(); 246 if (m_pageOverlayLayer) 247 m_pageOverlayLayer->flushCompositingStateForThisLayerOnly(); 248 249 bool didSync = m_webPage->corePage()->mainFrame()->view()->flushCompositingStateIncludingSubframes(); 250 251 toCoordinatedGraphicsLayer(m_rootLayer.get())->updateContentBuffersIncludingSubLayers(); 252 toCoordinatedGraphicsLayer(m_rootLayer.get())->syncPendingStateChangesIncludingSubLayers(); 253 254 flushPendingImageBackingChanges(); 255 256 if (m_shouldSyncFrame) { 257 didSync = true; 258 259 if (m_rootCompositingLayer) { 260 m_state.contentsSize = roundedIntSize(m_rootCompositingLayer->size()); 261 if (CoordinatedGraphicsLayer* contentsLayer = mainContentsLayer()) 262 m_state.coveredRect = contentsLayer->coverRect(); 263 } 264 265 m_state.scrollPosition = m_visibleContentsRect.location(); 266 267 m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::CommitCoordinatedGraphicsState(m_state)); 268 269 clearPendingStateChanges(); 270 m_waitingForUIProcess = true; 271 m_shouldSyncFrame = false; 272 } 273 274 if (m_forceRepaintAsyncCallbackID) { 275 m_webPage->send(Messages::WebPageProxy::VoidCallback(m_forceRepaintAsyncCallbackID)); 276 m_forceRepaintAsyncCallbackID = 0; 277 } 278 279 return didSync; 280} 281 282void CoordinatedLayerTreeHost::clearPendingStateChanges() 283{ 284 m_state.layersToCreate.clear(); 285 m_state.layersToUpdate.clear(); 286 m_state.layersToRemove.clear(); 287 288 m_state.imagesToCreate.clear(); 289 m_state.imagesToRemove.clear(); 290 m_state.imagesToUpdate.clear(); 291 m_state.imagesToClear.clear(); 292 293 m_state.updateAtlasesToCreate.clear(); 294 m_state.updateAtlasesToRemove.clear(); 295 296#if ENABLE(CSS_SHADERS) 297 m_state.customFiltersToCreate.clear(); 298 m_state.customFiltersToRemove.clear(); 299#endif 300} 301 302void CoordinatedLayerTreeHost::initializeRootCompositingLayerIfNeeded() 303{ 304 if (m_didInitializeRootCompositingLayer) 305 return; 306 307 m_state.rootCompositingLayer = toCoordinatedGraphicsLayer(m_rootLayer.get())->id(); 308 m_didInitializeRootCompositingLayer = true; 309 m_shouldSyncFrame = true; 310} 311 312void CoordinatedLayerTreeHost::syncLayerState(CoordinatedLayerID id, CoordinatedGraphicsLayerState& state) 313{ 314 m_shouldSyncFrame = true; 315 316#if ENABLE(CSS_SHADERS) 317 prepareCustomFilterProxiesIfNeeded(state); 318#endif 319 320 m_state.layersToUpdate.append(std::make_pair(id, state)); 321} 322 323#if ENABLE(CSS_SHADERS) 324void CoordinatedLayerTreeHost::prepareCustomFilterProxiesIfNeeded(CoordinatedGraphicsLayerState& state) 325{ 326 if (state.animationsChanged) { 327 GraphicsLayerAnimations& activeAnimations = state.animations; 328 for (size_t i = 0; i < activeAnimations.animations().size(); ++i) { 329 const KeyframeValueList& keyframes = activeAnimations.animations().at(i).keyframes(); 330 if (keyframes.property() != AnimatedPropertyWebkitFilter) 331 continue; 332 for (size_t j = 0; j < keyframes.size(); ++j) { 333 const FilterAnimationValue& filterValue = static_cast<const FilterAnimationValue&>(keyframes.at(j)); 334 checkCustomFilterProgramProxies(filterValue.value()); 335 } 336 } 337 } 338 339 if (state.filtersChanged) 340 checkCustomFilterProgramProxies(state.filters); 341} 342 343void CoordinatedLayerTreeHost::checkCustomFilterProgramProxies(const FilterOperations& filters) 344{ 345 // We need to create the WebCustomFilterProgramProxy objects before we get to serialize the 346 // custom filters to the other process. That's because WebCustomFilterProgramProxy needs 347 // to link back to the coordinator, so that we can send a message to the UI process when 348 // the program is not needed anymore. 349 // Note that the serialization will only happen at a later time in ArgumentCoder<WebCore::FilterOperations>::encode. 350 // At that point the program will only be serialized once. All the other times it will only use the ID of the program. 351 for (size_t i = 0; i < filters.size(); ++i) { 352 const FilterOperation* operation = filters.at(i); 353 if (operation->getOperationType() != FilterOperation::VALIDATED_CUSTOM) 354 continue; 355 const ValidatedCustomFilterOperation* customOperation = static_cast<const ValidatedCustomFilterOperation*>(operation); 356 ASSERT(customOperation->validatedProgram()->isInitialized()); 357 TextureMapperPlatformCompiledProgram* program = customOperation->validatedProgram()->platformCompiledProgram(); 358 359 RefPtr<WebCustomFilterProgramProxy> customFilterProgramProxy; 360 if (program->client()) 361 customFilterProgramProxy = static_cast<WebCustomFilterProgramProxy*>(program->client()); 362 else { 363 customFilterProgramProxy = WebCustomFilterProgramProxy::create(); 364 program->setClient(customFilterProgramProxy); 365 } 366 367 if (!customFilterProgramProxy->client()) { 368 customFilterProgramProxy->setClient(this); 369 m_customFilterPrograms.add(customFilterProgramProxy.get()); 370 m_state.customFiltersToCreate.append(std::make_pair(customFilterProgramProxy->id(), customOperation->validatedProgram()->validatedProgramInfo())); 371 } else { 372 // If the client was not disconnected then this coordinator must be the client for it. 373 ASSERT(customFilterProgramProxy->client() == this); 374 } 375 } 376} 377 378void CoordinatedLayerTreeHost::removeCustomFilterProgramProxy(WebCustomFilterProgramProxy* customFilterProgramProxy) 379{ 380 // At this time the shader is not needed anymore, so we remove it from our set and 381 // send a message to the other process to delete it. 382 m_customFilterPrograms.remove(customFilterProgramProxy); 383 m_state.customFiltersToRemove.append(customFilterProgramProxy->id()); 384} 385 386void CoordinatedLayerTreeHost::disconnectCustomFilterPrograms() 387{ 388 // Make sure that WebCore will not call into this coordinator anymore. 389 HashSet<WebCustomFilterProgramProxy*>::iterator iter = m_customFilterPrograms.begin(); 390 for (; iter != m_customFilterPrograms.end(); ++iter) 391 (*iter)->setClient(0); 392} 393#endif // ENABLE(CSS_SHADERS) 394 395void CoordinatedLayerTreeHost::detachLayer(CoordinatedGraphicsLayer* layer) 396{ 397 m_registeredLayers.remove(layer->id()); 398 399 size_t index = m_state.layersToCreate.find(layer->id()); 400 if (index != notFound) { 401 m_state.layersToCreate.remove(index); 402 return; 403 } 404 405 m_state.layersToRemove.append(layer->id()); 406 scheduleLayerFlush(); 407} 408 409void CoordinatedLayerTreeHost::performScheduledLayerFlush() 410{ 411 if (m_isSuspended || m_waitingForUIProcess) 412 return; 413 414 syncDisplayState(); 415 416 if (!m_isValid) 417 return; 418 419 if (flushPendingLayerChanges()) 420 didPerformScheduledLayerFlush(); 421} 422 423void CoordinatedLayerTreeHost::syncDisplayState() 424{ 425#if ENABLE(INSPECTOR) 426 m_webPage->corePage()->inspectorController()->didBeginFrame(); 427#endif 428 429#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER) && !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR) 430 // Make sure that any previously registered animation callbacks are being executed before we flush the layers. 431 m_lastAnimationServiceTime = WTF::monotonicallyIncreasingTime(); 432 m_webPage->corePage()->mainFrame()->view()->serviceScriptedAnimations(m_lastAnimationServiceTime); 433#endif 434 435 m_webPage->layoutIfNeeded(); 436} 437 438void CoordinatedLayerTreeHost::didPerformScheduledLayerFlush() 439{ 440 if (m_notifyAfterScheduledLayerFlush) { 441 static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers(); 442 m_notifyAfterScheduledLayerFlush = false; 443 } 444} 445 446void CoordinatedLayerTreeHost::layerFlushTimerFired(Timer<CoordinatedLayerTreeHost>*) 447{ 448 performScheduledLayerFlush(); 449} 450 451void CoordinatedLayerTreeHost::createPageOverlayLayer() 452{ 453 ASSERT(!m_pageOverlayLayer); 454 455 m_pageOverlayLayer = GraphicsLayer::create(this, this); 456#ifndef NDEBUG 457 m_pageOverlayLayer->setName("CoordinatedLayerTreeHost page overlay content"); 458#endif 459 460 m_pageOverlayLayer->setDrawsContent(true); 461 m_pageOverlayLayer->setSize(m_webPage->size()); 462 463 m_rootLayer->addChild(m_pageOverlayLayer.get()); 464} 465 466void CoordinatedLayerTreeHost::destroyPageOverlayLayer() 467{ 468 ASSERT(m_pageOverlayLayer); 469 m_pageOverlayLayer->removeFromParent(); 470 m_pageOverlayLayer = nullptr; 471} 472 473PassRefPtr<CoordinatedImageBacking> CoordinatedLayerTreeHost::createImageBackingIfNeeded(Image* image) 474{ 475 CoordinatedImageBackingID imageID = CoordinatedImageBacking::getCoordinatedImageBackingID(image); 476 ImageBackingMap::iterator it = m_imageBackings.find(imageID); 477 RefPtr<CoordinatedImageBacking> imageBacking; 478 if (it == m_imageBackings.end()) { 479 imageBacking = CoordinatedImageBacking::create(this, image); 480 m_imageBackings.add(imageID, imageBacking); 481 } else 482 imageBacking = it->value; 483 484 return imageBacking; 485} 486 487void CoordinatedLayerTreeHost::createImageBacking(CoordinatedImageBackingID imageID) 488{ 489 m_state.imagesToCreate.append(imageID); 490} 491 492void CoordinatedLayerTreeHost::updateImageBacking(CoordinatedImageBackingID imageID, PassRefPtr<CoordinatedSurface> coordinatedSurface) 493{ 494 m_shouldSyncFrame = true; 495 m_state.imagesToUpdate.append(std::make_pair(imageID, coordinatedSurface)); 496} 497 498void CoordinatedLayerTreeHost::clearImageBackingContents(CoordinatedImageBackingID imageID) 499{ 500 m_shouldSyncFrame = true; 501 m_state.imagesToClear.append(imageID); 502} 503 504void CoordinatedLayerTreeHost::removeImageBacking(CoordinatedImageBackingID imageID) 505{ 506 if (m_isPurging) 507 return; 508 509 ASSERT(m_imageBackings.contains(imageID)); 510 m_imageBackings.remove(imageID); 511 512 m_state.imagesToRemove.append(imageID); 513} 514 515void CoordinatedLayerTreeHost::flushPendingImageBackingChanges() 516{ 517 ImageBackingMap::iterator end = m_imageBackings.end(); 518 for (ImageBackingMap::iterator iter = m_imageBackings.begin(); iter != end; ++iter) 519 iter->value->update(); 520} 521 522void CoordinatedLayerTreeHost::notifyAnimationStarted(const WebCore::GraphicsLayer*, double /* time */) 523{ 524} 525 526void CoordinatedLayerTreeHost::notifyFlushRequired(const WebCore::GraphicsLayer*) 527{ 528 scheduleLayerFlush(); 529} 530 531void CoordinatedLayerTreeHost::paintContents(const WebCore::GraphicsLayer* graphicsLayer, WebCore::GraphicsContext& graphicsContext, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& clipRect) 532{ 533 if (graphicsLayer == m_pageOverlayLayer) { 534 // Overlays contain transparent contents and won't clear the context as part of their rendering, so we do it here. 535 graphicsContext.clearRect(clipRect); 536 m_webPage->drawPageOverlay(m_pageOverlay.get(), graphicsContext, clipRect); 537 return; 538 } 539} 540 541PassOwnPtr<GraphicsLayer> CoordinatedLayerTreeHost::createGraphicsLayer(GraphicsLayerClient* client) 542{ 543 CoordinatedGraphicsLayer* layer = new CoordinatedGraphicsLayer(client); 544 layer->setCoordinator(this); 545 m_registeredLayers.add(layer->id(), layer); 546 m_state.layersToCreate.append(layer->id()); 547 layer->setNeedsVisibleRectAdjustment(); 548 scheduleLayerFlush(); 549 return adoptPtr(layer); 550} 551 552PassRefPtr<CoordinatedSurface> CoordinatedLayerTreeHost::createCoordinatedSurface(const IntSize& size, CoordinatedSurface::Flags flags) 553{ 554 return WebCoordinatedSurface::create(size, flags); 555} 556 557float CoordinatedLayerTreeHost::deviceScaleFactor() const 558{ 559 return m_webPage->deviceScaleFactor(); 560} 561 562float CoordinatedLayerTreeHost::pageScaleFactor() const 563{ 564 return m_webPage->pageScaleFactor(); 565} 566 567bool LayerTreeHost::supportsAcceleratedCompositing() 568{ 569 return true; 570} 571 572void CoordinatedLayerTreeHost::createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface> coordinatedSurface) 573{ 574 m_state.updateAtlasesToCreate.append(std::make_pair(atlasID, coordinatedSurface)); 575} 576 577void CoordinatedLayerTreeHost::removeUpdateAtlas(uint32_t atlasID) 578{ 579 if (m_isPurging) 580 return; 581 m_state.updateAtlasesToRemove.append(atlasID); 582} 583 584WebCore::FloatRect CoordinatedLayerTreeHost::visibleContentsRect() const 585{ 586 return m_visibleContentsRect; 587} 588 589CoordinatedGraphicsLayer* CoordinatedLayerTreeHost::mainContentsLayer() 590{ 591 if (!m_rootCompositingLayer) 592 return 0; 593 594 return toCoordinatedGraphicsLayer(m_rootCompositingLayer)->findFirstDescendantWithContentsRecursively(); 595} 596 597void CoordinatedLayerTreeHost::setVisibleContentsRect(const FloatRect& rect, const FloatPoint& trajectoryVector) 598{ 599 // A zero trajectoryVector indicates that tiles all around the viewport are requested. 600 if (CoordinatedGraphicsLayer* contentsLayer = mainContentsLayer()) 601 contentsLayer->setVisibleContentRectTrajectoryVector(trajectoryVector); 602 603 bool contentsRectDidChange = rect != m_visibleContentsRect; 604 if (contentsRectDidChange) { 605 m_visibleContentsRect = rect; 606 607 LayerMap::iterator end = m_registeredLayers.end(); 608 for (LayerMap::iterator it = m_registeredLayers.begin(); it != end; ++it) { 609 it->value->setNeedsVisibleRectAdjustment(); 610 } 611 } 612 613 scheduleLayerFlush(); 614 if (m_webPage->useFixedLayout()) { 615 // Round the rect instead of enclosing it to make sure that its size stays 616 // the same while panning. This can have nasty effects on layout. 617 m_webPage->setFixedVisibleContentRect(roundedIntRect(rect)); 618 } 619} 620 621void CoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged() 622{ 623 m_rootLayer->deviceOrPageScaleFactorChanged(); 624 if (m_pageOverlayLayer) 625 m_pageOverlayLayer->deviceOrPageScaleFactorChanged(); 626} 627 628void CoordinatedLayerTreeHost::pageBackgroundTransparencyChanged() 629{ 630} 631 632GraphicsLayerFactory* CoordinatedLayerTreeHost::graphicsLayerFactory() 633{ 634 return this; 635} 636 637#if ENABLE(REQUEST_ANIMATION_FRAME) 638void CoordinatedLayerTreeHost::scheduleAnimation() 639{ 640 if (m_waitingForUIProcess) 641 return; 642 643 if (m_layerFlushTimer.isActive()) 644 return; 645 646 // According to the requestAnimationFrame spec, rAF callbacks should not be faster than 60FPS. 647 static const double MinimalTimeoutForAnimations = 1. / 60.; 648 m_layerFlushTimer.startOneShot(std::max<double>(0., MinimalTimeoutForAnimations - WTF::monotonicallyIncreasingTime() + m_lastAnimationServiceTime)); 649 scheduleLayerFlush(); 650} 651#endif 652 653void CoordinatedLayerTreeHost::renderNextFrame() 654{ 655 m_waitingForUIProcess = false; 656 scheduleLayerFlush(); 657 for (unsigned i = 0; i < m_updateAtlases.size(); ++i) 658 m_updateAtlases[i]->didSwapBuffers(); 659} 660 661void CoordinatedLayerTreeHost::purgeBackingStores() 662{ 663 TemporaryChange<bool> purgingToggle(m_isPurging, true); 664 665 LayerMap::iterator end = m_registeredLayers.end(); 666 for (LayerMap::iterator it = m_registeredLayers.begin(); it != end; ++it) 667 it->value->purgeBackingStores(); 668 669 m_imageBackings.clear(); 670 m_updateAtlases.clear(); 671} 672 673bool CoordinatedLayerTreeHost::paintToSurface(const IntSize& size, CoordinatedSurface::Flags flags, uint32_t& atlasID, IntPoint& offset, CoordinatedSurface::Client* client) 674{ 675 for (unsigned i = 0; i < m_updateAtlases.size(); ++i) { 676 UpdateAtlas* atlas = m_updateAtlases[i].get(); 677 if (atlas->supportsAlpha() == (flags & CoordinatedSurface::SupportsAlpha)) { 678 // This will false if there is no available buffer space. 679 if (atlas->paintOnAvailableBuffer(size, atlasID, offset, client)) 680 return true; 681 } 682 } 683 684 static const int ScratchBufferDimension = 1024; // Should be a power of two. 685 m_updateAtlases.append(adoptPtr(new UpdateAtlas(this, ScratchBufferDimension, flags))); 686 scheduleReleaseInactiveAtlases(); 687 return m_updateAtlases.last()->paintOnAvailableBuffer(size, atlasID, offset, client); 688} 689 690const double ReleaseInactiveAtlasesTimerInterval = 0.5; 691 692void CoordinatedLayerTreeHost::scheduleReleaseInactiveAtlases() 693{ 694 if (!m_releaseInactiveAtlasesTimer.isActive()) 695 m_releaseInactiveAtlasesTimer.startRepeating(ReleaseInactiveAtlasesTimerInterval); 696} 697 698void CoordinatedLayerTreeHost::releaseInactiveAtlasesTimerFired(Timer<CoordinatedLayerTreeHost>*) 699{ 700 // We always want to keep one atlas for non-composited content. 701 OwnPtr<UpdateAtlas> atlasToKeepAnyway; 702 bool foundActiveAtlasForNonCompositedContent = false; 703 for (int i = m_updateAtlases.size() - 1; i >= 0; --i) { 704 UpdateAtlas* atlas = m_updateAtlases[i].get(); 705 if (!atlas->isInUse()) 706 atlas->addTimeInactive(ReleaseInactiveAtlasesTimerInterval); 707 bool usableForNonCompositedContent = !atlas->supportsAlpha(); 708 if (atlas->isInactive()) { 709 if (!foundActiveAtlasForNonCompositedContent && !atlasToKeepAnyway && usableForNonCompositedContent) 710 atlasToKeepAnyway = m_updateAtlases[i].release(); 711 m_updateAtlases.remove(i); 712 } else if (usableForNonCompositedContent) 713 foundActiveAtlasForNonCompositedContent = true; 714 } 715 716 if (!foundActiveAtlasForNonCompositedContent && atlasToKeepAnyway) 717 m_updateAtlases.append(atlasToKeepAnyway.release()); 718 719 if (m_updateAtlases.size() <= 1) 720 m_releaseInactiveAtlasesTimer.stop(); 721} 722 723void CoordinatedLayerTreeHost::setBackgroundColor(const WebCore::Color& color) 724{ 725 m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetBackgroundColor(color)); 726} 727 728void CoordinatedLayerTreeHost::commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset) 729{ 730 LayerMap::iterator i = m_registeredLayers.find(layerID); 731 if (i == m_registeredLayers.end()) 732 return; 733 734 i->value->commitScrollOffset(offset); 735} 736 737} // namespace WebKit 738#endif // USE(COORDINATED_GRAPHICS) 739