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