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