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 "cc/resources/resource_update_controller.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/location.h" | |
9 #include "base/single_thread_task_runner.h" | |
10 #include "cc/resources/prioritized_resource.h" | |
11 #include "cc/resources/resource_provider.h" | |
12 | |
13 namespace { | |
14 | |
15 // Number of partial updates we allow. | |
16 const size_t kPartialTextureUpdatesMax = 12; | |
17 | |
18 // Measured in seconds. | |
19 const double kUploaderBusyTickRate = 0.001; | |
20 | |
21 // Number of blocking update intervals to allow. | |
22 const size_t kMaxBlockingUpdateIntervals = 4; | |
23 | |
24 } // namespace | |
25 | |
26 namespace cc { | |
27 | |
28 size_t ResourceUpdateController::MaxPartialTextureUpdates() { | |
29 return kPartialTextureUpdatesMax; | |
30 } | |
31 | |
32 size_t ResourceUpdateController::MaxFullUpdatesPerTick( | |
33 ResourceProvider* resource_provider) { | |
34 return resource_provider->EstimatedUploadsPerTick(); | |
35 } | |
36 | |
37 ResourceUpdateController::ResourceUpdateController( | |
38 ResourceUpdateControllerClient* client, | |
39 base::SingleThreadTaskRunner* task_runner, | |
40 scoped_ptr<ResourceUpdateQueue> queue, | |
41 ResourceProvider* resource_provider) | |
42 : client_(client), | |
43 queue_(queue.Pass()), | |
44 resource_provider_(resource_provider), | |
45 texture_updates_per_tick_(MaxFullUpdatesPerTick(resource_provider)), | |
46 first_update_attempt_(true), | |
47 task_runner_(task_runner), | |
48 task_posted_(false), | |
49 ready_to_finalize_(false), | |
50 weak_factory_(this) {} | |
51 | |
52 ResourceUpdateController::~ResourceUpdateController() {} | |
53 | |
54 void ResourceUpdateController::PerformMoreUpdates( | |
55 base::TimeTicks time_limit) { | |
56 time_limit_ = time_limit; | |
57 | |
58 // Update already in progress or we are already done. | |
59 if (task_posted_ || ready_to_finalize_) | |
60 return; | |
61 | |
62 // Call UpdateMoreTexturesNow() directly unless it's the first update | |
63 // attempt. This ensures that we empty the update queue in a finite | |
64 // amount of time. | |
65 if (!first_update_attempt_) | |
66 UpdateMoreTexturesNow(); | |
67 | |
68 // Post a 0-delay task when no updates were left. When it runs, | |
69 // ReadyToFinalizeTextureUpdates() will be called. | |
70 if (!UpdateMoreTexturesIfEnoughTimeRemaining()) { | |
71 task_posted_ = true; | |
72 task_runner_->PostTask( | |
73 FROM_HERE, | |
74 base::Bind(&ResourceUpdateController::OnTimerFired, | |
75 weak_factory_.GetWeakPtr())); | |
76 } | |
77 | |
78 first_update_attempt_ = false; | |
79 } | |
80 | |
81 void ResourceUpdateController::DiscardUploadsToEvictedResources() { | |
82 queue_->ClearUploadsToEvictedResources(); | |
83 } | |
84 | |
85 void ResourceUpdateController::UpdateTexture(ResourceUpdate update) { | |
86 update.bitmap->lockPixels(); | |
87 update.texture->SetPixels( | |
88 resource_provider_, | |
89 static_cast<const uint8_t*>(update.bitmap->getPixels()), | |
90 update.content_rect, | |
91 update.source_rect, | |
92 update.dest_offset); | |
93 update.bitmap->unlockPixels(); | |
94 } | |
95 | |
96 void ResourceUpdateController::Finalize() { | |
97 while (queue_->FullUploadSize()) | |
98 UpdateTexture(queue_->TakeFirstFullUpload()); | |
99 | |
100 while (queue_->PartialUploadSize()) | |
101 UpdateTexture(queue_->TakeFirstPartialUpload()); | |
102 | |
103 resource_provider_->FlushUploads(); | |
104 } | |
105 | |
106 void ResourceUpdateController::OnTimerFired() { | |
107 task_posted_ = false; | |
108 if (!UpdateMoreTexturesIfEnoughTimeRemaining()) { | |
109 ready_to_finalize_ = true; | |
110 client_->ReadyToFinalizeTextureUpdates(); | |
111 } | |
112 } | |
113 | |
114 base::TimeTicks ResourceUpdateController::UpdateMoreTexturesCompletionTime() { | |
115 return resource_provider_->EstimatedUploadCompletionTime( | |
116 texture_updates_per_tick_); | |
117 } | |
118 | |
119 size_t ResourceUpdateController::UpdateMoreTexturesSize() const { | |
120 return texture_updates_per_tick_; | |
121 } | |
122 | |
123 size_t ResourceUpdateController::MaxBlockingUpdates() const { | |
124 return UpdateMoreTexturesSize() * kMaxBlockingUpdateIntervals; | |
125 } | |
126 | |
127 bool ResourceUpdateController::UpdateMoreTexturesIfEnoughTimeRemaining() { | |
128 while (resource_provider_->NumBlockingUploads() < MaxBlockingUpdates()) { | |
129 if (!queue_->FullUploadSize()) | |
130 return false; | |
131 | |
132 if (!time_limit_.is_null()) { | |
133 base::TimeTicks completion_time = UpdateMoreTexturesCompletionTime(); | |
134 if (completion_time > time_limit_) | |
135 return true; | |
136 } | |
137 | |
138 UpdateMoreTexturesNow(); | |
139 } | |
140 | |
141 task_posted_ = true; | |
142 task_runner_->PostDelayedTask( | |
143 FROM_HERE, | |
144 base::Bind(&ResourceUpdateController::OnTimerFired, | |
145 weak_factory_.GetWeakPtr()), | |
146 base::TimeDelta::FromMilliseconds(kUploaderBusyTickRate * 1000)); | |
147 return true; | |
148 } | |
149 | |
150 void ResourceUpdateController::UpdateMoreTexturesNow() { | |
151 size_t uploads = std::min( | |
152 queue_->FullUploadSize(), UpdateMoreTexturesSize()); | |
153 | |
154 if (!uploads) | |
155 return; | |
156 | |
157 while (queue_->FullUploadSize() && uploads--) | |
158 UpdateTexture(queue_->TakeFirstFullUpload()); | |
159 | |
160 resource_provider_->FlushUploads(); | |
161 } | |
162 | |
163 } // namespace cc | |
OLD | NEW |