Fix the issue that accelerated overflow scrolling become invisible
[framework/web/webkit-efl.git] / Source / WebKit2 / WebProcess / WebPage / LayerTreeCoordinator / LayerTreeCoordinator.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28
29 #include "LayerTreeCoordinator.h"
30
31 #include "CoordinatedGraphicsArgumentCoders.h"
32 #include "DrawingAreaImpl.h"
33 #include "GraphicsContext.h"
34 #include "LayerTreeCoordinatorProxyMessages.h"
35 #include "MessageID.h"
36 #include "SurfaceUpdateInfo.h"
37 #include "WebCoreArgumentCoders.h"
38 #include "WebGraphicsLayer.h"
39 #include "WebPage.h"
40 #include <WebCore/Frame.h>
41 #include <WebCore/FrameView.h>
42 #include <WebCore/Page.h>
43 #include <WebCore/RenderLayer.h>
44 #include <WebCore/RenderLayerBacking.h>
45 #include <WebCore/RenderLayerCompositor.h>
46 #include <WebCore/RenderView.h>
47 #include <WebCore/Settings.h>
48
49 #if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
50 #include "WebProcess.h"
51 #endif
52
53 using namespace WebCore;
54
55 namespace WebKit {
56
57 #if ENABLE(TIZEN_LAYER_FLUSH_THROTTLING)
58 const float LayerTreeCoordinator::s_layerFlushTimerDelayTable[s_layerFlushTimerDelayMaxLevel] = {0, 0.1, 0.2, 0.6, 1.3};
59 #endif
60
61 PassRefPtr<LayerTreeCoordinator> LayerTreeCoordinator::create(WebPage* webPage)
62 {
63     return adoptRef(new LayerTreeCoordinator(webPage));
64 }
65
66 LayerTreeCoordinator::~LayerTreeCoordinator()
67 {
68     // Prevent setWebGraphicsLayerClient(0) -> detachLayer() from modifying the set while we iterate it.
69     HashSet<WebCore::WebGraphicsLayer*> registeredLayers;
70     registeredLayers.swap(m_registeredLayers);
71
72     HashSet<WebCore::WebGraphicsLayer*>::iterator end = registeredLayers.end();
73     for (HashSet<WebCore::WebGraphicsLayer*>::iterator it = registeredLayers.begin(); it != end; ++it)
74         (*it)->setWebGraphicsLayerClient(0);
75 }
76
77 LayerTreeCoordinator::LayerTreeCoordinator(WebPage* webPage)
78     : LayerTreeHost(webPage)
79     , m_notifyAfterScheduledLayerFlush(false)
80     , m_isValid(true)
81 #if OS(TIZEN)
82     , m_waitingForUIProcess(false)
83 #else
84     , m_waitingForUIProcess(true)
85 #endif
86     , m_isSuspended(false)
87     , m_contentsScale(1)
88     , m_shouldSendScrollPositionUpdate(true)
89     , m_shouldSyncFrame(false)
90     , m_shouldSyncRootLayer(true)
91     , m_layerFlushTimer(this, &LayerTreeCoordinator::layerFlushTimerFired)
92     , m_releaseInactiveAtlasesTimer(this, &LayerTreeCoordinator::releaseInactiveAtlasesTimerFired)
93     , m_layerFlushSchedulingEnabled(true)
94 #if ENABLE(TIZEN_LAYER_FLUSH_THROTTLING)
95     , m_layerFlushTimerDelay(0.0)
96     , m_deferLayerFlushEnabled(false)
97     , m_layerFlushTimerDelayLevel(0)
98 #endif
99 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
100     , m_suspendedJavaScript(false)
101 #endif
102 #if ENABLE(TIZEN_ONESHOT_DRAWING_SYNCHRONIZATION)
103     , m_needsOneShotDrawingSynchronization(false)
104 #endif
105 #if ENABLE(TIZEN_RUNTIME_BACKEND_SELECTION)
106     , m_isGLAccelerationMode(true)
107 #endif
108     , m_animationsLocked(false)
109 {
110     // Create a root layer.
111     m_rootLayer = GraphicsLayer::create(this);
112     WebGraphicsLayer* webRootLayer = toWebGraphicsLayer(m_rootLayer.get());
113     webRootLayer->setRootLayer(true);
114 #ifndef NDEBUG
115     m_rootLayer->setName("LayerTreeCoordinator root layer");
116 #endif
117     m_rootLayer->setDrawsContent(false);
118     m_rootLayer->setSize(m_webPage->size());
119     m_layerTreeContext.webLayerID = toWebGraphicsLayer(webRootLayer)->id();
120
121     m_nonCompositedContentLayer = GraphicsLayer::create(this);
122     toWebGraphicsLayer(m_rootLayer.get())->setWebGraphicsLayerClient(this);
123 #ifndef NDEBUG
124     m_nonCompositedContentLayer->setName("LayerTreeCoordinator non-composited content");
125 #endif
126     m_nonCompositedContentLayer->setDrawsContent(true);
127     m_nonCompositedContentLayer->setSize(m_webPage->size());
128
129     m_rootLayer->addChild(m_nonCompositedContentLayer.get());
130
131     if (m_webPage->hasPageOverlay())
132         createPageOverlayLayer();
133
134     scheduleLayerFlush();
135 }
136
137 void LayerTreeCoordinator::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled)
138 {
139     if (m_layerFlushSchedulingEnabled == layerFlushingEnabled)
140         return;
141
142     m_layerFlushSchedulingEnabled = layerFlushingEnabled;
143
144     if (m_layerFlushSchedulingEnabled) {
145         scheduleLayerFlush();
146         return;
147     }
148
149     cancelPendingLayerFlush();
150 }
151
152 void LayerTreeCoordinator::scheduleLayerFlush()
153 {
154     if (!m_layerFlushSchedulingEnabled)
155         return;
156
157     if (!m_layerFlushTimer.isActive()) {
158 #if ENABLE(TIZEN_LAYER_FLUSH_THROTTLING)
159         m_layerFlushTimerDelay = deferredLayerFlushDelay();
160         m_layerFlushTimer.startOneShot(m_layerFlushTimerDelay);
161     }
162 #if ENABLE(TIZEN_SYNC_REQUEST_ANIMATION_FRAME)
163     if (m_layerFlushTimerDelay > 0.0)
164         m_webPage->suspendAnimationController();
165 #endif
166 #else
167         m_layerFlushTimer.startOneShot(0.0);
168     }
169 #endif
170
171 #if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
172     if (!m_layerFlushWorkItemToDispatchWhileWaitingForSyncReply)
173         m_layerFlushWorkItemToDispatchWhileWaitingForSyncReply = m_webPage->connection()->dispatchWorkItemWhileWaitingForSyncReply(WTF::bind(&LayerTreeCoordinator::performScheduledLayerFlushForcely, this));
174 #endif
175 }
176
177 void LayerTreeCoordinator::cancelPendingLayerFlush()
178 {
179     m_layerFlushTimer.stop();
180 #if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
181     m_webPage->connection()->clearWorkItemWhileWaitingForSyncReply(m_layerFlushWorkItemToDispatchWhileWaitingForSyncReply);
182     m_layerFlushWorkItemToDispatchWhileWaitingForSyncReply.clear();
183 #endif
184 }
185
186 void LayerTreeCoordinator::setShouldNotifyAfterNextScheduledLayerFlush(bool notifyAfterScheduledLayerFlush)
187 {
188     m_notifyAfterScheduledLayerFlush = notifyAfterScheduledLayerFlush;
189 }
190
191 void LayerTreeCoordinator::setRootCompositingLayer(WebCore::GraphicsLayer* graphicsLayer)
192 {
193     m_nonCompositedContentLayer->removeAllChildren();
194     m_nonCompositedContentLayer->setContentsOpaque(m_webPage->drawsBackground() && !m_webPage->drawsTransparentBackground());
195
196     // Add the accelerated layer tree hierarchy.
197     if (graphicsLayer)
198         m_nonCompositedContentLayer->addChild(graphicsLayer);
199 }
200
201 void LayerTreeCoordinator::invalidate()
202 {
203     cancelPendingLayerFlush();
204
205     ASSERT(m_isValid);
206     m_rootLayer = nullptr;
207     m_isValid = false;
208 }
209
210 void LayerTreeCoordinator::setNonCompositedContentsNeedDisplay(const WebCore::IntRect& rect)
211 {
212     m_nonCompositedContentLayer->setNeedsDisplayInRect(rect);
213     if (m_pageOverlayLayer)
214         m_pageOverlayLayer->setNeedsDisplayInRect(rect);
215
216     scheduleLayerFlush();
217 }
218
219 void LayerTreeCoordinator::scrollNonCompositedContents(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset)
220 {
221     setNonCompositedContentsNeedDisplay(scrollRect);
222 }
223
224 void LayerTreeCoordinator::forceRepaint()
225 {
226     // We need to schedule another flush, otherwise the forced paint might cancel a later expected flush.
227     // This is aligned with LayerTreeHostCA.
228     scheduleLayerFlush();
229     flushPendingLayerChanges();
230 }
231
232 void LayerTreeCoordinator::sizeDidChange(const WebCore::IntSize& newSize)
233 {
234     if (m_rootLayer->size() == newSize)
235         return;
236
237     m_rootLayer->setSize(newSize);
238
239     // If the newSize exposes new areas of the non-composited content a setNeedsDisplay is needed
240     // for those newly exposed areas.
241     FloatSize oldSize = m_nonCompositedContentLayer->size();
242     m_nonCompositedContentLayer->setSize(newSize);
243
244     if (newSize.width() > oldSize.width()) {
245         float height = std::min(static_cast<float>(newSize.height()), oldSize.height());
246         m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(oldSize.width(), 0, newSize.width() - oldSize.width(), height));
247     }
248
249     if (newSize.height() > oldSize.height())
250         m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(0, oldSize.height(), newSize.width(), newSize.height() - oldSize.height()));
251
252     if (m_pageOverlayLayer)
253         m_pageOverlayLayer->setSize(newSize);
254
255     scheduleLayerFlush();
256 }
257
258 void LayerTreeCoordinator::didInstallPageOverlay()
259 {
260     createPageOverlayLayer();
261     scheduleLayerFlush();
262 }
263
264 void LayerTreeCoordinator::didUninstallPageOverlay()
265 {
266     destroyPageOverlayLayer();
267     scheduleLayerFlush();
268 }
269
270 void LayerTreeCoordinator::setPageOverlayNeedsDisplay(const WebCore::IntRect& rect)
271 {
272     ASSERT(m_pageOverlayLayer);
273     m_pageOverlayLayer->setNeedsDisplayInRect(rect);
274     scheduleLayerFlush();
275 }
276
277 void LayerTreeCoordinator::setPageOverlayOpacity(float value)
278 {
279     ASSERT(m_pageOverlayLayer);
280     m_pageOverlayLayer->setOpacity(value);
281     scheduleLayerFlush();
282 }
283
284 bool LayerTreeCoordinator::flushPendingLayerChanges()
285 {
286     if (m_waitingForUIProcess)
287         return false;
288
289     bool didSync = m_webPage->corePage()->mainFrame()->view()->syncCompositingStateIncludingSubframes();
290     m_nonCompositedContentLayer->syncCompositingStateForThisLayerOnly();
291     if (m_pageOverlayLayer)
292         m_pageOverlayLayer->syncCompositingStateForThisLayerOnly();
293
294     m_rootLayer->syncCompositingStateForThisLayerOnly();
295
296     if (m_shouldSyncRootLayer) {
297         m_webPage->send(Messages::LayerTreeCoordinatorProxy::SetRootCompositingLayer(toWebGraphicsLayer(m_rootLayer.get())->id()));
298         m_shouldSyncRootLayer = false;
299     }
300
301     if (!m_shouldSyncFrame)
302         return didSync;
303
304 #if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
305     if (!m_compositedContentLayers.isEmpty()) {
306         Vector<uint32_t> weblayerIDsCopy;
307         copyToVector(m_compositedContentLayers, weblayerIDsCopy);
308         m_compositedContentLayers.clear();
309         bool pauseJavaScript = false;
310         for (size_t i = 0; i < weblayerIDsCopy.size(); ++i) {
311             WebGraphicsLayer* layer = WebGraphicsLayer::layerByID(weblayerIDsCopy[i]);
312             if (layer && !layer->swapPlatformSurfaces())
313                 pauseJavaScript = true;
314         }
315         if (pauseJavaScript) {
316             m_webPage->suspendJavaScriptAndResources();
317             m_suspendedJavaScript = true;
318         }
319     }
320 #endif
321
322 #if ENABLE(TIZEN_SYNC_REQUEST_ANIMATION_FRAME)
323     m_webPage->suspendAnimationController();
324 #endif
325     m_webPage->send(Messages::LayerTreeCoordinatorProxy::DidRenderFrame());
326     m_waitingForUIProcess = true;
327     m_shouldSyncFrame = false;
328
329     return true;
330 }
331
332 void LayerTreeCoordinator::syncLayerState(WebLayerID id, const WebLayerInfo& info)
333 {
334     if (m_shouldSendScrollPositionUpdate) {
335         m_webPage->send(Messages::LayerTreeCoordinatorProxy::DidChangeScrollPosition(m_visibleContentsRect.location()));
336         m_shouldSendScrollPositionUpdate = false;
337     }
338
339     m_shouldSyncFrame = true;
340     m_webPage->send(Messages::LayerTreeCoordinatorProxy::SetCompositingLayerState(id, info));
341 }
342
343 void LayerTreeCoordinator::syncLayerChildren(WebLayerID id, const Vector<WebLayerID>& children)
344 {
345     m_shouldSyncFrame = true;
346     m_webPage->send(Messages::LayerTreeCoordinatorProxy::SetCompositingLayerChildren(id, children));
347 }
348
349 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
350 void LayerTreeCoordinator::syncCanvas(WebLayerID id, const IntSize& canvasSize, uint64_t graphicsSurfaceToken, uint32_t frontBuffer, int flags)
351 #else
352 void LayerTreeCoordinator::syncCanvas(WebLayerID id, const IntSize& canvasSize, uint64_t graphicsSurfaceToken, uint32_t frontBuffer)
353 #endif
354 {
355     m_shouldSyncFrame = true;
356 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
357     m_compositedContentLayers.add(id);
358 #if ENABLE(TIZEN_ACCELERATED_2D_CANVAS_EFL)
359     m_compositedContentCanvas2DLayers.add(id);
360 #endif
361     m_webPage->send(Messages::LayerTreeCoordinatorProxy::SyncCanvas(id, canvasSize, graphicsSurfaceToken, frontBuffer, flags));
362 #else
363     m_webPage->send(Messages::LayerTreeCoordinatorProxy::SyncCanvas(id, canvasSize, graphicsSurfaceToken, frontBuffer));
364 #endif
365 }
366
367 #if ENABLE(CSS_FILTERS)
368 void LayerTreeCoordinator::syncLayerFilters(WebLayerID id, const FilterOperations& filters)
369 {
370     m_shouldSyncFrame = true;
371     m_webPage->send(Messages::LayerTreeCoordinatorProxy::SetCompositingLayerFilters(id, filters));
372 }
373 #endif
374
375 void LayerTreeCoordinator::attachLayer(WebGraphicsLayer* layer)
376 {
377     ASSERT(!m_registeredLayers.contains(layer));
378     m_registeredLayers.add(layer);
379
380     layer->setContentsScale(m_contentsScale);
381     layer->adjustVisibleRect();
382 }
383
384 void LayerTreeCoordinator::detachLayer(WebGraphicsLayer* layer)
385 {
386     m_registeredLayers.remove(layer);
387     m_shouldSyncFrame = true;
388     m_webPage->send(Messages::LayerTreeCoordinatorProxy::DeleteCompositingLayer(layer->id()));
389
390 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
391     m_compositedContentLayers.remove(layer->id());
392 #endif
393 #if ENABLE(TIZEN_ACCELERATED_2D_CANVAS_EFL)
394     m_compositedContentCanvas2DLayers.remove(layer->id());
395 #endif
396 }
397
398 static void updateOffsetFromViewportForSelf(RenderLayer* renderLayer)
399 {
400     // These conditions must match the conditions in RenderLayerCompositor::requiresCompositingForPosition.
401     RenderLayerBacking* backing = renderLayer->backing();
402     if (!backing)
403         return;
404
405     RenderStyle* style = renderLayer->renderer()->style();
406     if (!style)
407         return;
408
409     if (!renderLayer->renderer()->isOutOfFlowPositioned() || renderLayer->renderer()->style()->position() != FixedPosition)
410         return;
411
412     if (!renderLayer->renderer()->container()->isRenderView())
413         return;
414
415     if (!renderLayer->isStackingContext())
416         return;
417
418     WebGraphicsLayer* graphicsLayer = toWebGraphicsLayer(backing->graphicsLayer());
419     graphicsLayer->setFixedToViewport(true);
420 }
421
422 static void updateOffsetFromViewportForLayer(RenderLayer* renderLayer)
423 {
424     updateOffsetFromViewportForSelf(renderLayer);
425
426     if (renderLayer->firstChild())
427         updateOffsetFromViewportForLayer(renderLayer->firstChild());
428     if (renderLayer->nextSibling())
429         updateOffsetFromViewportForLayer(renderLayer->nextSibling());
430 }
431
432 void LayerTreeCoordinator::syncFixedLayers()
433 {
434     if (!m_webPage->corePage()->settings() || !m_webPage->corePage()->settings()->acceleratedCompositingForFixedPositionEnabled())
435         return;
436
437     if (!m_webPage->mainFrame()->view()->hasFixedObjects())
438         return;
439
440     RenderLayer* rootRenderLayer = m_webPage->mainFrame()->contentRenderer()->compositor()->rootRenderLayer();
441     ASSERT(rootRenderLayer);
442     if (rootRenderLayer->firstChild())
443         updateOffsetFromViewportForLayer(rootRenderLayer->firstChild());
444 }
445
446 void LayerTreeCoordinator::lockAnimations()
447 {
448     m_animationsLocked = true;
449     m_webPage->send(Messages::LayerTreeCoordinatorProxy::SetAnimationsLocked(true));
450 }
451
452 void LayerTreeCoordinator::unlockAnimations()
453 {
454     if (!m_animationsLocked)
455         return;
456
457     m_animationsLocked = false;
458     m_webPage->send(Messages::LayerTreeCoordinatorProxy::SetAnimationsLocked(false));
459 }
460
461 void LayerTreeCoordinator::performScheduledLayerFlush()
462 {
463 #if ENABLE(TIZEN_ACCELERATED_2D_CANVAS_EFL)
464     if (m_waitingForUIProcess && !m_compositedContentCanvas2DLayers.isEmpty()) {
465         Vector<uint32_t> weblayerIDsCopy;
466         copyToVector(m_compositedContentCanvas2DLayers, weblayerIDsCopy);
467         m_compositedContentCanvas2DLayers.clear();
468         for (size_t i = 0; i < weblayerIDsCopy.size(); ++i) {
469             WebGraphicsLayer* layer = WebGraphicsLayer::layerByID(weblayerIDsCopy[i]);
470             if (layer)
471                 layer->flushPlatformSurfaces();
472         }
473         return;
474     }
475 #endif
476
477     if (m_isSuspended || m_waitingForUIProcess)
478         return;
479
480 #if ENABLE(TIZEN_CUTOFF_TILES_OVER_MEMORY_LIMIT)
481     calculateCutOffThreshold();
482 #endif
483
484 #if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER) && !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
485     // Make sure that any previously registered animation callbacks are being executed before we flush the layers.
486     m_webPage->corePage()->mainFrame()->view()->serviceScriptedAnimations(convertSecondsToDOMTimeStamp(currentTime()));
487 #endif
488
489     // We lock the animations while performing layout, to avoid flickers caused by animations continuing in the UI process while
490     // the web process layout wants to cancel them.
491     lockAnimations();
492
493     m_webPage->layoutIfNeeded();
494
495     // We can unlock the animations before flushing if there are no visible changes, for example if there are content updates
496     // in a layer with opacity 0.
497     bool canUnlockBeforeFlush = !m_isValid || !toWebGraphicsLayer(m_rootLayer.get())->hasPendingVisibleChanges();
498     if (canUnlockBeforeFlush)
499         unlockAnimations();
500
501     if (!m_isValid)
502         return;
503
504 #if ENABLE(TIZEN_ONESHOT_DRAWING_SYNCHRONIZATION)
505     if (m_needsOneShotDrawingSynchronization) {
506         scheduleLayerFlush();
507         toWebGraphicsLayer(m_nonCompositedContentLayer.get())->adjustVisibleRect();
508         m_needsOneShotDrawingSynchronization = false;
509         return;
510     }
511 #endif
512
513     if (flushPendingLayerChanges())
514         didPerformScheduledLayerFlush();
515 }
516
517 void LayerTreeCoordinator::didPerformScheduledLayerFlush()
518 {
519     if (m_notifyAfterScheduledLayerFlush) {
520         static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers();
521         m_notifyAfterScheduledLayerFlush = false;
522     }
523 }
524
525 void LayerTreeCoordinator::layerFlushTimerFired(Timer<LayerTreeCoordinator>*)
526 {
527 #if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
528     m_webPage->connection()->clearWorkItemWhileWaitingForSyncReply(m_layerFlushWorkItemToDispatchWhileWaitingForSyncReply);
529     m_layerFlushWorkItemToDispatchWhileWaitingForSyncReply.clear();
530 #endif
531     performScheduledLayerFlush();
532 }
533
534 void LayerTreeCoordinator::createPageOverlayLayer()
535 {
536     ASSERT(!m_pageOverlayLayer);
537
538     m_pageOverlayLayer = GraphicsLayer::create(this);
539 #ifndef NDEBUG
540     m_pageOverlayLayer->setName("LayerTreeCoordinator page overlay content");
541 #endif
542
543     m_pageOverlayLayer->setDrawsContent(true);
544     m_pageOverlayLayer->setSize(m_webPage->size());
545
546     m_rootLayer->addChild(m_pageOverlayLayer.get());
547 }
548
549 void LayerTreeCoordinator::destroyPageOverlayLayer()
550 {
551     ASSERT(m_pageOverlayLayer);
552     m_pageOverlayLayer->removeFromParent();
553     m_pageOverlayLayer = nullptr;
554 }
555
556 int64_t LayerTreeCoordinator::adoptImageBackingStore(Image* image)
557 {
558     if (!image)
559         return InvalidWebLayerID;
560
561     int64_t key = 0;
562
563 #if PLATFORM(QT)
564     QImage* nativeImage = image->nativeImageForCurrentFrame();
565
566     if (!nativeImage)
567         return InvalidWebLayerID;
568
569     key = nativeImage->cacheKey();
570 #elif ENABLE(TIZEN_WEBKIT2_TILED_AC)
571     key = (int64_t)(image);
572 #endif
573
574     HashMap<int64_t, int>::iterator it = m_directlyCompositedImageRefCounts.find(key);
575
576     if (it != m_directlyCompositedImageRefCounts.end()) {
577         ++(it->second);
578         return key;
579     }
580
581     RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(image->size(), (image->currentFrameHasAlpha() ? ShareableBitmap::SupportsAlpha : 0));
582     {
583         OwnPtr<WebCore::GraphicsContext> graphicsContext = bitmap->createGraphicsContext();
584         graphicsContext->drawImage(image, ColorSpaceDeviceRGB, IntPoint::zero());
585     }
586
587     ShareableBitmap::Handle handle;
588     bitmap->createHandle(handle);
589     m_webPage->send(Messages::LayerTreeCoordinatorProxy::CreateDirectlyCompositedImage(key, handle));
590     m_directlyCompositedImageRefCounts.add(key, 1);
591     return key;
592 }
593
594 void LayerTreeCoordinator::releaseImageBackingStore(int64_t key)
595 {
596     if (!key)
597         return;
598     HashMap<int64_t, int>::iterator it = m_directlyCompositedImageRefCounts.find(key);
599     if (it == m_directlyCompositedImageRefCounts.end())
600         return;
601
602     it->second--;
603
604     if (it->second)
605         return;
606
607     m_directlyCompositedImageRefCounts.remove(it);
608     m_webPage->send(Messages::LayerTreeCoordinatorProxy::DestroyDirectlyCompositedImage(key));
609 }
610
611
612 void LayerTreeCoordinator::notifyAnimationStarted(const WebCore::GraphicsLayer*, double time)
613 {
614 }
615
616 void LayerTreeCoordinator::notifySyncRequired(const WebCore::GraphicsLayer*)
617 {
618 }
619
620 void LayerTreeCoordinator::paintContents(const WebCore::GraphicsLayer* graphicsLayer, WebCore::GraphicsContext& graphicsContext, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& clipRect)
621 {
622     if (graphicsLayer == m_nonCompositedContentLayer) {
623         m_webPage->drawRect(graphicsContext, clipRect);
624         return;
625     }
626
627     if (graphicsLayer == m_pageOverlayLayer) {
628         // Overlays contain transparent contents and won't clear the context as part of their rendering, so we do it here.
629         graphicsContext.clearRect(clipRect);
630         m_webPage->drawPageOverlay(graphicsContext, clipRect);
631         return;
632     }
633 }
634
635 bool LayerTreeCoordinator::showDebugBorders(const WebCore::GraphicsLayer*) const
636 {
637     return m_webPage->corePage()->settings()->showDebugBorders();
638 }
639
640 bool LayerTreeCoordinator::showRepaintCounter(const WebCore::GraphicsLayer*) const
641 {
642     return m_webPage->corePage()->settings()->showRepaintCounter();
643 }
644
645 bool LayerTreeHost::supportsAcceleratedCompositing()
646 {
647     return true;
648 }
649
650 void LayerTreeCoordinator::createTile(WebLayerID layerID, int tileID, const SurfaceUpdateInfo& updateInfo, const WebCore::IntRect& targetRect)
651 {
652     m_shouldSyncFrame = true;
653     m_webPage->send(Messages::LayerTreeCoordinatorProxy::CreateTileForLayer(layerID, tileID, targetRect, updateInfo));
654 }
655
656 void LayerTreeCoordinator::updateTile(WebLayerID layerID, int tileID, const SurfaceUpdateInfo& updateInfo, const WebCore::IntRect& targetRect)
657 {
658     m_shouldSyncFrame = true;
659     m_webPage->send(Messages::LayerTreeCoordinatorProxy::UpdateTileForLayer(layerID, tileID, targetRect, updateInfo));
660 }
661
662 void LayerTreeCoordinator::removeTile(WebLayerID layerID, int tileID)
663 {
664     m_shouldSyncFrame = true;
665     m_webPage->send(Messages::LayerTreeCoordinatorProxy::RemoveTileForLayer(layerID, tileID));
666 }
667
668 WebCore::IntRect LayerTreeCoordinator::visibleContentsRect() const
669 {
670     return m_visibleContentsRect;
671 }
672
673 void LayerTreeCoordinator::setLayerAnimations(WebLayerID layerID, const GraphicsLayerAnimations& animations)
674 {
675     m_shouldSyncFrame = true;
676     m_webPage->send(Messages::LayerTreeCoordinatorProxy::SetLayerAnimations(layerID, animations.getActiveAnimations()));
677 }
678
679 void LayerTreeCoordinator::setVisibleContentsRect(const IntRect& rect, float scale, const FloatPoint& trajectoryVector)
680 {
681     bool contentsRectDidChange = rect != m_visibleContentsRect;
682     bool contentsScaleDidChange = scale != m_contentsScale;
683
684     if (trajectoryVector != FloatPoint::zero())
685         toWebGraphicsLayer(m_nonCompositedContentLayer.get())->setVisibleContentRectTrajectoryVector(trajectoryVector);
686
687     if (contentsRectDidChange || contentsScaleDidChange) {
688         m_visibleContentsRect = rect;
689         m_contentsScale = scale;
690
691         HashSet<WebCore::WebGraphicsLayer*>::iterator end = m_registeredLayers.end();
692         for (HashSet<WebCore::WebGraphicsLayer*>::iterator it = m_registeredLayers.begin(); it != end; ++it) {
693             if (contentsScaleDidChange)
694                 (*it)->setContentsScale(scale);
695             if (contentsRectDidChange)
696 #if ENABLE(TIZEN_WEBKIT2_PRE_RENDERING_WITH_DIRECTIVITY)
697                 (*it)->setVisibleContentRectTrajectoryVector(trajectoryVector);
698 #else
699                 (*it)->adjustVisibleRect();
700 #endif
701         }
702     }
703
704     scheduleLayerFlush();
705     if (m_webPage->useFixedLayout())
706         m_webPage->setFixedVisibleContentRect(rect);
707     if (contentsRectDidChange)
708         m_shouldSendScrollPositionUpdate = true;
709 }
710
711 #if USE(UI_SIDE_COMPOSITING)
712 void LayerTreeCoordinator::scheduleAnimation()
713 {
714     scheduleLayerFlush();
715 }
716 #endif
717
718 void LayerTreeCoordinator::renderNextFrame()
719 {
720     m_waitingForUIProcess = false;
721 #if ENABLE(TIZEN_SYNC_REQUEST_ANIMATION_FRAME)
722 #if ENABLE(TIZEN_LAYER_FLUSH_THROTTLING)
723     if (m_layerFlushTimerDelay <= 0.0)
724 #endif
725         m_webPage->resumeAnimationController();
726 #endif
727     scheduleLayerFlush();
728 #if ENABLE(TIZEN_DAILY_UPVERSIONING)
729     for (size_t i = 0; i < m_updateAtlases.size(); ++i)
730 #else
731     for (int i = 0; i < m_updateAtlases.size(); ++i)
732 #endif
733         m_updateAtlases[i]->didSwapBuffers();
734
735 #if ENABLE(TIZEN_SYNC_REQUEST_ANIMATION_FRAME)
736 #if ENABLE(TIZEN_LAYER_FLUSH_THROTTLING)
737     if (m_layerFlushTimerDelay > 0.0)
738         m_webPage->resumeAnimationController();
739 #endif
740 #endif
741 }
742
743 #if ENABLE(TIZEN_WEBKIT2_ROTATION_WHILE_JAVASCRIPT_POPUP)
744 void LayerTreeCoordinator::performScheduledLayerFlushForcely()
745 {
746     if (!WebProcess::shared().isWaitingForJavaScriptPopupFinished())
747         return;
748
749     m_layerFlushTimer.stop();
750     m_webPage->connection()->clearWorkItemWhileWaitingForSyncReply(m_layerFlushWorkItemToDispatchWhileWaitingForSyncReply);
751     m_layerFlushWorkItemToDispatchWhileWaitingForSyncReply.clear();
752
753     m_waitingForUIProcess = false;
754
755     performScheduledLayerFlush();
756 }
757 #endif
758
759 bool LayerTreeCoordinator::layerTreeTileUpdatesAllowed() const
760 {
761     return !m_isSuspended && !m_waitingForUIProcess;
762 }
763
764 void LayerTreeCoordinator::purgeBackingStores()
765 {
766     HashSet<WebCore::WebGraphicsLayer*>::iterator end = m_registeredLayers.end();
767     for (HashSet<WebCore::WebGraphicsLayer*>::iterator it = m_registeredLayers.begin(); it != end; ++it)
768         (*it)->purgeBackingStores();
769
770     ASSERT(!m_directlyCompositedImageRefCounts.size());
771     m_updateAtlases.clear();
772 }
773
774 PassOwnPtr<WebCore::GraphicsContext> LayerTreeCoordinator::beginContentUpdate(const WebCore::IntSize& size, ShareableBitmap::Flags flags, ShareableSurface::Handle& handle, WebCore::IntPoint& offset)
775 {
776     OwnPtr<WebCore::GraphicsContext> graphicsContext;
777 #if ENABLE(TIZEN_DAILY_UPVERSIONING)
778     for (size_t i = 0; i < m_updateAtlases.size(); ++i) {
779 #else
780     for (int i = 0; i < m_updateAtlases.size(); ++i) {
781 #endif
782         UpdateAtlas* atlas = m_updateAtlases[i].get();
783         if (atlas->flags() == flags) {
784             // This will return null if there is no available buffer space.
785             graphicsContext = atlas->beginPaintingOnAvailableBuffer(handle, size, offset);
786             if (graphicsContext)
787                 return graphicsContext.release();
788         }
789     }
790
791     static const int ScratchBufferDimension = 1024;
792     m_updateAtlases.append(adoptPtr(new UpdateAtlas(ScratchBufferDimension, flags)));
793     scheduleReleaseInactiveAtlases();
794     return m_updateAtlases.last()->beginPaintingOnAvailableBuffer(handle, size, offset);
795 }
796
797 #if ENABLE(TIZEN_WEBKIT2_TILED_AC) && !ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
798 void LayerTreeCoordinator::pauseRendering()
799 {
800     m_isSuspended = true;
801 #if ENABLE(WEBGL)
802     // Make sure compositing webgl layer after returning from home screen.
803     HashSet<WebCore::WebGraphicsLayer*>::iterator end = m_registeredLayers.end();
804     for (HashSet<WebCore::WebGraphicsLayer*>::iterator it = m_registeredLayers.begin(); it != end; ++it) {
805         if ((*it)->contentType() == WebLayerInfo::Canvas3DContentType)
806             (*it)->markCanvasPlatformLayerNeedsUpdate();
807     }
808 #endif
809 }
810 #endif
811
812 #if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
813 void LayerTreeCoordinator::freePlatformSurface(int layerID, int platformSurfaceId)
814 {
815     WebGraphicsLayer* layer = WebGraphicsLayer::layerByID(layerID);
816     if (layer && (layer->contentType() == WebLayerInfo::Canvas3DContentType || layer->contentType() == WebLayerInfo::MediaContentType || layer->contentType() == WebLayerInfo::Canvas2DContentType)) {
817         layer->freePlatformSurface(platformSurfaceId);
818
819         if (m_suspendedJavaScript && layer->swapPlatformSurfaces()) {
820             m_webPage->resumeJavaScriptAndResources();
821             m_suspendedJavaScript = false;
822         }
823     }
824
825     // Even after a graphics layer just destroyed in WebProcess side,
826     // freePlatformSurface messages that destroyed layer can surely come.
827     // Therefore, below code should be run always before layer validity check.
828     WebProcess::shared().platformSurfacePool()->freePlatformSurface(platformSurfaceId);
829 }
830
831 void LayerTreeCoordinator::freePlatformSurfaceByTileID(int tileID)
832 {
833     WebProcess::shared().platformSurfacePool()->freePlatformSurfaceByTileID(tileID);
834 }
835
836 void LayerTreeCoordinator::removePlatformSurface(int layerID, int platformSurfaceId)
837 {
838     WebGraphicsLayer* layer = WebGraphicsLayer::layerByID(layerID);
839     if (layer && (layer->contentType() == WebLayerInfo::Canvas3DContentType || layer->contentType() == WebLayerInfo::MediaContentType || layer->contentType() == WebLayerInfo::Canvas2DContentType))
840         layer->removePlatformSurface(platformSurfaceId);
841 }
842 #endif
843
844 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
845 void LayerTreeCoordinator::setVisibleContentsRectAndTrajectoryVectorForLayer(int layerID, const WebCore::IntRect& visibleRect, const WebCore::FloatPoint& trajectoryVector)
846 {
847     GraphicsLayer* contentsLayer = WebGraphicsLayer::layerByID(layerID);
848     if (!contentsLayer)
849         return;
850
851     if (trajectoryVector != FloatPoint::zero()) {
852         m_webPage->scrollOverflowWithTrajectoryVector(trajectoryVector);
853         toWebGraphicsLayer(contentsLayer)->setVisibleContentRectTrajectoryVector(trajectoryVector);
854
855 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_SCROLLBAR)
856         const Vector<GraphicsLayer*>& childLayers = contentsLayer->children();
857         for (size_t i = 0; i < childLayers.size(); ++i)
858             if (childLayers[i]->isScrollbar())
859                toWebGraphicsLayer(childLayers[i])->startAnimation();
860 #endif
861     }
862     else
863         toWebGraphicsLayer(contentsLayer)->adjustVisibleRect();
864
865     scheduleLayerFlush();
866 }
867 #endif
868
869 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
870 void LayerTreeCoordinator::addOrUpdateScrollingLayer(WebCore::GraphicsLayer* scrollingLayer, WebCore::GraphicsLayer* contentsLayer, const WebCore::IntSize& scrollSize)
871 {
872     if (!scrollingLayer || !contentsLayer)
873         return;
874
875     toWebGraphicsLayer(contentsLayer)->setIsOverflow(true);
876 #if !ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
877     // FIXME: We might need to consider paddingBox margin for overflow scroll layer
878     // FloatPoint offset(-scrollingLayer->offsetFromRenderer().width() - scrollingLayer->boundsOrigin().x()
879     //        , -scrollingLayer->offsetFromRenderer().height() - scrollingLayer->boundsOrigin().y());
880     FloatPoint offset(scrollingLayer->boundsOrigin());
881     contentsLayer->setPosition(-offset);
882
883     IntRect visibleRect(FloatRect(offset, scrollingLayer->size()));
884
885     // FIXME: Need to set trajectoryVector?
886     // FloatPoint trajectoryVector(scrollingLayer->trajectoryVector());
887     // if (trajectoryVector != FloatPoint::zero())
888         //toWebGraphicsLayer(contentsLayer)->setVisibleContentRectTrajectoryVector(-trajectoryVector);
889
890     // FIXME: Scale factor might be changed.
891     // toWebGraphicsLayer(contentsLayer)->setContentsScale(m_contentsScale);
892 #else
893     setNeedsOneShotDrawingSynchronization();
894 #endif
895     toWebGraphicsLayer(contentsLayer)->adjustVisibleRect();
896 }
897
898 void LayerTreeCoordinator::removeScrollingLayer(WebCore::GraphicsLayer* scrollingLayer, WebCore::GraphicsLayer* contentsLayer)
899 {
900     if (!scrollingLayer || !contentsLayer)
901         return;
902
903     toWebGraphicsLayer(contentsLayer)->setIsOverflow(false);
904     toWebGraphicsLayer(contentsLayer)->syncLayerState();
905 }
906 #endif // ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
907
908 #if ENABLE(TIZEN_ONESHOT_DRAWING_SYNCHRONIZATION)
909 void LayerTreeCoordinator::setNeedsOneShotDrawingSynchronization()
910 {
911     m_needsOneShotDrawingSynchronization = true;
912 }
913 #endif
914
915 #if ENABLE(TIZEN_LAYER_FLUSH_THROTTLING)
916 void LayerTreeCoordinator::setDeferLayerFlush(bool deferLayerFlushEnabled)
917 {
918     m_deferLayerFlushEnabled = deferLayerFlushEnabled;
919     m_layerFlushTimerDelayLevel = 0;
920     double newDelay = deferredLayerFlushDelay();
921
922     // If the m_layerFlushTimer is already activated, we stop the old timer and then begin the timer with a new delay
923     if (m_layerFlushTimerDelay != newDelay && m_layerFlushTimer.isActive()) {
924         m_layerFlushTimer.stop();
925         m_layerFlushTimer.startOneShot(newDelay);
926     }
927     m_layerFlushTimerDelay = newDelay;
928
929 #if ENABLE(TIZEN_SYNC_REQUEST_ANIMATION_FRAME)
930     if (m_layerFlushTimerDelay == 0.0)
931         m_webPage->resumeAnimationController();
932 #endif
933 }
934
935 float LayerTreeCoordinator::deferredLayerFlushDelay()
936 {
937     if (!m_deferLayerFlushEnabled)
938          return 0;
939
940     if (m_layerFlushTimerDelayLevel >= s_layerFlushTimerDelayMaxLevel)
941         m_layerFlushTimerDelayLevel = s_layerFlushTimerDelayMaxLevel - 1;
942
943     return s_layerFlushTimerDelayTable[m_layerFlushTimerDelayLevel++];
944 }
945 #endif
946
947 #if ENABLE(TIZEN_CUTOFF_TILES_OVER_MEMORY_LIMIT)
948 static bool AscendingTileSortByDistance(TileCutOffInfo first, TileCutOffInfo second)
949 {
950     if (first.m_distance < second.m_distance)
951         return true;
952
953     return false;
954 }
955
956 void LayerTreeCoordinator::calculateCutOffThreshold()
957 {
958     Vector<WebCore::TileCutOffInfo> tilesCutOffInfo;
959     HashSet<WebCore::WebGraphicsLayer*>::iterator end = m_registeredLayers.end();
960     for (HashSet<WebCore::WebGraphicsLayer*>::iterator it = m_registeredLayers.begin(); it != end; ++it)
961         tilesCutOffInfo.append((*it)->getCutOffInfoList());
962     tilesCutOffInfo.append(toWebGraphicsLayer(m_nonCompositedContentLayer.get())->getCutOffInfoList());
963
964     std::sort(tilesCutOffInfo.begin(), tilesCutOffInfo.end(), AscendingTileSortByDistance);
965
966     size_t allocatedMemory = 0;
967     // FIXME: This patch will be considered in future.
968     // Need to correct offscreen-to-onscreen animation layer's tile cutoff computation
969     const size_t memoryLimit = 30 * 1024 * 1024; // 30 MB
970     double cutOffDistance = std::numeric_limits<double>::max();
971     for (size_t i = 0; i < tilesCutOffInfo.size(); ++i) {
972         TileCutOffInfo cutOffInfo = tilesCutOffInfo[i];
973         allocatedMemory += cutOffInfo.m_allocatedMemoryByte;
974         if (memoryLimit < allocatedMemory) {
975             cutOffDistance = cutOffInfo.m_distance;
976             break;
977         }
978     }
979
980     for (HashSet<WebCore::WebGraphicsLayer*>::iterator it = m_registeredLayers.begin(); it != end; ++it)
981         (*it)->setCutOffDistance(cutOffDistance);
982
983     toWebGraphicsLayer(m_nonCompositedContentLayer.get())->setCutOffDistance(cutOffDistance);
984 }
985 #endif
986
987 const double ReleaseInactiveAtlasesTimerInterval = 0.5;
988
989 void LayerTreeCoordinator::scheduleReleaseInactiveAtlases()
990 {
991     if (!m_releaseInactiveAtlasesTimer.isActive())
992         m_releaseInactiveAtlasesTimer.startRepeating(ReleaseInactiveAtlasesTimerInterval);
993 }
994
995 void LayerTreeCoordinator::releaseInactiveAtlasesTimerFired(Timer<LayerTreeCoordinator>*)
996 {
997     // We always want to keep one atlas for non-composited content.
998     OwnPtr<UpdateAtlas> atlasToKeepAnyway;
999     bool foundActiveAtlasForNonCompositedContent = false;
1000     for (int i = m_updateAtlases.size() - 1;  i >= 0; --i) {
1001         UpdateAtlas* atlas = m_updateAtlases[i].get();
1002         if (!atlas->isInUse())
1003             atlas->addTimeInactive(ReleaseInactiveAtlasesTimerInterval);
1004         bool usableForNonCompositedContent = !atlas->supportsAlpha();
1005         if (atlas->isInactive()) {
1006             if (!foundActiveAtlasForNonCompositedContent && !atlasToKeepAnyway && usableForNonCompositedContent)
1007                 atlasToKeepAnyway = m_updateAtlases[i].release();
1008             m_updateAtlases.remove(i);
1009         } else if (usableForNonCompositedContent)
1010             foundActiveAtlasForNonCompositedContent = true;
1011     }
1012
1013     if (!foundActiveAtlasForNonCompositedContent && atlasToKeepAnyway)
1014         m_updateAtlases.append(atlasToKeepAnyway.release());
1015
1016     if (m_updateAtlases.size() <= 1)
1017         m_releaseInactiveAtlasesTimer.stop();
1018 }
1019
1020 } // namespace WebKit