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