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.
5 #include "cc/resources/resource_update_controller.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"
15 // Number of partial updates we allow.
16 const size_t kPartialTextureUpdatesMax
= 12;
18 // Measured in seconds.
19 const double kUploaderBusyTickRate
= 0.001;
21 // Number of blocking update intervals to allow.
22 const size_t kMaxBlockingUpdateIntervals
= 4;
28 size_t ResourceUpdateController::MaxPartialTextureUpdates() {
29 return kPartialTextureUpdatesMax
;
32 size_t ResourceUpdateController::MaxFullUpdatesPerTick(
33 ResourceProvider
* resource_provider
) {
34 return resource_provider
->EstimatedUploadsPerTick();
37 ResourceUpdateController::ResourceUpdateController(
38 ResourceUpdateControllerClient
* client
,
39 base::SingleThreadTaskRunner
* task_runner
,
40 scoped_ptr
<ResourceUpdateQueue
> queue
,
41 ResourceProvider
* resource_provider
)
44 resource_provider_(resource_provider
),
45 texture_updates_per_tick_(MaxFullUpdatesPerTick(resource_provider
)),
46 first_update_attempt_(true),
47 task_runner_(task_runner
),
49 ready_to_finalize_(false),
50 weak_factory_(this) {}
52 ResourceUpdateController::~ResourceUpdateController() {}
54 void ResourceUpdateController::PerformMoreUpdates(
55 base::TimeTicks time_limit
) {
56 time_limit_
= time_limit
;
58 // Update already in progress or we are already done.
59 if (task_posted_
|| ready_to_finalize_
)
62 // Call UpdateMoreTexturesNow() directly unless it's the first update
63 // attempt. This ensures that we empty the update queue in a finite
65 if (!first_update_attempt_
)
66 UpdateMoreTexturesNow();
68 // Post a 0-delay task when no updates were left. When it runs,
69 // ReadyToFinalizeTextureUpdates() will be called.
70 if (!UpdateMoreTexturesIfEnoughTimeRemaining()) {
72 task_runner_
->PostTask(
74 base::Bind(&ResourceUpdateController::OnTimerFired
,
75 weak_factory_
.GetWeakPtr()));
78 first_update_attempt_
= false;
81 void ResourceUpdateController::DiscardUploadsToEvictedResources() {
82 queue_
->ClearUploadsToEvictedResources();
85 void ResourceUpdateController::UpdateTexture(ResourceUpdate update
) {
86 update
.bitmap
->lockPixels();
87 update
.texture
->SetPixels(
89 static_cast<const uint8_t*>(update
.bitmap
->getPixels()),
93 update
.bitmap
->unlockPixels();
96 void ResourceUpdateController::Finalize() {
97 while (queue_
->FullUploadSize())
98 UpdateTexture(queue_
->TakeFirstFullUpload());
100 while (queue_
->PartialUploadSize())
101 UpdateTexture(queue_
->TakeFirstPartialUpload());
103 resource_provider_
->FlushUploads();
106 void ResourceUpdateController::OnTimerFired() {
107 task_posted_
= false;
108 if (!UpdateMoreTexturesIfEnoughTimeRemaining()) {
109 ready_to_finalize_
= true;
110 client_
->ReadyToFinalizeTextureUpdates();
114 base::TimeTicks
ResourceUpdateController::UpdateMoreTexturesCompletionTime() {
115 return resource_provider_
->EstimatedUploadCompletionTime(
116 texture_updates_per_tick_
);
119 size_t ResourceUpdateController::UpdateMoreTexturesSize() const {
120 return texture_updates_per_tick_
;
123 size_t ResourceUpdateController::MaxBlockingUpdates() const {
124 return UpdateMoreTexturesSize() * kMaxBlockingUpdateIntervals
;
127 bool ResourceUpdateController::UpdateMoreTexturesIfEnoughTimeRemaining() {
128 while (resource_provider_
->NumBlockingUploads() < MaxBlockingUpdates()) {
129 if (!queue_
->FullUploadSize())
132 if (!time_limit_
.is_null()) {
133 base::TimeTicks completion_time
= UpdateMoreTexturesCompletionTime();
134 if (completion_time
> time_limit_
)
138 UpdateMoreTexturesNow();
142 task_runner_
->PostDelayedTask(
144 base::Bind(&ResourceUpdateController::OnTimerFired
,
145 weak_factory_
.GetWeakPtr()),
146 base::TimeDelta::FromMilliseconds(kUploaderBusyTickRate
* 1000));
150 void ResourceUpdateController::UpdateMoreTexturesNow() {
151 size_t uploads
= std::min(
152 queue_
->FullUploadSize(), UpdateMoreTexturesSize());
157 while (queue_
->FullUploadSize() && uploads
--)
158 UpdateTexture(queue_
->TakeFirstFullUpload());
160 resource_provider_
->FlushUploads();