OLD | NEW |
| (Empty) |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 | |
7 #include "CCTextureUpdateController.h" | |
8 | |
9 #include "GraphicsContext3D.h" | |
10 #include "TextureCopier.h" | |
11 #include "TextureUploader.h" | |
12 #include "TraceEvent.h" | |
13 #include <limits> | |
14 #include <wtf/CurrentTime.h> | |
15 | |
16 namespace { | |
17 | |
18 // Number of partial updates we allow. | |
19 static const size_t partialTextureUpdatesMax = 12; | |
20 | |
21 // Measured in seconds. | |
22 static const double textureUpdateTickRate = 0.004; | |
23 | |
24 // Measured in seconds. | |
25 static const double uploaderBusyTickRate = 0.001; | |
26 | |
27 // Flush interval when performing texture uploads. | |
28 static const int textureUploadFlushPeriod = 4; | |
29 | |
30 // Number of blocking update intervals to allow. | |
31 static const size_t maxBlockingUpdateIntervals = 4; | |
32 | |
33 } // anonymous namespace | |
34 | |
35 namespace cc { | |
36 | |
37 size_t CCTextureUpdateController::maxPartialTextureUpdates() | |
38 { | |
39 return partialTextureUpdatesMax; | |
40 } | |
41 | |
42 size_t CCTextureUpdateController::maxFullUpdatesPerTick(TextureUploader* uploade
r) | |
43 { | |
44 double texturesPerSecond = uploader->estimatedTexturesPerSecond(); | |
45 size_t texturesPerTick = floor(textureUpdateTickRate * texturesPerSecond); | |
46 return texturesPerTick ? texturesPerTick : 1; | |
47 } | |
48 | |
49 CCTextureUpdateController::CCTextureUpdateController(CCTextureUpdateControllerCl
ient* client, CCThread* thread, PassOwnPtr<CCTextureUpdateQueue> queue, CCResour
ceProvider* resourceProvider, TextureUploader* uploader) | |
50 : m_client(client) | |
51 , m_timer(adoptPtr(new CCTimer(thread, this))) | |
52 , m_queue(queue) | |
53 , m_resourceProvider(resourceProvider) | |
54 , m_uploader(uploader) | |
55 , m_textureUpdatesPerTick(maxFullUpdatesPerTick(uploader)) | |
56 , m_firstUpdateAttempt(true) | |
57 { | |
58 } | |
59 | |
60 CCTextureUpdateController::~CCTextureUpdateController() | |
61 { | |
62 } | |
63 | |
64 void CCTextureUpdateController::performMoreUpdates( | |
65 base::TimeTicks timeLimit) | |
66 { | |
67 m_timeLimit = timeLimit; | |
68 | |
69 // Update already in progress. | |
70 if (m_timer->isActive()) | |
71 return; | |
72 | |
73 // Call updateMoreTexturesNow() directly unless it's the first update | |
74 // attempt. This ensures that we empty the update queue in a finite | |
75 // amount of time. | |
76 if (m_firstUpdateAttempt) { | |
77 // Post a 0-delay task when no updates were left. When it runs, | |
78 // readyToFinalizeTextureUpdates() will be called. | |
79 if (!updateMoreTexturesIfEnoughTimeRemaining()) | |
80 m_timer->startOneShot(0); | |
81 | |
82 m_firstUpdateAttempt = false; | |
83 } else | |
84 updateMoreTexturesNow(); | |
85 } | |
86 | |
87 void CCTextureUpdateController::discardUploadsToEvictedResources() | |
88 { | |
89 m_queue->clearUploadsToEvictedResources(); | |
90 } | |
91 | |
92 void CCTextureUpdateController::finalize() | |
93 { | |
94 size_t uploadCount = 0; | |
95 while (m_queue->fullUploadSize()) { | |
96 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount) | |
97 m_resourceProvider->shallowFlushIfSupported(); | |
98 | |
99 m_uploader->uploadTexture( | |
100 m_resourceProvider, m_queue->takeFirstFullUpload()); | |
101 uploadCount++; | |
102 } | |
103 | |
104 while (m_queue->partialUploadSize()) { | |
105 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount) | |
106 m_resourceProvider->shallowFlushIfSupported(); | |
107 | |
108 m_uploader->uploadTexture( | |
109 m_resourceProvider, m_queue->takeFirstPartialUpload()); | |
110 uploadCount++; | |
111 } | |
112 | |
113 if (uploadCount) | |
114 m_resourceProvider->shallowFlushIfSupported(); | |
115 | |
116 if (m_queue->copySize()) { | |
117 TextureCopier* copier = m_resourceProvider->textureCopier(); | |
118 while (m_queue->copySize()) | |
119 copier->copyTexture(m_queue->takeFirstCopy()); | |
120 | |
121 // If we've performed any texture copies, we need to insert a flush | |
122 // here into the compositor context before letting the main thread | |
123 // proceed as it may make draw calls to the source texture of one of | |
124 // our copy operations. | |
125 copier->flush(); | |
126 } | |
127 } | |
128 | |
129 void CCTextureUpdateController::onTimerFired() | |
130 { | |
131 if (!updateMoreTexturesIfEnoughTimeRemaining()) | |
132 m_client->readyToFinalizeTextureUpdates(); | |
133 } | |
134 | |
135 base::TimeTicks CCTextureUpdateController::now() const | |
136 { | |
137 return base::TimeTicks::Now(); | |
138 } | |
139 | |
140 base::TimeDelta CCTextureUpdateController::updateMoreTexturesTime() const | |
141 { | |
142 return base::TimeDelta::FromMilliseconds(textureUpdateTickRate * 1000); | |
143 } | |
144 | |
145 size_t CCTextureUpdateController::updateMoreTexturesSize() const | |
146 { | |
147 return m_textureUpdatesPerTick; | |
148 } | |
149 | |
150 size_t CCTextureUpdateController::maxBlockingUpdates() const | |
151 { | |
152 return updateMoreTexturesSize() * maxBlockingUpdateIntervals; | |
153 } | |
154 | |
155 bool CCTextureUpdateController::updateMoreTexturesIfEnoughTimeRemaining() | |
156 { | |
157 // Blocking uploads will increase when we're too aggressive in our upload | |
158 // time estimate. We use a different timeout here to prevent unnecessary | |
159 // amounts of idle time when blocking uploads have reached the max. | |
160 if (m_uploader->numBlockingUploads() >= maxBlockingUpdates()) { | |
161 m_timer->startOneShot(uploaderBusyTickRate); | |
162 return true; | |
163 } | |
164 | |
165 if (!m_queue->fullUploadSize()) | |
166 return false; | |
167 | |
168 bool hasTimeRemaining = m_timeLimit.is_null() || | |
169 this->now() < m_timeLimit - updateMoreTexturesTime(); | |
170 if (hasTimeRemaining) | |
171 updateMoreTexturesNow(); | |
172 | |
173 return true; | |
174 } | |
175 | |
176 void CCTextureUpdateController::updateMoreTexturesNow() | |
177 { | |
178 size_t uploads = std::min( | |
179 m_queue->fullUploadSize(), updateMoreTexturesSize()); | |
180 m_timer->startOneShot( | |
181 updateMoreTexturesTime().InSecondsF() / updateMoreTexturesSize() * | |
182 uploads); | |
183 | |
184 if (!uploads) | |
185 return; | |
186 | |
187 size_t uploadCount = 0; | |
188 while (m_queue->fullUploadSize() && uploadCount < uploads) { | |
189 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount) | |
190 m_resourceProvider->shallowFlushIfSupported(); | |
191 m_uploader->uploadTexture(m_resourceProvider, m_queue->takeFirstFullUplo
ad()); | |
192 uploadCount++; | |
193 } | |
194 m_resourceProvider->shallowFlushIfSupported(); | |
195 } | |
196 | |
197 } | |
OLD | NEW |