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"
12 #include "ui/gfx/frame_time.h"
16 // Number of partial updates we allow.
17 const size_t kPartialTextureUpdatesMax
= 12;
19 // Measured in seconds.
20 const double kUploaderBusyTickRate
= 0.001;
22 // Number of blocking update intervals to allow.
23 const size_t kMaxBlockingUpdateIntervals
= 4;
29 size_t ResourceUpdateController::MaxPartialTextureUpdates() {
30 return kPartialTextureUpdatesMax
;
33 size_t ResourceUpdateController::MaxFullUpdatesPerTick(
34 ResourceProvider
* resource_provider
) {
35 return resource_provider
->EstimatedUploadsPerTick();
38 ResourceUpdateController::ResourceUpdateController(
39 ResourceUpdateControllerClient
* client
,
40 base::SingleThreadTaskRunner
* task_runner
,
41 scoped_ptr
<ResourceUpdateQueue
> queue
,
42 ResourceProvider
* resource_provider
)
45 resource_provider_(resource_provider
),
46 texture_updates_per_tick_(MaxFullUpdatesPerTick(resource_provider
)),
47 first_update_attempt_(true),
48 task_runner_(task_runner
),
50 ready_to_finalize_(false),
51 weak_factory_(this) {}
53 ResourceUpdateController::~ResourceUpdateController() {}
55 void ResourceUpdateController::PerformMoreUpdates(
56 base::TimeTicks time_limit
) {
57 time_limit_
= time_limit
;
59 // Update already in progress or we are already done.
60 if (task_posted_
|| ready_to_finalize_
)
63 // Call UpdateMoreTexturesNow() directly unless it's the first update
64 // attempt. This ensures that we empty the update queue in a finite
66 if (!first_update_attempt_
)
67 UpdateMoreTexturesNow();
69 // Post a 0-delay task when no updates were left. When it runs,
70 // ReadyToFinalizeTextureUpdates() will be called.
71 if (!UpdateMoreTexturesIfEnoughTimeRemaining()) {
73 task_runner_
->PostTask(
75 base::Bind(&ResourceUpdateController::OnTimerFired
,
76 weak_factory_
.GetWeakPtr()));
79 first_update_attempt_
= false;
82 void ResourceUpdateController::DiscardUploadsToEvictedResources() {
83 queue_
->ClearUploadsToEvictedResources();
86 void ResourceUpdateController::UpdateTexture(ResourceUpdate update
) {
87 update
.bitmap
->lockPixels();
88 update
.texture
->SetPixels(
90 static_cast<const uint8_t*>(update
.bitmap
->getPixels()),
94 update
.bitmap
->unlockPixels();
97 void ResourceUpdateController::Finalize() {
98 while (queue_
->FullUploadSize())
99 UpdateTexture(queue_
->TakeFirstFullUpload());
101 while (queue_
->PartialUploadSize())
102 UpdateTexture(queue_
->TakeFirstPartialUpload());
104 resource_provider_
->FlushUploads();
107 void ResourceUpdateController::OnTimerFired() {
108 task_posted_
= false;
109 if (!UpdateMoreTexturesIfEnoughTimeRemaining()) {
110 ready_to_finalize_
= true;
111 client_
->ReadyToFinalizeTextureUpdates();
115 base::TimeTicks
ResourceUpdateController::UpdateMoreTexturesCompletionTime() {
116 return resource_provider_
->EstimatedUploadCompletionTime(
117 texture_updates_per_tick_
);
120 size_t ResourceUpdateController::UpdateMoreTexturesSize() const {
121 return texture_updates_per_tick_
;
124 size_t ResourceUpdateController::MaxBlockingUpdates() const {
125 return UpdateMoreTexturesSize() * kMaxBlockingUpdateIntervals
;
128 bool ResourceUpdateController::UpdateMoreTexturesIfEnoughTimeRemaining() {
129 while (resource_provider_
->NumBlockingUploads() < MaxBlockingUpdates()) {
130 if (!queue_
->FullUploadSize())
133 if (!time_limit_
.is_null()) {
134 base::TimeTicks completion_time
= UpdateMoreTexturesCompletionTime();
135 if (completion_time
> time_limit_
)
139 UpdateMoreTexturesNow();
143 task_runner_
->PostDelayedTask(
145 base::Bind(&ResourceUpdateController::OnTimerFired
,
146 weak_factory_
.GetWeakPtr()),
147 base::TimeDelta::FromMilliseconds(kUploaderBusyTickRate
* 1000));
151 void ResourceUpdateController::UpdateMoreTexturesNow() {
152 size_t uploads
= std::min(
153 queue_
->FullUploadSize(), UpdateMoreTexturesSize());
158 while (queue_
->FullUploadSize() && uploads
--)
159 UpdateTexture(queue_
->TakeFirstFullUpload());
161 resource_provider_
->FlushUploads();