blob: 8b273850f7f7955095987ef5ca6a42c346639923 [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// 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"
[email protected]41b8f682012-09-19 01:51:1712#include "TraceEvent.h"
13#include <limits>
[email protected]94f206c12012-08-25 00:09:1414#include <wtf/CurrentTime.h>
15
16namespace {
17
[email protected]41b8f682012-09-19 01:51:1718// Number of partial updates we allow.
19static const size_t maxPartialTextureUpdatesMax = 12;
[email protected]94f206c12012-08-25 00:09:1420
21// Measured in seconds.
22static const double textureUpdateTickRate = 0.004;
23
[email protected]12695152012-09-17 22:28:1424// Measured in seconds.
25static const double uploaderBusyTickRate = 0.001;
26
[email protected]94f206c12012-08-25 00:09:1427// Flush interval when performing texture uploads.
28static const int textureUploadFlushPeriod = 4;
29
30} // anonymous namespace
31
[email protected]9c88e562012-09-14 22:21:3032namespace cc {
[email protected]94f206c12012-08-25 00:09:1433
34size_t CCTextureUpdateController::maxPartialTextureUpdates()
35{
[email protected]41b8f682012-09-19 01:51:1736 return maxPartialTextureUpdatesMax;
37}
38
39size_t CCTextureUpdateController::maxFullUpdatesPerTick(TextureUploader* uploader)
40{
41 double texturesPerSecond = uploader->estimatedTexturesPerSecond();
42 size_t texturesPerTick = floor(textureUpdateTickRate * texturesPerSecond);
43 return texturesPerTick ? texturesPerTick : 1;
[email protected]94f206c12012-08-25 00:09:1444}
45
[email protected]cc11ff32012-09-18 14:46:1546void CCTextureUpdateController::updateTextures(CCResourceProvider* resourceProvider, TextureUploader* uploader, CCTextureUpdateQueue* queue)
[email protected]94f206c12012-08-25 00:09:1447{
[email protected]cc11ff32012-09-18 14:46:1548 size_t uploadCount = 0;
49 while (queue->fullUploadSize()) {
50 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
[email protected]94f206c12012-08-25 00:09:1451 resourceProvider->shallowFlushIfSupported();
52
[email protected]cc11ff32012-09-18 14:46:1553 uploader->uploadTexture(
54 resourceProvider, queue->takeFirstFullUpload());
55 uploadCount++;
56 }
[email protected]94f206c12012-08-25 00:09:1457
[email protected]cc11ff32012-09-18 14:46:1558 while (queue->partialUploadSize()) {
59 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
[email protected]94f206c12012-08-25 00:09:1460 resourceProvider->shallowFlushIfSupported();
61
[email protected]cc11ff32012-09-18 14:46:1562 uploader->uploadTexture(
63 resourceProvider, queue->takeFirstPartialUpload());
64 uploadCount++;
[email protected]94f206c12012-08-25 00:09:1465 }
66
[email protected]cc11ff32012-09-18 14:46:1567 if (uploadCount)
68 resourceProvider->shallowFlushIfSupported();
[email protected]94f206c12012-08-25 00:09:1469
[email protected]cc11ff32012-09-18 14:46:1570 if (queue->copySize()) {
71 TextureCopier* copier = resourceProvider->textureCopier();
72 while (queue->copySize())
73 copier->copyTexture(queue->takeFirstCopy());
74
75 // If we've performed any texture copies, we need to insert a flush
76 // here into the compositor context before letting the main thread
77 // proceed as it may make draw calls to the source texture of one of
78 // our copy operations.
[email protected]94f206c12012-08-25 00:09:1479 copier->flush();
[email protected]cc11ff32012-09-18 14:46:1580 }
[email protected]94f206c12012-08-25 00:09:1481}
82
[email protected]ed4685982012-09-18 03:44:5883CCTextureUpdateController::CCTextureUpdateController(CCTextureUpdateControllerClient* client, CCThread* thread, PassOwnPtr<CCTextureUpdateQueue> queue, CCResourceProvider* resourceProvider, TextureUploader* uploader)
[email protected]3c496dc2012-09-13 23:14:2084 : m_client(client)
85 , m_timer(adoptPtr(new CCTimer(thread, this)))
[email protected]94f206c12012-08-25 00:09:1486 , m_queue(queue)
87 , m_resourceProvider(resourceProvider)
[email protected]94f206c12012-08-25 00:09:1488 , m_uploader(uploader)
89 , m_monotonicTimeLimit(0)
[email protected]41b8f682012-09-19 01:51:1790 , m_textureUpdatesPerTick(maxFullUpdatesPerTick(uploader))
[email protected]94f206c12012-08-25 00:09:1491 , m_firstUpdateAttempt(true)
92{
93}
94
95CCTextureUpdateController::~CCTextureUpdateController()
96{
97}
98
[email protected]12695152012-09-17 22:28:1499void CCTextureUpdateController::performMoreUpdates(
100 double monotonicTimeLimit)
[email protected]94f206c12012-08-25 00:09:14101{
[email protected]3c496dc2012-09-13 23:14:20102 ASSERT(monotonicTimeLimit >= m_monotonicTimeLimit);
[email protected]94f206c12012-08-25 00:09:14103 m_monotonicTimeLimit = monotonicTimeLimit;
104
[email protected]3c496dc2012-09-13 23:14:20105 // Update already in progress.
106 if (m_timer->isActive())
[email protected]94f206c12012-08-25 00:09:14107 return;
108
109 // Call updateMoreTexturesNow() directly unless it's the first update
110 // attempt. This ensures that we empty the update queue in a finite
111 // amount of time.
112 if (m_firstUpdateAttempt) {
[email protected]3c496dc2012-09-13 23:14:20113 // Post a 0-delay task when no updates were left. When it runs,
[email protected]12695152012-09-17 22:28:14114 // readyToFinalizeTextureUpdates() will be called.
[email protected]3c496dc2012-09-13 23:14:20115 if (!updateMoreTexturesIfEnoughTimeRemaining())
116 m_timer->startOneShot(0);
117
[email protected]94f206c12012-08-25 00:09:14118 m_firstUpdateAttempt = false;
119 } else
120 updateMoreTexturesNow();
121}
122
[email protected]12695152012-09-17 22:28:14123void CCTextureUpdateController::finalize()
124{
[email protected]cc11ff32012-09-18 14:46:15125 updateTextures(m_resourceProvider, m_uploader, m_queue.get());
[email protected]12695152012-09-17 22:28:14126}
127
[email protected]94f206c12012-08-25 00:09:14128void CCTextureUpdateController::onTimerFired()
129{
[email protected]3c496dc2012-09-13 23:14:20130 if (!updateMoreTexturesIfEnoughTimeRemaining())
[email protected]12695152012-09-17 22:28:14131 m_client->readyToFinalizeTextureUpdates();
[email protected]94f206c12012-08-25 00:09:14132}
133
134double CCTextureUpdateController::monotonicTimeNow() const
135{
136 return monotonicallyIncreasingTime();
137}
138
139double CCTextureUpdateController::updateMoreTexturesTime() const
140{
141 return textureUpdateTickRate;
142}
143
144size_t CCTextureUpdateController::updateMoreTexturesSize() const
145{
[email protected]41b8f682012-09-19 01:51:17146 return m_textureUpdatesPerTick;
[email protected]94f206c12012-08-25 00:09:14147}
148
[email protected]3c496dc2012-09-13 23:14:20149bool CCTextureUpdateController::updateMoreTexturesIfEnoughTimeRemaining()
[email protected]94f206c12012-08-25 00:09:14150{
[email protected]12695152012-09-17 22:28:14151 // Uploader might be busy when we're too aggressive in our upload time
152 // estimate. We use a different timeout here to prevent unnecessary
153 // amounts of idle time.
154 if (m_uploader->isBusy()) {
155 m_timer->startOneShot(uploaderBusyTickRate);
156 return true;
157 }
158
159 if (!m_queue->fullUploadSize())
[email protected]3c496dc2012-09-13 23:14:20160 return false;
161
[email protected]94f206c12012-08-25 00:09:14162 bool hasTimeRemaining = monotonicTimeNow() < m_monotonicTimeLimit - updateMoreTexturesTime();
163 if (hasTimeRemaining)
164 updateMoreTexturesNow();
[email protected]3c496dc2012-09-13 23:14:20165
166 return true;
[email protected]94f206c12012-08-25 00:09:14167}
168
169void CCTextureUpdateController::updateMoreTexturesNow()
170{
[email protected]12695152012-09-17 22:28:14171 size_t uploads = std::min(
172 m_queue->fullUploadSize(), updateMoreTexturesSize());
173 m_timer->startOneShot(
174 updateMoreTexturesTime() / updateMoreTexturesSize() * uploads);
175
176 if (!uploads)
177 return;
178
[email protected]12695152012-09-17 22:28:14179 size_t uploadCount = 0;
[email protected]41b8f682012-09-19 01:51:17180 m_uploader->beginUploads();
181 while (m_queue->fullUploadSize() && uploadCount < uploads) {
182 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
[email protected]12695152012-09-17 22:28:14183 m_resourceProvider->shallowFlushIfSupported();
[email protected]41b8f682012-09-19 01:51:17184 m_uploader->uploadTexture(m_resourceProvider, m_queue->takeFirstFullUpload());
185 uploadCount++;
[email protected]12695152012-09-17 22:28:14186 }
[email protected]12695152012-09-17 22:28:14187 m_uploader->endUploads();
[email protected]41b8f682012-09-19 01:51:17188 m_resourceProvider->shallowFlushIfSupported();
[email protected]94f206c12012-08-25 00:09:14189}
190
191}