OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 | 6 |
7 #include "CCTextureUpdateController.h" | 7 #include "CCTextureUpdateController.h" |
8 | 8 |
9 #include "GraphicsContext3D.h" | 9 #include "GraphicsContext3D.h" |
10 #include "TextureCopier.h" | 10 #include "TextureCopier.h" |
11 #include "TextureUploader.h" | 11 #include "TextureUploader.h" |
| 12 #include "TraceEvent.h" |
| 13 #include <limits> |
12 #include <wtf/CurrentTime.h> | 14 #include <wtf/CurrentTime.h> |
13 | 15 |
14 namespace { | 16 namespace { |
15 | 17 |
16 // Number of textures to update with each call to updateMoreTexturesIfEnoughTime
Remaining(). | 18 static const size_t pixelsPerTexture = 256 * 256; |
17 static const size_t textureUpdatesPerTick = 12; | 19 |
| 20 // Minimum number of textures to update with each call to updateMoreTexturesIfEn
oughTimeRemaining(). |
| 21 static const size_t textureUpdatesPerFullTickMin = 12; |
18 | 22 |
19 // Measured in seconds. | 23 // Measured in seconds. |
20 static const double textureUpdateTickRate = 0.004; | 24 static const double textureUpdateTickRate = 0.004; |
21 | 25 |
22 // Flush interval when performing texture uploads. | 26 // Flush interval when performing texture uploads. |
23 static const int textureUploadFlushPeriod = 4; | 27 static const int textureUploadFlushPeriod = 4; |
24 | 28 |
25 } // anonymous namespace | 29 } // anonymous namespace |
26 | 30 |
27 namespace WebCore { | 31 namespace WebCore { |
28 | 32 |
29 size_t CCTextureUpdateController::maxPartialTextureUpdates() | 33 size_t CCTextureUpdateController::maxTextureUpdates(TextureUploader* uploader) |
30 { | 34 { |
31 return textureUpdatesPerTick; | 35 double texturesPerSecond = uploader->estimatedPixelsPerSecond() / pixelsPerT
exture; |
| 36 |
| 37 return std::max(textureUpdatesPerFullTickMin, |
| 38 (size_t) floor(textureUpdateTickRate * texturesPerSecond)); |
| 39 } |
| 40 |
| 41 PassOwnPtr<CCTextureUpdateController> CCTextureUpdateController::create(CCThread
* thread, PassOwnPtr<CCTextureUpdateQueue> queue, CCResourceProvider* resourcePr
ovider, TextureCopier* copier, TextureUploader* uploader, size_t maxTextureUpdat
es) |
| 42 { |
| 43 return adoptPtr(new CCTextureUpdateController(thread, queue, resourceProvide
r, copier, uploader, maxTextureUpdates)); |
32 } | 44 } |
33 | 45 |
34 void CCTextureUpdateController::updateTextures(CCResourceProvider* resourceProvi
der, TextureCopier* copier, TextureUploader* uploader, CCTextureUpdateQueue* que
ue, size_t count) | 46 void CCTextureUpdateController::updateTextures(CCResourceProvider* resourceProvi
der, TextureCopier* copier, TextureUploader* uploader, CCTextureUpdateQueue* que
ue, size_t count) |
35 { | 47 { |
36 if (queue->fullUploadSize() || queue->partialUploadSize()) { | 48 if (queue->fullUploadSize() || queue->partialUploadSize()) { |
37 if (uploader->isBusy()) | 49 if (uploader->isBusy()) |
38 return; | 50 return; |
39 | 51 |
40 uploader->beginUploads(); | 52 uploader->beginUploads(); |
41 | 53 |
42 size_t fullUploadCount = 0; | 54 size_t fullUploadCount = 0; |
43 while (queue->fullUploadSize() && fullUploadCount < count) { | 55 bool uploadMore = queue->fullUploadSize() && fullUploadCount < count; |
| 56 while (uploadMore) { |
44 uploader->uploadTexture(resourceProvider, queue->takeFirstFullUpload
()); | 57 uploader->uploadTexture(resourceProvider, queue->takeFirstFullUpload
()); |
45 fullUploadCount++; | 58 fullUploadCount++; |
46 if (!(fullUploadCount % textureUploadFlushPeriod)) | 59 uploadMore = queue->fullUploadSize() && fullUploadCount < count; |
| 60 |
| 61 // Flush periodically, but deffer our last flush until after uploade
r->endUploads() |
| 62 // in order to keep the query associated with endUploads grouped wit
h our last texture upload. |
| 63 if (!(fullUploadCount % textureUploadFlushPeriod) && uploadMore) |
47 resourceProvider->shallowFlushIfSupported(); | 64 resourceProvider->shallowFlushIfSupported(); |
48 } | 65 } |
49 | 66 |
50 // Make sure there are no dangling uploads without a flush. | 67 ASSERT(queue->partialUploadSize() <= count); |
51 if (fullUploadCount % textureUploadFlushPeriod) | 68 bool needAnotherTick = queue->fullUploadSize() || ((count - fullUploadCo
unt) < queue->partialUploadSize()); |
| 69 if (needAnotherTick) { |
| 70 uploader->endUploads(); |
52 resourceProvider->shallowFlushIfSupported(); | 71 resourceProvider->shallowFlushIfSupported(); |
53 | |
54 bool moreUploads = queue->fullUploadSize(); | |
55 | |
56 ASSERT(queue->partialUploadSize() <= count); | |
57 // We need another update batch if the number of updates remaining | |
58 // in |count| is greater than the remaining partial entries. | |
59 if ((count - fullUploadCount) < queue->partialUploadSize()) | |
60 moreUploads = true; | |
61 | |
62 if (moreUploads) { | |
63 uploader->endUploads(); | |
64 return; | 72 return; |
65 } | 73 } |
| 74 resourceProvider->shallowFlushIfSupported(); |
66 | 75 |
67 size_t partialUploadCount = 0; | 76 size_t partialUploadCount = 0; |
68 while (queue->partialUploadSize()) { | 77 while (queue->partialUploadSize()) { |
69 uploader->uploadTexture(resourceProvider, queue->takeFirstPartialUpl
oad()); | 78 uploader->uploadTexture(resourceProvider, queue->takeFirstPartialUpl
oad()); |
70 partialUploadCount++; | 79 partialUploadCount++; |
71 if (!(partialUploadCount % textureUploadFlushPeriod)) | 80 |
| 81 // Flush periodically, but deffer our last flush until after uploade
r->endUploads() |
| 82 // in order to keep the query associated with endUploads grouped wit
h our last texture upload. |
| 83 if (!(partialUploadCount % textureUploadFlushPeriod) && queue->parti
alUploadSize()) |
72 resourceProvider->shallowFlushIfSupported(); | 84 resourceProvider->shallowFlushIfSupported(); |
73 } | 85 } |
74 | 86 |
75 // Make sure there are no dangling partial uploads without a flush. | |
76 if (partialUploadCount % textureUploadFlushPeriod) | |
77 resourceProvider->shallowFlushIfSupported(); | |
78 | |
79 uploader->endUploads(); | 87 uploader->endUploads(); |
| 88 resourceProvider->shallowFlushIfSupported(); |
80 } | 89 } |
81 | 90 |
82 size_t copyCount = 0; | 91 size_t copyCount = 0; |
83 while (queue->copySize()) { | 92 while (queue->copySize()) { |
84 copier->copyTexture(queue->takeFirstCopy()); | 93 copier->copyTexture(queue->takeFirstCopy()); |
85 copyCount++; | 94 copyCount++; |
86 } | 95 } |
87 | 96 |
88 // If we've performed any texture copies, we need to insert a flush here int
o the compositor context | 97 // If we've performed any texture copies, we need to insert a flush here int
o the compositor context |
89 // before letting the main thread proceed as it may make draw calls to the s
ource texture of one of | 98 // before letting the main thread proceed as it may make draw calls to the s
ource texture of one of |
90 // our copy operations. | 99 // our copy operations. |
91 if (copyCount) | 100 if (copyCount) |
92 copier->flush(); | 101 copier->flush(); |
93 } | 102 } |
94 | 103 |
95 CCTextureUpdateController::CCTextureUpdateController(CCThread* thread, PassOwnPt
r<CCTextureUpdateQueue> queue, CCResourceProvider* resourceProvider, TextureCopi
er* copier, TextureUploader* uploader) | 104 CCTextureUpdateController::CCTextureUpdateController(CCThread* thread, PassOwnPt
r<CCTextureUpdateQueue> queue, CCResourceProvider* resourceProvider, TextureCopi
er* copier, TextureUploader* uploader, size_t maxTextureUpdates) |
96 : m_timer(adoptPtr(new CCTimer(thread, this))) | 105 : m_timer(adoptPtr(new CCTimer(thread, this))) |
97 , m_queue(queue) | 106 , m_queue(queue) |
98 , m_resourceProvider(resourceProvider) | 107 , m_resourceProvider(resourceProvider) |
99 , m_copier(copier) | 108 , m_copier(copier) |
100 , m_uploader(uploader) | 109 , m_uploader(uploader) |
101 , m_monotonicTimeLimit(0) | 110 , m_monotonicTimeLimit(0) |
| 111 , m_textureUpdatesPerTick(maxTextureUpdates) |
102 , m_firstUpdateAttempt(true) | 112 , m_firstUpdateAttempt(true) |
103 { | 113 { |
104 } | 114 } |
105 | 115 |
106 CCTextureUpdateController::~CCTextureUpdateController() | 116 CCTextureUpdateController::~CCTextureUpdateController() |
107 { | 117 { |
108 } | 118 } |
109 | 119 |
110 bool CCTextureUpdateController::hasMoreUpdates() const | 120 bool CCTextureUpdateController::hasMoreUpdates() const |
111 { | 121 { |
112 return m_queue->hasMoreUpdates(); | 122 return m_queue->hasMoreUpdates(); |
113 } | 123 } |
114 | 124 |
115 void CCTextureUpdateController::updateMoreTextures(double monotonicTimeLimit) | 125 void CCTextureUpdateController::updateMoreTextures(double monotonicTimeLimit) |
116 { | 126 { |
117 m_monotonicTimeLimit = monotonicTimeLimit; | 127 m_monotonicTimeLimit = monotonicTimeLimit; |
118 | 128 |
119 if (!m_queue->hasMoreUpdates()) | 129 if (!m_queue->hasMoreUpdates()) |
120 return; | 130 return; |
121 | 131 |
122 // Call updateMoreTexturesNow() directly unless it's the first update | 132 // Call updateMoreTexturesNow() directly unless it's the first update |
123 // attempt. This ensures that we empty the update queue in a finite | 133 // attempt. This ensures that we empty the update queue in a finite |
124 // amount of time. | 134 // amount of time. |
125 if (m_firstUpdateAttempt) { | 135 if (m_firstUpdateAttempt) { |
126 updateMoreTexturesIfEnoughTimeRemaining(); | 136 updateMoreTexturesIfEnoughTimeRemaining(); |
127 m_firstUpdateAttempt = false; | 137 m_firstUpdateAttempt = false; |
128 } else | 138 } else |
129 updateMoreTexturesNow(); | 139 updateMoreTexturesNow(); |
| 140 |
130 } | 141 } |
131 | 142 |
132 void CCTextureUpdateController::onTimerFired() | 143 void CCTextureUpdateController::onTimerFired() |
133 { | 144 { |
134 if (!m_queue->hasMoreUpdates()) | 145 if (!m_queue->hasMoreUpdates()) |
135 return; | 146 return; |
136 | 147 |
137 updateMoreTexturesIfEnoughTimeRemaining(); | 148 updateMoreTexturesIfEnoughTimeRemaining(); |
138 } | 149 } |
139 | 150 |
140 double CCTextureUpdateController::monotonicTimeNow() const | 151 double CCTextureUpdateController::monotonicTimeNow() const |
141 { | 152 { |
142 return monotonicallyIncreasingTime(); | 153 return monotonicallyIncreasingTime(); |
143 } | 154 } |
144 | 155 |
145 double CCTextureUpdateController::updateMoreTexturesTime() const | 156 double CCTextureUpdateController::updateMoreTexturesTime() const |
146 { | 157 { |
147 return textureUpdateTickRate; | 158 return textureUpdateTickRate; |
148 } | 159 } |
149 | 160 |
150 size_t CCTextureUpdateController::updateMoreTexturesSize() const | 161 size_t CCTextureUpdateController::updateMoreTexturesSize() const |
151 { | 162 { |
152 return textureUpdatesPerTick; | 163 return m_textureUpdatesPerTick; |
153 } | 164 } |
154 | 165 |
155 void CCTextureUpdateController::updateMoreTexturesIfEnoughTimeRemaining() | 166 void CCTextureUpdateController::updateMoreTexturesIfEnoughTimeRemaining() |
156 { | 167 { |
157 bool hasTimeRemaining = monotonicTimeNow() < m_monotonicTimeLimit - updateMo
reTexturesTime(); | 168 bool hasTimeRemaining = monotonicTimeNow() < m_monotonicTimeLimit - updateMo
reTexturesTime(); |
158 if (hasTimeRemaining) | 169 if (hasTimeRemaining) |
159 updateMoreTexturesNow(); | 170 updateMoreTexturesNow(); |
160 } | 171 } |
161 | 172 |
162 void CCTextureUpdateController::updateMoreTexturesNow() | 173 void CCTextureUpdateController::updateMoreTexturesNow() |
163 { | 174 { |
164 m_timer->startOneShot(updateMoreTexturesTime()); | 175 m_timer->startOneShot(updateMoreTexturesTime()); |
165 updateTextures(m_resourceProvider, m_copier, m_uploader, m_queue.get(), upda
teMoreTexturesSize()); | 176 updateTextures(m_resourceProvider, m_copier, m_uploader, m_queue.get(), upda
teMoreTexturesSize()); |
166 } | 177 } |
167 | 178 |
168 } | 179 } |
OLD | NEW |