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 "content/browser/compositor/browser_compositor_view_mac.h" 6 7#include "base/debug/trace_event.h" 8#include "base/lazy_instance.h" 9#include "content/browser/gpu/gpu_process_host_ui_shim.h" 10#include "content/browser/compositor/browser_compositor_view_private_mac.h" 11#include "content/common/gpu/gpu_messages.h" 12 13//////////////////////////////////////////////////////////////////////////////// 14// BrowserCompositorViewMac 15 16namespace content { 17namespace { 18 19// The number of placeholder objects allocated. If this reaches zero, then 20// the BrowserCompositorViewMacInternal being held on to for recycling, 21// |g_recyclable_internal_view|, will be freed. 22uint32 g_placeholder_count = 0; 23 24// A spare BrowserCompositorViewMacInternal kept around for recycling. 25base::LazyInstance<scoped_ptr<BrowserCompositorViewMacInternal>> 26 g_recyclable_internal_view; 27 28} // namespace 29 30BrowserCompositorViewMac::BrowserCompositorViewMac( 31 BrowserCompositorViewMacClient* client) : client_(client) { 32 // Try to use the recyclable BrowserCompositorViewMacInternal if there is one, 33 // otherwise allocate a new one. 34 // TODO(ccameron): If there exists a frame in flight (swap has been called 35 // by the compositor, but the frame has not arrived from the GPU process 36 // yet), then that frame may inappropriately flash in the new view. 37 internal_view_ = g_recyclable_internal_view.Get().Pass(); 38 if (!internal_view_) 39 internal_view_.reset(new BrowserCompositorViewMacInternal); 40 internal_view_->SetClient(client_); 41} 42 43BrowserCompositorViewMac::~BrowserCompositorViewMac() { 44 // Make this BrowserCompositorViewMacInternal recyclable for future instances. 45 internal_view_->ResetClient(); 46 g_recyclable_internal_view.Get() = internal_view_.Pass(); 47 48 // If there are no placeholders allocated, destroy the recyclable 49 // BrowserCompositorViewMacInternal that we just populated. 50 if (!g_placeholder_count) 51 g_recyclable_internal_view.Get().reset(); 52} 53 54ui::Compositor* BrowserCompositorViewMac::GetCompositor() const { 55 DCHECK(internal_view_); 56 return internal_view_->compositor(); 57} 58 59bool BrowserCompositorViewMac::HasFrameOfSize( 60 const gfx::Size& dip_size) const { 61 if (internal_view_) 62 return internal_view_->HasFrameOfSize(dip_size); 63 return false; 64} 65 66void BrowserCompositorViewMac::BeginPumpingFrames() { 67 if (internal_view_) 68 internal_view_->BeginPumpingFrames(); 69} 70 71void BrowserCompositorViewMac::EndPumpingFrames() { 72 if (internal_view_) 73 internal_view_->EndPumpingFrames(); 74} 75 76// static 77void BrowserCompositorViewMac::GotAcceleratedFrame( 78 gfx::AcceleratedWidget widget, 79 uint64 surface_handle, int surface_id, 80 const std::vector<ui::LatencyInfo>& latency_info, 81 gfx::Size pixel_size, float scale_factor, 82 int gpu_host_id, int gpu_route_id) { 83 BrowserCompositorViewMacInternal* internal_view = 84 BrowserCompositorViewMacInternal::FromAcceleratedWidget(widget); 85 int renderer_id = 0; 86 if (internal_view) { 87 internal_view->GotAcceleratedFrame( 88 surface_handle, surface_id, latency_info, pixel_size, scale_factor); 89 renderer_id = internal_view->GetRendererID(); 90 } 91 92 // Acknowledge the swap, now that it has been processed. 93 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; 94 ack_params.sync_point = 0; 95 ack_params.renderer_id = renderer_id; 96 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id); 97 if (ui_shim) { 98 ui_shim->Send(new AcceleratedSurfaceMsg_BufferPresented( 99 gpu_route_id, ack_params)); 100 } 101} 102 103// static 104void BrowserCompositorViewMac::GotSoftwareFrame( 105 gfx::AcceleratedWidget widget, 106 cc::SoftwareFrameData* frame_data, float scale_factor, SkCanvas* canvas) { 107 BrowserCompositorViewMacInternal* internal_view = 108 BrowserCompositorViewMacInternal::FromAcceleratedWidget(widget); 109 if (internal_view) 110 internal_view->GotSoftwareFrame(frame_data, scale_factor, canvas); 111} 112 113//////////////////////////////////////////////////////////////////////////////// 114// BrowserCompositorViewPlaceholderMac 115 116BrowserCompositorViewPlaceholderMac::BrowserCompositorViewPlaceholderMac() { 117 g_placeholder_count += 1; 118} 119 120BrowserCompositorViewPlaceholderMac::~BrowserCompositorViewPlaceholderMac() { 121 DCHECK_GT(g_placeholder_count, 0u); 122 g_placeholder_count -= 1; 123 124 // If there are no placeholders allocated, destroy the recyclable 125 // BrowserCompositorViewMacInternal. 126 if (!g_placeholder_count) 127 g_recyclable_internal_view.Get().reset(); 128} 129 130} // namespace content 131