• 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       weak_factory_(this) {}
51 
~ResourceUpdateController()52 ResourceUpdateController::~ResourceUpdateController() {}
53 
PerformMoreUpdates(base::TimeTicks time_limit)54 void ResourceUpdateController::PerformMoreUpdates(
55     base::TimeTicks time_limit) {
56   time_limit_ = time_limit;
57 
58   // Update already in progress.
59   if (task_posted_)
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 
DiscardUploadsToEvictedResources()81 void ResourceUpdateController::DiscardUploadsToEvictedResources() {
82   queue_->ClearUploadsToEvictedResources();
83 }
84 
UpdateTexture(ResourceUpdate update)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 
Finalize()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 
OnTimerFired()106 void ResourceUpdateController::OnTimerFired() {
107   task_posted_ = false;
108   if (!UpdateMoreTexturesIfEnoughTimeRemaining())
109     client_->ReadyToFinalizeTextureUpdates();
110 }
111 
UpdateMoreTexturesCompletionTime()112 base::TimeTicks ResourceUpdateController::UpdateMoreTexturesCompletionTime() {
113   return resource_provider_->EstimatedUploadCompletionTime(
114       texture_updates_per_tick_);
115 }
116 
UpdateMoreTexturesSize() const117 size_t ResourceUpdateController::UpdateMoreTexturesSize() const {
118   return texture_updates_per_tick_;
119 }
120 
MaxBlockingUpdates() const121 size_t ResourceUpdateController::MaxBlockingUpdates() const {
122   return UpdateMoreTexturesSize() * kMaxBlockingUpdateIntervals;
123 }
124 
UpdateMoreTexturesIfEnoughTimeRemaining()125 bool ResourceUpdateController::UpdateMoreTexturesIfEnoughTimeRemaining() {
126   while (resource_provider_->NumBlockingUploads() < MaxBlockingUpdates()) {
127     if (!queue_->FullUploadSize())
128       return false;
129 
130     if (!time_limit_.is_null()) {
131       base::TimeTicks completion_time = UpdateMoreTexturesCompletionTime();
132       if (completion_time > time_limit_)
133         return true;
134     }
135 
136     UpdateMoreTexturesNow();
137   }
138 
139   task_posted_ = true;
140   task_runner_->PostDelayedTask(
141       FROM_HERE,
142       base::Bind(&ResourceUpdateController::OnTimerFired,
143                  weak_factory_.GetWeakPtr()),
144       base::TimeDelta::FromMilliseconds(kUploaderBusyTickRate * 1000));
145   return true;
146 }
147 
UpdateMoreTexturesNow()148 void ResourceUpdateController::UpdateMoreTexturesNow() {
149   size_t uploads = std::min(
150       queue_->FullUploadSize(), UpdateMoreTexturesSize());
151 
152   if (!uploads)
153     return;
154 
155   while (queue_->FullUploadSize() && uploads--)
156     UpdateTexture(queue_->TakeFirstFullUpload());
157 
158   resource_provider_->FlushUploads();
159 }
160 
161 }  // namespace cc
162