1// Copyright (c) 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 "content/browser/gpu/gpu_process_host_ui_shim.h" 6 7#include <algorithm> 8 9#include "base/bind.h" 10#include "base/debug/trace_event.h" 11#include "base/id_map.h" 12#include "base/lazy_instance.h" 13#include "base/strings/string_number_conversions.h" 14#include "content/browser/gpu/gpu_data_manager_impl.h" 15#include "content/browser/gpu/gpu_process_host.h" 16#include "content/browser/gpu/gpu_surface_tracker.h" 17#include "content/browser/renderer_host/render_process_host_impl.h" 18#include "content/browser/renderer_host/render_view_host_impl.h" 19#include "content/browser/renderer_host/render_widget_host_view_base.h" 20#include "content/common/gpu/gpu_messages.h" 21#include "content/public/browser/browser_thread.h" 22 23#if defined(USE_OZONE) 24#include "ui/ozone/ozone_platform.h" 25#include "ui/ozone/public/gpu_platform_support_host.h" 26#endif 27 28namespace content { 29 30namespace { 31 32// One of the linux specific headers defines this as a macro. 33#ifdef DestroyAll 34#undef DestroyAll 35#endif 36 37base::LazyInstance<IDMap<GpuProcessHostUIShim> > g_hosts_by_id = 38 LAZY_INSTANCE_INITIALIZER; 39 40void SendOnIOThreadTask(int host_id, IPC::Message* msg) { 41 GpuProcessHost* host = GpuProcessHost::FromID(host_id); 42 if (host) 43 host->Send(msg); 44 else 45 delete msg; 46} 47 48class ScopedSendOnIOThread { 49 public: 50 ScopedSendOnIOThread(int host_id, IPC::Message* msg) 51 : host_id_(host_id), 52 msg_(msg), 53 cancelled_(false) { 54 } 55 56 ~ScopedSendOnIOThread() { 57 if (!cancelled_) { 58 BrowserThread::PostTask(BrowserThread::IO, 59 FROM_HERE, 60 base::Bind(&SendOnIOThreadTask, 61 host_id_, 62 msg_.release())); 63 } 64 } 65 66 void Cancel() { cancelled_ = true; } 67 68 private: 69 int host_id_; 70 scoped_ptr<IPC::Message> msg_; 71 bool cancelled_; 72}; 73 74RenderWidgetHostViewBase* GetRenderWidgetHostViewFromSurfaceID( 75 int surface_id) { 76 int render_process_id = 0; 77 int render_widget_id = 0; 78 if (!GpuSurfaceTracker::Get()->GetRenderWidgetIDForSurface( 79 surface_id, &render_process_id, &render_widget_id)) 80 return NULL; 81 82 RenderWidgetHost* host = 83 RenderWidgetHost::FromID(render_process_id, render_widget_id); 84 return host ? static_cast<RenderWidgetHostViewBase*>(host->GetView()) : NULL; 85} 86 87} // namespace 88 89void RouteToGpuProcessHostUIShimTask(int host_id, const IPC::Message& msg) { 90 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(host_id); 91 if (ui_shim) 92 ui_shim->OnMessageReceived(msg); 93} 94 95GpuProcessHostUIShim::GpuProcessHostUIShim(int host_id) 96 : host_id_(host_id) { 97 g_hosts_by_id.Pointer()->AddWithID(this, host_id_); 98#if defined(USE_OZONE) 99 ui::OzonePlatform::GetInstance() 100 ->GetGpuPlatformSupportHost() 101 ->OnChannelEstablished(host_id, this); 102#endif 103} 104 105// static 106GpuProcessHostUIShim* GpuProcessHostUIShim::Create(int host_id) { 107 DCHECK(!FromID(host_id)); 108 return new GpuProcessHostUIShim(host_id); 109} 110 111// static 112void GpuProcessHostUIShim::Destroy(int host_id, const std::string& message) { 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 114 115 GpuDataManagerImpl::GetInstance()->AddLogMessage( 116 logging::LOG_ERROR, "GpuProcessHostUIShim", 117 message); 118 119#if defined(USE_OZONE) 120 ui::OzonePlatform::GetInstance() 121 ->GetGpuPlatformSupportHost() 122 ->OnChannelDestroyed(host_id); 123#endif 124 125 delete FromID(host_id); 126} 127 128// static 129void GpuProcessHostUIShim::DestroyAll() { 130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 131 while (!g_hosts_by_id.Pointer()->IsEmpty()) { 132 IDMap<GpuProcessHostUIShim>::iterator it(g_hosts_by_id.Pointer()); 133 delete it.GetCurrentValue(); 134 } 135} 136 137// static 138GpuProcessHostUIShim* GpuProcessHostUIShim::FromID(int host_id) { 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 140 return g_hosts_by_id.Pointer()->Lookup(host_id); 141} 142 143// static 144GpuProcessHostUIShim* GpuProcessHostUIShim::GetOneInstance() { 145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 146 if (g_hosts_by_id.Pointer()->IsEmpty()) 147 return NULL; 148 IDMap<GpuProcessHostUIShim>::iterator it(g_hosts_by_id.Pointer()); 149 return it.GetCurrentValue(); 150} 151 152bool GpuProcessHostUIShim::Send(IPC::Message* msg) { 153 DCHECK(CalledOnValidThread()); 154 return BrowserThread::PostTask(BrowserThread::IO, 155 FROM_HERE, 156 base::Bind(&SendOnIOThreadTask, 157 host_id_, 158 msg)); 159} 160 161bool GpuProcessHostUIShim::OnMessageReceived(const IPC::Message& message) { 162 DCHECK(CalledOnValidThread()); 163 164#if defined(USE_OZONE) 165 if (ui::OzonePlatform::GetInstance() 166 ->GetGpuPlatformSupportHost() 167 ->OnMessageReceived(message)) 168 return true; 169#endif 170 171 if (message.routing_id() != MSG_ROUTING_CONTROL) 172 return false; 173 174 return OnControlMessageReceived(message); 175} 176 177void GpuProcessHostUIShim::SimulateRemoveAllContext() { 178 Send(new GpuMsg_Clean()); 179} 180 181void GpuProcessHostUIShim::SimulateCrash() { 182 Send(new GpuMsg_Crash()); 183} 184 185void GpuProcessHostUIShim::SimulateHang() { 186 Send(new GpuMsg_Hang()); 187} 188 189GpuProcessHostUIShim::~GpuProcessHostUIShim() { 190 DCHECK(CalledOnValidThread()); 191 g_hosts_by_id.Pointer()->Remove(host_id_); 192} 193 194bool GpuProcessHostUIShim::OnControlMessageReceived( 195 const IPC::Message& message) { 196 DCHECK(CalledOnValidThread()); 197 198 IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim, message) 199 IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage, 200 OnLogMessage) 201 202 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceInitialized, 203 OnAcceleratedSurfaceInitialized) 204 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped, 205 OnAcceleratedSurfaceBuffersSwapped) 206 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfacePostSubBuffer, 207 OnAcceleratedSurfacePostSubBuffer) 208 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceSuspend, 209 OnAcceleratedSurfaceSuspend) 210 IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected, 211 OnGraphicsInfoCollected) 212 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceRelease, 213 OnAcceleratedSurfaceRelease) 214 IPC_MESSAGE_HANDLER(GpuHostMsg_VideoMemoryUsageStats, 215 OnVideoMemoryUsageStatsReceived); 216 IPC_MESSAGE_HANDLER(GpuHostMsg_UpdateVSyncParameters, 217 OnUpdateVSyncParameters) 218 IPC_MESSAGE_HANDLER(GpuHostMsg_FrameDrawn, OnFrameDrawn) 219 220 IPC_MESSAGE_UNHANDLED_ERROR() 221 IPC_END_MESSAGE_MAP() 222 223 return true; 224} 225 226void GpuProcessHostUIShim::OnUpdateVSyncParameters(int surface_id, 227 base::TimeTicks timebase, 228 base::TimeDelta interval) { 229 230 int render_process_id = 0; 231 int render_widget_id = 0; 232 if (!GpuSurfaceTracker::Get()->GetRenderWidgetIDForSurface( 233 surface_id, &render_process_id, &render_widget_id)) { 234 return; 235 } 236 RenderWidgetHost* rwh = 237 RenderWidgetHost::FromID(render_process_id, render_widget_id); 238 if (!rwh) 239 return; 240 RenderWidgetHostImpl::From(rwh)->UpdateVSyncParameters(timebase, interval); 241} 242 243void GpuProcessHostUIShim::OnLogMessage( 244 int level, 245 const std::string& header, 246 const std::string& message) { 247 GpuDataManagerImpl::GetInstance()->AddLogMessage( 248 level, header, message); 249} 250 251void GpuProcessHostUIShim::OnGraphicsInfoCollected( 252 const gpu::GPUInfo& gpu_info) { 253 // OnGraphicsInfoCollected is sent back after the GPU process successfully 254 // initializes GL. 255 TRACE_EVENT0("test_gpu", "OnGraphicsInfoCollected"); 256 257 GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info); 258} 259 260void GpuProcessHostUIShim::OnAcceleratedSurfaceInitialized(int32 surface_id, 261 int32 route_id) { 262 RenderWidgetHostViewBase* view = 263 GetRenderWidgetHostViewFromSurfaceID(surface_id); 264 if (!view) 265 return; 266 view->AcceleratedSurfaceInitialized(host_id_, route_id); 267} 268 269void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped( 270 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) { 271 TRACE_EVENT0("renderer", 272 "GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped"); 273 if (!ui::LatencyInfo::Verify(params.latency_info, 274 "GpuHostMsg_AcceleratedSurfaceBuffersSwapped")) 275 return; 276 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; 277 ack_params.mailbox = params.mailbox; 278 ack_params.sync_point = 0; 279 ScopedSendOnIOThread delayed_send( 280 host_id_, 281 new AcceleratedSurfaceMsg_BufferPresented(params.route_id, 282 ack_params)); 283 284 RenderWidgetHostViewBase* view = GetRenderWidgetHostViewFromSurfaceID( 285 params.surface_id); 286 if (!view) 287 return; 288 289 delayed_send.Cancel(); 290 291 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params view_params = params; 292 293 RenderWidgetHostImpl* impl = 294 RenderWidgetHostImpl::From(view->GetRenderWidgetHost()); 295 for (size_t i = 0; i < view_params.latency_info.size(); i++) 296 impl->AddLatencyInfoComponentIds(&view_params.latency_info[i]); 297 298 // View must send ACK message after next composite. 299 view->AcceleratedSurfaceBuffersSwapped(view_params, host_id_); 300 view->DidReceiveRendererFrame(); 301} 302 303void GpuProcessHostUIShim::OnFrameDrawn( 304 const std::vector<ui::LatencyInfo>& latency_info) { 305 if (!ui::LatencyInfo::Verify(latency_info, 306 "GpuProcessHostUIShim::OnFrameDrawn")) 307 return; 308 RenderWidgetHostImpl::CompositorFrameDrawn(latency_info); 309} 310 311void GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer( 312 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params) { 313 TRACE_EVENT0("renderer", 314 "GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer"); 315 if (!ui::LatencyInfo::Verify(params.latency_info, 316 "GpuHostMsg_AcceleratedSurfacePostSubBuffer")) 317 return; 318 AcceleratedSurfaceMsg_BufferPresented_Params ack_params; 319 ack_params.mailbox = params.mailbox; 320 ack_params.sync_point = 0; 321 ScopedSendOnIOThread delayed_send( 322 host_id_, 323 new AcceleratedSurfaceMsg_BufferPresented(params.route_id, 324 ack_params)); 325 326 RenderWidgetHostViewBase* view = 327 GetRenderWidgetHostViewFromSurfaceID(params.surface_id); 328 if (!view) 329 return; 330 331 delayed_send.Cancel(); 332 333 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params view_params = params; 334 335 RenderWidgetHostImpl* impl = 336 RenderWidgetHostImpl::From(view->GetRenderWidgetHost()); 337 for (size_t i = 0; i < view_params.latency_info.size(); i++) 338 impl->AddLatencyInfoComponentIds(&view_params.latency_info[i]); 339 340 // View must send ACK message after next composite. 341 view->AcceleratedSurfacePostSubBuffer(view_params, host_id_); 342 view->DidReceiveRendererFrame(); 343} 344 345void GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend(int32 surface_id) { 346 TRACE_EVENT0("renderer", 347 "GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend"); 348 349 RenderWidgetHostViewBase* view = 350 GetRenderWidgetHostViewFromSurfaceID(surface_id); 351 if (!view) 352 return; 353 354 view->AcceleratedSurfaceSuspend(); 355} 356 357void GpuProcessHostUIShim::OnAcceleratedSurfaceRelease( 358 const GpuHostMsg_AcceleratedSurfaceRelease_Params& params) { 359 RenderWidgetHostViewBase* view = GetRenderWidgetHostViewFromSurfaceID( 360 params.surface_id); 361 if (!view) 362 return; 363 view->AcceleratedSurfaceRelease(); 364} 365 366void GpuProcessHostUIShim::OnVideoMemoryUsageStatsReceived( 367 const GPUVideoMemoryUsageStats& video_memory_usage_stats) { 368 GpuDataManagerImpl::GetInstance()->UpdateVideoMemoryUsageStats( 369 video_memory_usage_stats); 370} 371 372} // namespace content 373