• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MaxPartialTextureUpdates()29 size_t ResourceUpdateController::MaxPartialTextureUpdates() {
30   return kPartialTextureUpdatesMax;
31 }
32 
MaxFullUpdatesPerTick(ResourceProvider * resource_provider)33 size_t ResourceUpdateController::MaxFullUpdatesPerTick(
34     ResourceProvider* resource_provider) {
35   return resource_provider->EstimatedUploadsPerTick();
36 }
37 
ResourceUpdateController(ResourceUpdateControllerClient * client,base::SingleThreadTaskRunner * task_runner,scoped_ptr<ResourceUpdateQueue> queue,ResourceProvider * resource_provider)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 
~ResourceUpdateController()53 ResourceUpdateController::~ResourceUpdateController() {}
54 
PerformMoreUpdates(base::TimeTicks time_limit)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 
DiscardUploadsToEvictedResources()82 void ResourceUpdateController::DiscardUploadsToEvictedResources() {
83   queue_->ClearUploadsToEvictedResources();
84 }
85 
UpdateTexture(ResourceUpdate update)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 
Finalize()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 
OnTimerFired()107 void ResourceUpdateController::OnTimerFired() {
108   task_posted_ = false;
109   if (!UpdateMoreTexturesIfEnoughTimeRemaining()) {
110     ready_to_finalize_ = true;
111     client_->ReadyToFinalizeTextureUpdates();
112   }
113 }
114 
UpdateMoreTexturesCompletionTime()115 base::TimeTicks ResourceUpdateController::UpdateMoreTexturesCompletionTime() {
116   return resource_provider_->EstimatedUploadCompletionTime(
117       texture_updates_per_tick_);
118 }
119 
UpdateMoreTexturesSize() const120 size_t ResourceUpdateController::UpdateMoreTexturesSize() const {
121   return texture_updates_per_tick_;
122 }
123 
MaxBlockingUpdates() const124 size_t ResourceUpdateController::MaxBlockingUpdates() const {
125   return UpdateMoreTexturesSize() * kMaxBlockingUpdateIntervals;
126 }
127 
UpdateMoreTexturesIfEnoughTimeRemaining()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 
UpdateMoreTexturesNow()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
165