blob: a844ee4f8466537c3511bfcff1179a6bc56ce4ab [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.
[email protected]a7c078b2012-09-20 17:52:1219static const size_t partialTextureUpdatesMax = 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]a7c078b2012-09-20 17:52:1236 return partialTextureUpdatesMax;
[email protected]41b8f682012-09-19 01:51:1737}
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]ed4685982012-09-18 03:44:5846CCTextureUpdateController::CCTextureUpdateController(CCTextureUpdateControllerClient* client, CCThread* thread, PassOwnPtr<CCTextureUpdateQueue> queue, CCResourceProvider* resourceProvider, TextureUploader* uploader)
[email protected]3c496dc2012-09-13 23:14:2047 : m_client(client)
48 , m_timer(adoptPtr(new CCTimer(thread, this)))
[email protected]94f206c12012-08-25 00:09:1449 , m_queue(queue)
50 , m_resourceProvider(resourceProvider)
[email protected]94f206c12012-08-25 00:09:1451 , m_uploader(uploader)
[email protected]41b8f682012-09-19 01:51:1752 , m_textureUpdatesPerTick(maxFullUpdatesPerTick(uploader))
[email protected]94f206c12012-08-25 00:09:1453 , m_firstUpdateAttempt(true)
54{
55}
56
57CCTextureUpdateController::~CCTextureUpdateController()
58{
59}
60
[email protected]12695152012-09-17 22:28:1461void CCTextureUpdateController::performMoreUpdates(
[email protected]d918afe2012-09-27 19:27:2162 base::TimeTicks timeLimit)
[email protected]94f206c12012-08-25 00:09:1463{
[email protected]d918afe2012-09-27 19:27:2164 m_timeLimit = timeLimit;
[email protected]94f206c12012-08-25 00:09:1465
[email protected]3c496dc2012-09-13 23:14:2066 // Update already in progress.
67 if (m_timer->isActive())
[email protected]94f206c12012-08-25 00:09:1468 return;
69
70 // Call updateMoreTexturesNow() directly unless it's the first update
71 // attempt. This ensures that we empty the update queue in a finite
72 // amount of time.
73 if (m_firstUpdateAttempt) {
[email protected]3c496dc2012-09-13 23:14:2074 // Post a 0-delay task when no updates were left. When it runs,
[email protected]12695152012-09-17 22:28:1475 // readyToFinalizeTextureUpdates() will be called.
[email protected]3c496dc2012-09-13 23:14:2076 if (!updateMoreTexturesIfEnoughTimeRemaining())
77 m_timer->startOneShot(0);
78
[email protected]94f206c12012-08-25 00:09:1479 m_firstUpdateAttempt = false;
80 } else
81 updateMoreTexturesNow();
82}
83
[email protected]77a60b9b2012-09-19 23:59:0184void CCTextureUpdateController::discardUploadsToEvictedResources()
85{
86 m_queue->clearUploadsToEvictedResources();
87}
88
[email protected]12695152012-09-17 22:28:1489void CCTextureUpdateController::finalize()
90{
[email protected]f961b792012-09-20 07:27:3391 size_t uploadCount = 0;
92 while (m_queue->fullUploadSize()) {
93 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
94 m_resourceProvider->shallowFlushIfSupported();
95
96 m_uploader->uploadTexture(
97 m_resourceProvider, m_queue->takeFirstFullUpload());
98 uploadCount++;
99 }
100
101 while (m_queue->partialUploadSize()) {
102 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
103 m_resourceProvider->shallowFlushIfSupported();
104
105 m_uploader->uploadTexture(
106 m_resourceProvider, m_queue->takeFirstPartialUpload());
107 uploadCount++;
108 }
109
110 if (uploadCount)
111 m_resourceProvider->shallowFlushIfSupported();
112
113 if (m_queue->copySize()) {
114 TextureCopier* copier = m_resourceProvider->textureCopier();
115 while (m_queue->copySize())
116 copier->copyTexture(m_queue->takeFirstCopy());
117
118 // If we've performed any texture copies, we need to insert a flush
119 // here into the compositor context before letting the main thread
120 // proceed as it may make draw calls to the source texture of one of
121 // our copy operations.
122 copier->flush();
123 }
[email protected]12695152012-09-17 22:28:14124}
125
[email protected]94f206c12012-08-25 00:09:14126void CCTextureUpdateController::onTimerFired()
127{
[email protected]3c496dc2012-09-13 23:14:20128 if (!updateMoreTexturesIfEnoughTimeRemaining())
[email protected]12695152012-09-17 22:28:14129 m_client->readyToFinalizeTextureUpdates();
[email protected]94f206c12012-08-25 00:09:14130}
131
[email protected]d918afe2012-09-27 19:27:21132base::TimeTicks CCTextureUpdateController::now() const
[email protected]94f206c12012-08-25 00:09:14133{
[email protected]d918afe2012-09-27 19:27:21134 return base::TimeTicks::Now();
[email protected]94f206c12012-08-25 00:09:14135}
136
[email protected]d918afe2012-09-27 19:27:21137base::TimeDelta CCTextureUpdateController::updateMoreTexturesTime() const
[email protected]94f206c12012-08-25 00:09:14138{
[email protected]d918afe2012-09-27 19:27:21139 return base::TimeDelta::FromMilliseconds(textureUpdateTickRate * 1000);
[email protected]94f206c12012-08-25 00:09:14140}
141
142size_t CCTextureUpdateController::updateMoreTexturesSize() const
143{
[email protected]41b8f682012-09-19 01:51:17144 return m_textureUpdatesPerTick;
[email protected]94f206c12012-08-25 00:09:14145}
146
[email protected]3c496dc2012-09-13 23:14:20147bool CCTextureUpdateController::updateMoreTexturesIfEnoughTimeRemaining()
[email protected]94f206c12012-08-25 00:09:14148{
[email protected]12695152012-09-17 22:28:14149 // Uploader might be busy when we're too aggressive in our upload time
150 // estimate. We use a different timeout here to prevent unnecessary
151 // amounts of idle time.
152 if (m_uploader->isBusy()) {
153 m_timer->startOneShot(uploaderBusyTickRate);
154 return true;
155 }
156
157 if (!m_queue->fullUploadSize())
[email protected]3c496dc2012-09-13 23:14:20158 return false;
159
[email protected]e8e410d2012-09-28 01:47:01160 bool hasTimeRemaining = m_timeLimit.is_null() ||
161 this->now() < m_timeLimit - updateMoreTexturesTime();
[email protected]94f206c12012-08-25 00:09:14162 if (hasTimeRemaining)
163 updateMoreTexturesNow();
[email protected]3c496dc2012-09-13 23:14:20164
165 return true;
[email protected]94f206c12012-08-25 00:09:14166}
167
168void CCTextureUpdateController::updateMoreTexturesNow()
169{
[email protected]12695152012-09-17 22:28:14170 size_t uploads = std::min(
171 m_queue->fullUploadSize(), updateMoreTexturesSize());
172 m_timer->startOneShot(
[email protected]d918afe2012-09-27 19:27:21173 updateMoreTexturesTime().InSecondsF() / updateMoreTexturesSize() *
174 uploads);
[email protected]12695152012-09-17 22:28:14175
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}