Home | History | Annotate | Download | only in surfaces
      1 // Copyright 2014 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/surfaces/display.h"
      6 
      7 #include "base/debug/trace_event.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "cc/output/compositor_frame.h"
     10 #include "cc/output/compositor_frame_ack.h"
     11 #include "cc/output/direct_renderer.h"
     12 #include "cc/output/gl_renderer.h"
     13 #include "cc/output/software_renderer.h"
     14 #include "cc/surfaces/display_client.h"
     15 #include "cc/surfaces/surface.h"
     16 #include "cc/surfaces/surface_aggregator.h"
     17 #include "cc/surfaces/surface_manager.h"
     18 #include "cc/trees/blocking_task_runner.h"
     19 
     20 namespace cc {
     21 
     22 Display::Display(DisplayClient* client,
     23                  SurfaceManager* manager,
     24                  SharedBitmapManager* bitmap_manager)
     25     : client_(client),
     26       manager_(manager),
     27       bitmap_manager_(bitmap_manager),
     28       blocking_main_thread_task_runner_(
     29           BlockingTaskRunner::Create(base::MessageLoopProxy::current())) {
     30   manager_->AddObserver(this);
     31 }
     32 
     33 Display::~Display() {
     34   manager_->RemoveObserver(this);
     35 }
     36 
     37 void Display::Resize(SurfaceId id, const gfx::Size& size) {
     38   current_surface_id_ = id;
     39   current_surface_size_ = size;
     40   client_->DisplayDamaged();
     41 }
     42 
     43 void Display::InitializeOutputSurface() {
     44   if (output_surface_)
     45     return;
     46   scoped_ptr<OutputSurface> output_surface = client_->CreateOutputSurface();
     47   if (!output_surface->BindToClient(this))
     48     return;
     49 
     50   int highp_threshold_min = 0;
     51   bool use_rgba_4444_texture_format = false;
     52   size_t id_allocation_chunk_size = 1;
     53   bool use_distance_field_text = false;
     54   scoped_ptr<ResourceProvider> resource_provider =
     55       ResourceProvider::Create(output_surface.get(),
     56                                bitmap_manager_,
     57                                blocking_main_thread_task_runner_.get(),
     58                                highp_threshold_min,
     59                                use_rgba_4444_texture_format,
     60                                id_allocation_chunk_size,
     61                                use_distance_field_text);
     62   if (!resource_provider)
     63     return;
     64 
     65   if (output_surface->context_provider()) {
     66     TextureMailboxDeleter* texture_mailbox_deleter = NULL;
     67     scoped_ptr<GLRenderer> renderer =
     68         GLRenderer::Create(this,
     69                            &settings_,
     70                            output_surface.get(),
     71                            resource_provider.get(),
     72                            texture_mailbox_deleter,
     73                            highp_threshold_min);
     74     if (!renderer)
     75       return;
     76     renderer_ = renderer.Pass();
     77   } else {
     78     scoped_ptr<SoftwareRenderer> renderer = SoftwareRenderer::Create(
     79         this, &settings_, output_surface.get(), resource_provider.get());
     80     if (!renderer)
     81       return;
     82     renderer_ = renderer.Pass();
     83   }
     84 
     85   output_surface_ = output_surface.Pass();
     86   resource_provider_ = resource_provider.Pass();
     87   aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get()));
     88 }
     89 
     90 bool Display::Draw() {
     91   if (current_surface_id_.is_null())
     92     return false;
     93 
     94   InitializeOutputSurface();
     95   if (!output_surface_)
     96     return false;
     97 
     98   // TODO(skyostil): We should hold a BlockingTaskRunner::CapturePostTasks
     99   // while Aggregate is called to immediately run release callbacks afterward.
    100   scoped_ptr<CompositorFrame> frame =
    101       aggregator_->Aggregate(current_surface_id_);
    102   if (!frame)
    103     return false;
    104 
    105   TRACE_EVENT0("cc", "Display::Draw");
    106   DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
    107 
    108   // Only reshape when we know we are going to draw. Otherwise, the reshape
    109   // can leave the window at the wrong size if we never draw and the proper
    110   // viewport size is never set.
    111   output_surface_->Reshape(current_surface_size_, 1.f);
    112   float device_scale_factor = 1.0f;
    113   gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_);
    114   gfx::Rect device_clip_rect = device_viewport_rect;
    115   bool disable_picture_quad_image_filtering = false;
    116 
    117   renderer_->DecideRenderPassAllocationsForFrame(frame_data->render_pass_list);
    118   renderer_->DrawFrame(&frame_data->render_pass_list,
    119                        device_scale_factor,
    120                        device_viewport_rect,
    121                        device_clip_rect,
    122                        disable_picture_quad_image_filtering);
    123   renderer_->SwapBuffers(frame->metadata);
    124   for (SurfaceAggregator::SurfaceIndexMap::iterator it =
    125            aggregator_->previous_contained_surfaces().begin();
    126        it != aggregator_->previous_contained_surfaces().end();
    127        ++it) {
    128     Surface* surface = manager_->GetSurfaceForId(it->first);
    129     if (surface)
    130       surface->RunDrawCallbacks();
    131   }
    132   return true;
    133 }
    134 
    135 void Display::DidSwapBuffers() {
    136   client_->DidSwapBuffers();
    137 }
    138 
    139 void Display::DidSwapBuffersComplete() {
    140   client_->DidSwapBuffersComplete();
    141 }
    142 
    143 void Display::CommitVSyncParameters(base::TimeTicks timebase,
    144                                     base::TimeDelta interval) {
    145   client_->CommitVSyncParameters(timebase, interval);
    146 }
    147 
    148 void Display::OnSurfaceDamaged(SurfaceId surface) {
    149   if (aggregator_ && aggregator_->previous_contained_surfaces().count(surface))
    150     client_->DisplayDamaged();
    151 }
    152 
    153 SurfaceId Display::CurrentSurfaceId() {
    154   return current_surface_id_;
    155 }
    156 
    157 int Display::GetMaxFramesPending() {
    158   if (!output_surface_)
    159     return OutputSurface::DEFAULT_MAX_FRAMES_PENDING;
    160   return output_surface_->capabilities().max_frames_pending;
    161 }
    162 
    163 }  // namespace cc
    164