Home | History | Annotate | Download | only in resources
      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       weak_factory_(this) {}
     51 
     52 ResourceUpdateController::~ResourceUpdateController() {}
     53 
     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 
     81 void ResourceUpdateController::DiscardUploadsToEvictedResources() {
     82   queue_->ClearUploadsToEvictedResources();
     83 }
     84 
     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 
     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 
    106 void ResourceUpdateController::OnTimerFired() {
    107   task_posted_ = false;
    108   if (!UpdateMoreTexturesIfEnoughTimeRemaining())
    109     client_->ReadyToFinalizeTextureUpdates();
    110 }
    111 
    112 base::TimeTicks ResourceUpdateController::UpdateMoreTexturesCompletionTime() {
    113   return resource_provider_->EstimatedUploadCompletionTime(
    114       texture_updates_per_tick_);
    115 }
    116 
    117 size_t ResourceUpdateController::UpdateMoreTexturesSize() const {
    118   return texture_updates_per_tick_;
    119 }
    120 
    121 size_t ResourceUpdateController::MaxBlockingUpdates() const {
    122   return UpdateMoreTexturesSize() * kMaxBlockingUpdateIntervals;
    123 }
    124 
    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 
    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