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.
5 #include "content/browser/gpu/gpu_process_host_ui_shim.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/compositor_util.h"
15 #include "content/browser/gpu/gpu_data_manager_impl.h"
16 #include "content/browser/gpu/gpu_process_host.h"
17 #include "content/browser/gpu/gpu_surface_tracker.h"
18 #include "content/browser/renderer_host/render_process_host_impl.h"
19 #include "content/browser/renderer_host/render_view_host_impl.h"
20 #include "content/browser/renderer_host/render_widget_helper.h"
21 #include "content/browser/renderer_host/render_widget_host_view_base.h"
22 #include "content/common/gpu/gpu_messages.h"
23 #include "content/public/browser/browser_thread.h"
25 #if defined(OS_MACOSX)
26 #include "content/browser/compositor/browser_compositor_view_mac.h"
29 #if defined(USE_OZONE)
30 #include "ui/ozone/public/gpu_platform_support_host.h"
31 #include "ui/ozone/public/ozone_platform.h"
38 // One of the linux specific headers defines this as a macro.
43 base::LazyInstance
<IDMap
<GpuProcessHostUIShim
> > g_hosts_by_id
=
44 LAZY_INSTANCE_INITIALIZER
;
46 void SendOnIOThreadTask(int host_id
, IPC::Message
* msg
) {
47 GpuProcessHost
* host
= GpuProcessHost::FromID(host_id
);
54 class ScopedSendOnIOThread
{
56 ScopedSendOnIOThread(int host_id
, IPC::Message
* msg
)
62 ~ScopedSendOnIOThread() {
64 BrowserThread::PostTask(BrowserThread::IO
,
66 base::Bind(&SendOnIOThreadTask
,
72 void Cancel() { cancelled_
= true; }
76 scoped_ptr
<IPC::Message
> msg_
;
80 RenderWidgetHostViewBase
* GetRenderWidgetHostViewFromSurfaceID(
82 int render_process_id
= 0;
83 int render_widget_id
= 0;
84 if (!GpuSurfaceTracker::Get()->GetRenderWidgetIDForSurface(
85 surface_id
, &render_process_id
, &render_widget_id
))
88 RenderWidgetHost
* host
=
89 RenderWidgetHost::FromID(render_process_id
, render_widget_id
);
90 return host
? static_cast<RenderWidgetHostViewBase
*>(host
->GetView()) : NULL
;
95 void RouteToGpuProcessHostUIShimTask(int host_id
, const IPC::Message
& msg
) {
96 GpuProcessHostUIShim
* ui_shim
= GpuProcessHostUIShim::FromID(host_id
);
98 ui_shim
->OnMessageReceived(msg
);
101 GpuProcessHostUIShim::GpuProcessHostUIShim(int host_id
)
102 : host_id_(host_id
) {
103 g_hosts_by_id
.Pointer()->AddWithID(this, host_id_
);
104 #if defined(USE_OZONE)
105 ui::OzonePlatform::GetInstance()
106 ->GetGpuPlatformSupportHost()
107 ->OnChannelEstablished(host_id
, this);
112 GpuProcessHostUIShim
* GpuProcessHostUIShim::Create(int host_id
) {
113 DCHECK(!FromID(host_id
));
114 return new GpuProcessHostUIShim(host_id
);
118 void GpuProcessHostUIShim::Destroy(int host_id
, const std::string
& message
) {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
121 GpuDataManagerImpl::GetInstance()->AddLogMessage(
122 logging::LOG_ERROR
, "GpuProcessHostUIShim",
125 #if defined(USE_OZONE)
126 ui::OzonePlatform::GetInstance()
127 ->GetGpuPlatformSupportHost()
128 ->OnChannelDestroyed(host_id
);
131 delete FromID(host_id
);
135 void GpuProcessHostUIShim::DestroyAll() {
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
137 while (!g_hosts_by_id
.Pointer()->IsEmpty()) {
138 IDMap
<GpuProcessHostUIShim
>::iterator
it(g_hosts_by_id
.Pointer());
139 delete it
.GetCurrentValue();
144 GpuProcessHostUIShim
* GpuProcessHostUIShim::FromID(int host_id
) {
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
146 return g_hosts_by_id
.Pointer()->Lookup(host_id
);
150 GpuProcessHostUIShim
* GpuProcessHostUIShim::GetOneInstance() {
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
152 if (g_hosts_by_id
.Pointer()->IsEmpty())
154 IDMap
<GpuProcessHostUIShim
>::iterator
it(g_hosts_by_id
.Pointer());
155 return it
.GetCurrentValue();
158 bool GpuProcessHostUIShim::Send(IPC::Message
* msg
) {
159 DCHECK(CalledOnValidThread());
160 return BrowserThread::PostTask(BrowserThread::IO
,
162 base::Bind(&SendOnIOThreadTask
,
167 bool GpuProcessHostUIShim::OnMessageReceived(const IPC::Message
& message
) {
168 DCHECK(CalledOnValidThread());
170 #if defined(USE_OZONE)
171 if (ui::OzonePlatform::GetInstance()
172 ->GetGpuPlatformSupportHost()
173 ->OnMessageReceived(message
))
177 if (message
.routing_id() != MSG_ROUTING_CONTROL
)
180 return OnControlMessageReceived(message
);
183 void GpuProcessHostUIShim::SimulateRemoveAllContext() {
184 Send(new GpuMsg_Clean());
187 void GpuProcessHostUIShim::SimulateCrash() {
188 Send(new GpuMsg_Crash());
191 void GpuProcessHostUIShim::SimulateHang() {
192 Send(new GpuMsg_Hang());
195 GpuProcessHostUIShim::~GpuProcessHostUIShim() {
196 DCHECK(CalledOnValidThread());
197 g_hosts_by_id
.Pointer()->Remove(host_id_
);
200 bool GpuProcessHostUIShim::OnControlMessageReceived(
201 const IPC::Message
& message
) {
202 DCHECK(CalledOnValidThread());
204 IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim
, message
)
205 IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage
,
208 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceInitialized
,
209 OnAcceleratedSurfaceInitialized
)
210 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped
,
211 OnAcceleratedSurfaceBuffersSwapped
)
212 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfacePostSubBuffer
,
213 OnAcceleratedSurfacePostSubBuffer
)
214 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceSuspend
,
215 OnAcceleratedSurfaceSuspend
)
216 IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected
,
217 OnGraphicsInfoCollected
)
218 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceRelease
,
219 OnAcceleratedSurfaceRelease
)
220 IPC_MESSAGE_HANDLER(GpuHostMsg_VideoMemoryUsageStats
,
221 OnVideoMemoryUsageStatsReceived
);
222 IPC_MESSAGE_HANDLER(GpuHostMsg_FrameDrawn
, OnFrameDrawn
)
224 IPC_MESSAGE_UNHANDLED_ERROR()
225 IPC_END_MESSAGE_MAP()
230 void GpuProcessHostUIShim::OnLogMessage(
232 const std::string
& header
,
233 const std::string
& message
) {
234 GpuDataManagerImpl::GetInstance()->AddLogMessage(
235 level
, header
, message
);
238 void GpuProcessHostUIShim::OnGraphicsInfoCollected(
239 const gpu::GPUInfo
& gpu_info
) {
240 // OnGraphicsInfoCollected is sent back after the GPU process successfully
242 TRACE_EVENT0("test_gpu", "OnGraphicsInfoCollected");
244 GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info
);
247 void GpuProcessHostUIShim::OnAcceleratedSurfaceInitialized(int32 surface_id
,
249 RenderWidgetHostViewBase
* view
=
250 GetRenderWidgetHostViewFromSurfaceID(surface_id
);
253 view
->AcceleratedSurfaceInitialized(host_id_
, route_id
);
256 void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped(
257 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params
& params
) {
258 TRACE_EVENT0("renderer",
259 "GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped");
260 if (!ui::LatencyInfo::Verify(params
.latency_info
,
261 "GpuHostMsg_AcceleratedSurfaceBuffersSwapped"))
264 #if defined(OS_MACOSX)
265 // On Mac with delegated rendering, accelerated surfaces are not necessarily
266 // associated with a RenderWidgetHostViewBase.
267 if (IsDelegatedRendererEnabled()) {
268 gfx::AcceleratedWidget native_widget
=
269 content::GpuSurfaceTracker::Get()->AcquireNativeWidget(
271 BrowserCompositorViewMac::GotAcceleratedFrame(
272 native_widget
, params
.surface_handle
, params
.surface_id
,
273 params
.latency_info
, params
.size
, params
.scale_factor
,
274 host_id_
, params
.route_id
);
279 AcceleratedSurfaceMsg_BufferPresented_Params ack_params
;
280 ack_params
.mailbox
= params
.mailbox
;
281 ack_params
.sync_point
= 0;
282 ScopedSendOnIOThread
delayed_send(
284 new AcceleratedSurfaceMsg_BufferPresented(params
.route_id
,
287 RenderWidgetHostViewBase
* view
= GetRenderWidgetHostViewFromSurfaceID(
292 delayed_send
.Cancel();
294 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params view_params
= params
;
296 RenderWidgetHostImpl
* impl
=
297 RenderWidgetHostImpl::From(view
->GetRenderWidgetHost());
298 for (size_t i
= 0; i
< view_params
.latency_info
.size(); i
++)
299 impl
->AddLatencyInfoComponentIds(&view_params
.latency_info
[i
]);
301 // View must send ACK message after next composite.
302 view
->AcceleratedSurfaceBuffersSwapped(view_params
, host_id_
);
303 view
->DidReceiveRendererFrame();
306 void GpuProcessHostUIShim::OnFrameDrawn(
307 const std::vector
<ui::LatencyInfo
>& latency_info
) {
308 if (!ui::LatencyInfo::Verify(latency_info
,
309 "GpuProcessHostUIShim::OnFrameDrawn"))
311 RenderWidgetHostImpl::CompositorFrameDrawn(latency_info
);
314 void GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer(
315 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params
& params
) {
316 TRACE_EVENT0("renderer",
317 "GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer");
318 if (!ui::LatencyInfo::Verify(params
.latency_info
,
319 "GpuHostMsg_AcceleratedSurfacePostSubBuffer"))
321 AcceleratedSurfaceMsg_BufferPresented_Params ack_params
;
322 ack_params
.mailbox
= params
.mailbox
;
323 ack_params
.sync_point
= 0;
324 ScopedSendOnIOThread
delayed_send(
326 new AcceleratedSurfaceMsg_BufferPresented(params
.route_id
,
329 RenderWidgetHostViewBase
* view
=
330 GetRenderWidgetHostViewFromSurfaceID(params
.surface_id
);
334 delayed_send
.Cancel();
336 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params view_params
= params
;
338 RenderWidgetHostImpl
* impl
=
339 RenderWidgetHostImpl::From(view
->GetRenderWidgetHost());
340 for (size_t i
= 0; i
< view_params
.latency_info
.size(); i
++)
341 impl
->AddLatencyInfoComponentIds(&view_params
.latency_info
[i
]);
343 // View must send ACK message after next composite.
344 view
->AcceleratedSurfacePostSubBuffer(view_params
, host_id_
);
345 view
->DidReceiveRendererFrame();
348 void GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend(int32 surface_id
) {
349 TRACE_EVENT0("renderer",
350 "GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend");
352 RenderWidgetHostViewBase
* view
=
353 GetRenderWidgetHostViewFromSurfaceID(surface_id
);
357 view
->AcceleratedSurfaceSuspend();
360 void GpuProcessHostUIShim::OnAcceleratedSurfaceRelease(
361 const GpuHostMsg_AcceleratedSurfaceRelease_Params
& params
) {
362 RenderWidgetHostViewBase
* view
= GetRenderWidgetHostViewFromSurfaceID(
366 view
->AcceleratedSurfaceRelease();
369 void GpuProcessHostUIShim::OnVideoMemoryUsageStatsReceived(
370 const GPUVideoMemoryUsageStats
& video_memory_usage_stats
) {
371 GpuDataManagerImpl::GetInstance()->UpdateVideoMemoryUsageStats(
372 video_memory_usage_stats
);
375 } // namespace content