• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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