84b8423588bc48f03c9668fdd1cf1c8de73ed975
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCScheduler.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "cc/CCScheduler.h"
28 #include "TraceEvent.h"
29
30 namespace WebCore {
31
32 CCScheduler::CCScheduler(CCSchedulerClient* client, PassOwnPtr<CCFrameRateController> frameRateController)
33     : m_client(client)
34     , m_frameRateController(frameRateController)
35     , m_updateMoreResourcesPending(false)
36 {
37     ASSERT(m_client);
38     m_frameRateController->setClient(this);
39     m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
40 }
41
42 CCScheduler::~CCScheduler()
43 {
44     m_frameRateController->setActive(false);
45 }
46
47 void CCScheduler::setCanBeginFrame(bool can)
48 {
49     m_stateMachine.setCanBeginFrame(can);
50     processScheduledActions();
51 }
52
53 void CCScheduler::setVisible(bool visible)
54 {
55     m_stateMachine.setVisible(visible);
56     processScheduledActions();
57 }
58
59 void CCScheduler::setNeedsCommit()
60 {
61     m_stateMachine.setNeedsCommit();
62     processScheduledActions();
63 }
64
65 void CCScheduler::setNeedsForcedCommit()
66 {
67     m_stateMachine.setNeedsForcedCommit();
68     processScheduledActions();
69 }
70
71 void CCScheduler::setNeedsRedraw()
72 {
73     m_stateMachine.setNeedsRedraw();
74     processScheduledActions();
75 }
76
77 void CCScheduler::setNeedsForcedRedraw()
78 {
79     m_stateMachine.setNeedsForcedRedraw();
80     processScheduledActions();
81 }
82
83 void CCScheduler::setMainThreadNeedsLayerTextures()
84 {
85     m_stateMachine.setMainThreadNeedsLayerTextures();
86     processScheduledActions();
87 }
88
89 void CCScheduler::beginFrameComplete()
90 {
91     TRACE_EVENT("CCScheduler::beginFrameComplete", this, 0);
92     m_stateMachine.beginFrameComplete();
93     processScheduledActions();
94 }
95
96 void CCScheduler::setMaxFramesPending(int maxFramesPending)
97 {
98     m_frameRateController->setMaxFramesPending(maxFramesPending);
99 }
100
101 void CCScheduler::didSwapBuffersComplete()
102 {
103     TRACE_EVENT("CCScheduler::didSwapBuffersComplete", this, 0);
104     m_frameRateController->didFinishFrame();
105 }
106
107 void CCScheduler::didLoseContext()
108 {
109     TRACE_EVENT("CCScheduler::didLoseContext", this, 0);
110     m_frameRateController->didAbortAllPendingFrames();
111     m_stateMachine.didLoseContext();
112     processScheduledActions();
113 }
114
115 void CCScheduler::didRecreateContext()
116 {
117     TRACE_EVENT("CCScheduler::didRecreateContext", this, 0);
118     m_stateMachine.didRecreateContext();
119     processScheduledActions();
120 }
121
122 void CCScheduler::vsyncTick()
123 {
124     if (m_updateMoreResourcesPending) {
125         m_updateMoreResourcesPending = false;
126         m_stateMachine.beginUpdateMoreResourcesComplete(m_client->hasMoreResourceUpdates());
127     }
128     TRACE_EVENT("CCScheduler::vsyncTick", this, 0);
129
130     m_stateMachine.didEnterVSync();
131     processScheduledActions();
132     m_stateMachine.didLeaveVSync();
133 }
134
135 CCSchedulerStateMachine::Action CCScheduler::nextAction()
136 {
137     m_stateMachine.setCanDraw(m_client->canDraw());
138     return m_stateMachine.nextAction();
139 }
140
141 void CCScheduler::processScheduledActions()
142 {
143     // Early out so we don't spam TRACE_EVENTS with useless processScheduledActions.
144     if (nextAction() == CCSchedulerStateMachine::ACTION_NONE) {
145         m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
146         return;
147     }
148
149     // This function can re-enter itself. For example, draw may call
150     // setNeedsCommit. Proceeed with caution.
151     CCSchedulerStateMachine::Action action;
152     do {
153         action = nextAction();
154         m_stateMachine.updateState(action);
155
156         switch (action) {
157         case CCSchedulerStateMachine::ACTION_NONE:
158             break;
159         case CCSchedulerStateMachine::ACTION_BEGIN_FRAME:
160             m_client->scheduledActionBeginFrame();
161             break;
162         case CCSchedulerStateMachine::ACTION_BEGIN_UPDATE_MORE_RESOURCES:
163             m_client->scheduledActionUpdateMoreResources();
164             if (!m_client->hasMoreResourceUpdates()) {
165                 // If we were just told to update resources, but there are no
166                 // more pending, then tell the state machine that the
167                 // beginUpdateMoreResources completed. If more are pending,
168                 // then we will ack the update at the next draw.
169                 m_updateMoreResourcesPending = false;
170                 m_stateMachine.beginUpdateMoreResourcesComplete(false);
171             } else
172                 m_updateMoreResourcesPending = true;
173             break;
174         case CCSchedulerStateMachine::ACTION_COMMIT:
175             m_client->scheduledActionCommit();
176             break;
177         case CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: {
178             CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapIfPossible();
179             m_stateMachine.didDrawIfPossibleCompleted(result.didDraw);
180             if (result.didSwap)
181                 m_frameRateController->didBeginFrame();
182             break;
183         }
184         case CCSchedulerStateMachine::ACTION_DRAW_FORCED: {
185             CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapForced();
186             if (result.didSwap)
187                 m_frameRateController->didBeginFrame();
188             break;
189         } case CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION:
190             m_client->scheduledActionBeginContextRecreation();
191             break;
192         case CCSchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
193             m_client->scheduledActionAcquireLayerTexturesForMainThread();
194             break;
195         }
196     } while (action != CCSchedulerStateMachine::ACTION_NONE);
197
198     // Activate or deactivate the frame rate controller.
199     m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
200 }
201
202 }