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
28 namespace content {
29
30 namespace {
31
32 // One of the linux specific headers defines this as a macro.
33 #ifdef DestroyAll
34 #undef DestroyAll
35 #endif
36
37 base::LazyInstance<IDMap<GpuProcessHostUIShim> > g_hosts_by_id =
38 LAZY_INSTANCE_INITIALIZER;
39
SendOnIOThreadTask(int host_id,IPC::Message * msg)40 void 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
48 class ScopedSendOnIOThread {
49 public:
ScopedSendOnIOThread(int host_id,IPC::Message * msg)50 ScopedSendOnIOThread(int host_id, IPC::Message* msg)
51 : host_id_(host_id),
52 msg_(msg),
53 cancelled_(false) {
54 }
55
~ScopedSendOnIOThread()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
Cancel()66 void Cancel() { cancelled_ = true; }
67
68 private:
69 int host_id_;
70 scoped_ptr<IPC::Message> msg_;
71 bool cancelled_;
72 };
73
GetRenderWidgetHostViewFromSurfaceID(int surface_id)74 RenderWidgetHostViewBase* 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
RouteToGpuProcessHostUIShimTask(int host_id,const IPC::Message & msg)89 void 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
GpuProcessHostUIShim(int host_id)95 GpuProcessHostUIShim::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
Create(int host_id)106 GpuProcessHostUIShim* GpuProcessHostUIShim::Create(int host_id) {
107 DCHECK(!FromID(host_id));
108 return new GpuProcessHostUIShim(host_id);
109 }
110
111 // static
Destroy(int host_id,const std::string & message)112 void 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
DestroyAll()129 void 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
FromID(int host_id)138 GpuProcessHostUIShim* 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
GetOneInstance()144 GpuProcessHostUIShim* 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
Send(IPC::Message * msg)152 bool 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
OnMessageReceived(const IPC::Message & message)161 bool 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
SimulateRemoveAllContext()177 void GpuProcessHostUIShim::SimulateRemoveAllContext() {
178 Send(new GpuMsg_Clean());
179 }
180
SimulateCrash()181 void GpuProcessHostUIShim::SimulateCrash() {
182 Send(new GpuMsg_Crash());
183 }
184
SimulateHang()185 void GpuProcessHostUIShim::SimulateHang() {
186 Send(new GpuMsg_Hang());
187 }
188
~GpuProcessHostUIShim()189 GpuProcessHostUIShim::~GpuProcessHostUIShim() {
190 DCHECK(CalledOnValidThread());
191 g_hosts_by_id.Pointer()->Remove(host_id_);
192 }
193
OnControlMessageReceived(const IPC::Message & message)194 bool 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
OnUpdateVSyncParameters(int surface_id,base::TimeTicks timebase,base::TimeDelta interval)226 void 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
OnLogMessage(int level,const std::string & header,const std::string & message)243 void 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
OnGraphicsInfoCollected(const gpu::GPUInfo & gpu_info)251 void 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
OnAcceleratedSurfaceInitialized(int32 surface_id,int32 route_id)260 void 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
OnAcceleratedSurfaceBuffersSwapped(const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params & params)269 void 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
OnFrameDrawn(const std::vector<ui::LatencyInfo> & latency_info)303 void 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
OnAcceleratedSurfacePostSubBuffer(const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params & params)311 void 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
OnAcceleratedSurfaceSuspend(int32 surface_id)345 void 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
OnAcceleratedSurfaceRelease(const GpuHostMsg_AcceleratedSurfaceRelease_Params & params)357 void 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
OnVideoMemoryUsageStatsReceived(const GPUVideoMemoryUsageStats & video_memory_usage_stats)366 void GpuProcessHostUIShim::OnVideoMemoryUsageStatsReceived(
367 const GPUVideoMemoryUsageStats& video_memory_usage_stats) {
368 GpuDataManagerImpl::GetInstance()->UpdateVideoMemoryUsageStats(
369 video_memory_usage_stats);
370 }
371
372 } // namespace content
373