• 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/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"
24 
25 #if defined(OS_MACOSX)
26 #include "content/browser/compositor/browser_compositor_view_mac.h"
27 #endif
28 
29 #if defined(USE_OZONE)
30 #include "ui/ozone/public/gpu_platform_support_host.h"
31 #include "ui/ozone/public/ozone_platform.h"
32 #endif
33 
34 namespace content {
35 
36 namespace {
37 
38 // One of the linux specific headers defines this as a macro.
39 #ifdef DestroyAll
40 #undef DestroyAll
41 #endif
42 
43 base::LazyInstance<IDMap<GpuProcessHostUIShim> > g_hosts_by_id =
44     LAZY_INSTANCE_INITIALIZER;
45 
SendOnIOThreadTask(int host_id,IPC::Message * msg)46 void SendOnIOThreadTask(int host_id, IPC::Message* msg) {
47   GpuProcessHost* host = GpuProcessHost::FromID(host_id);
48   if (host)
49     host->Send(msg);
50   else
51     delete msg;
52 }
53 
54 class ScopedSendOnIOThread {
55  public:
ScopedSendOnIOThread(int host_id,IPC::Message * msg)56   ScopedSendOnIOThread(int host_id, IPC::Message* msg)
57       : host_id_(host_id),
58         msg_(msg),
59         cancelled_(false) {
60   }
61 
~ScopedSendOnIOThread()62   ~ScopedSendOnIOThread() {
63     if (!cancelled_) {
64       BrowserThread::PostTask(BrowserThread::IO,
65                               FROM_HERE,
66                               base::Bind(&SendOnIOThreadTask,
67                                          host_id_,
68                                          msg_.release()));
69     }
70   }
71 
Cancel()72   void Cancel() { cancelled_ = true; }
73 
74  private:
75   int host_id_;
76   scoped_ptr<IPC::Message> msg_;
77   bool cancelled_;
78 };
79 
GetRenderWidgetHostViewFromSurfaceID(int surface_id)80 RenderWidgetHostViewBase* GetRenderWidgetHostViewFromSurfaceID(
81     int surface_id) {
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))
86     return NULL;
87 
88   RenderWidgetHost* host =
89       RenderWidgetHost::FromID(render_process_id, render_widget_id);
90   return host ? static_cast<RenderWidgetHostViewBase*>(host->GetView()) : NULL;
91 }
92 
93 }  // namespace
94 
RouteToGpuProcessHostUIShimTask(int host_id,const IPC::Message & msg)95 void RouteToGpuProcessHostUIShimTask(int host_id, const IPC::Message& msg) {
96   GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(host_id);
97   if (ui_shim)
98     ui_shim->OnMessageReceived(msg);
99 }
100 
GpuProcessHostUIShim(int host_id)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);
108 #endif
109 }
110 
111 // static
Create(int host_id)112 GpuProcessHostUIShim* GpuProcessHostUIShim::Create(int host_id) {
113   DCHECK(!FromID(host_id));
114   return new GpuProcessHostUIShim(host_id);
115 }
116 
117 // static
Destroy(int host_id,const std::string & message)118 void GpuProcessHostUIShim::Destroy(int host_id, const std::string& message) {
119   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
120 
121   GpuDataManagerImpl::GetInstance()->AddLogMessage(
122       logging::LOG_ERROR, "GpuProcessHostUIShim",
123       message);
124 
125 #if defined(USE_OZONE)
126   ui::OzonePlatform::GetInstance()
127       ->GetGpuPlatformSupportHost()
128       ->OnChannelDestroyed(host_id);
129 #endif
130 
131   delete FromID(host_id);
132 }
133 
134 // static
DestroyAll()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();
140   }
141 }
142 
143 // static
FromID(int host_id)144 GpuProcessHostUIShim* GpuProcessHostUIShim::FromID(int host_id) {
145   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
146   return g_hosts_by_id.Pointer()->Lookup(host_id);
147 }
148 
149 // static
GetOneInstance()150 GpuProcessHostUIShim* GpuProcessHostUIShim::GetOneInstance() {
151   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
152   if (g_hosts_by_id.Pointer()->IsEmpty())
153     return NULL;
154   IDMap<GpuProcessHostUIShim>::iterator it(g_hosts_by_id.Pointer());
155   return it.GetCurrentValue();
156 }
157 
Send(IPC::Message * msg)158 bool GpuProcessHostUIShim::Send(IPC::Message* msg) {
159   DCHECK(CalledOnValidThread());
160   return BrowserThread::PostTask(BrowserThread::IO,
161                                  FROM_HERE,
162                                  base::Bind(&SendOnIOThreadTask,
163                                             host_id_,
164                                             msg));
165 }
166 
OnMessageReceived(const IPC::Message & message)167 bool GpuProcessHostUIShim::OnMessageReceived(const IPC::Message& message) {
168   DCHECK(CalledOnValidThread());
169 
170 #if defined(USE_OZONE)
171   if (ui::OzonePlatform::GetInstance()
172           ->GetGpuPlatformSupportHost()
173           ->OnMessageReceived(message))
174     return true;
175 #endif
176 
177   if (message.routing_id() != MSG_ROUTING_CONTROL)
178     return false;
179 
180   return OnControlMessageReceived(message);
181 }
182 
SimulateRemoveAllContext()183 void GpuProcessHostUIShim::SimulateRemoveAllContext() {
184   Send(new GpuMsg_Clean());
185 }
186 
SimulateCrash()187 void GpuProcessHostUIShim::SimulateCrash() {
188   Send(new GpuMsg_Crash());
189 }
190 
SimulateHang()191 void GpuProcessHostUIShim::SimulateHang() {
192   Send(new GpuMsg_Hang());
193 }
194 
~GpuProcessHostUIShim()195 GpuProcessHostUIShim::~GpuProcessHostUIShim() {
196   DCHECK(CalledOnValidThread());
197   g_hosts_by_id.Pointer()->Remove(host_id_);
198 }
199 
OnControlMessageReceived(const IPC::Message & message)200 bool GpuProcessHostUIShim::OnControlMessageReceived(
201     const IPC::Message& message) {
202   DCHECK(CalledOnValidThread());
203 
204   IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim, message)
205     IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage,
206                         OnLogMessage)
207 
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)
223 
224     IPC_MESSAGE_UNHANDLED_ERROR()
225   IPC_END_MESSAGE_MAP()
226 
227   return true;
228 }
229 
OnLogMessage(int level,const std::string & header,const std::string & message)230 void GpuProcessHostUIShim::OnLogMessage(
231     int level,
232     const std::string& header,
233     const std::string& message) {
234   GpuDataManagerImpl::GetInstance()->AddLogMessage(
235       level, header, message);
236 }
237 
OnGraphicsInfoCollected(const gpu::GPUInfo & gpu_info)238 void GpuProcessHostUIShim::OnGraphicsInfoCollected(
239     const gpu::GPUInfo& gpu_info) {
240   // OnGraphicsInfoCollected is sent back after the GPU process successfully
241   // initializes GL.
242   TRACE_EVENT0("test_gpu", "OnGraphicsInfoCollected");
243 
244   GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info);
245 }
246 
OnAcceleratedSurfaceInitialized(int32 surface_id,int32 route_id)247 void GpuProcessHostUIShim::OnAcceleratedSurfaceInitialized(int32 surface_id,
248                                                            int32 route_id) {
249   RenderWidgetHostViewBase* view =
250       GetRenderWidgetHostViewFromSurfaceID(surface_id);
251   if (!view)
252     return;
253   view->AcceleratedSurfaceInitialized(host_id_, route_id);
254 }
255 
OnAcceleratedSurfaceBuffersSwapped(const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params & params)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"))
262     return;
263 
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(
270             params.surface_id);
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);
275     return;
276   }
277 #endif
278 
279   AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
280   ack_params.mailbox = params.mailbox;
281   ack_params.sync_point = 0;
282   ScopedSendOnIOThread delayed_send(
283       host_id_,
284       new AcceleratedSurfaceMsg_BufferPresented(params.route_id,
285                                                 ack_params));
286 
287   RenderWidgetHostViewBase* view = GetRenderWidgetHostViewFromSurfaceID(
288       params.surface_id);
289   if (!view)
290     return;
291 
292   delayed_send.Cancel();
293 
294   GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params view_params = params;
295 
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]);
300 
301   // View must send ACK message after next composite.
302   view->AcceleratedSurfaceBuffersSwapped(view_params, host_id_);
303   view->DidReceiveRendererFrame();
304 }
305 
OnFrameDrawn(const std::vector<ui::LatencyInfo> & latency_info)306 void GpuProcessHostUIShim::OnFrameDrawn(
307     const std::vector<ui::LatencyInfo>& latency_info) {
308   if (!ui::LatencyInfo::Verify(latency_info,
309                                "GpuProcessHostUIShim::OnFrameDrawn"))
310     return;
311   RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
312 }
313 
OnAcceleratedSurfacePostSubBuffer(const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params & params)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"))
320     return;
321   AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
322   ack_params.mailbox = params.mailbox;
323   ack_params.sync_point = 0;
324   ScopedSendOnIOThread delayed_send(
325       host_id_,
326       new AcceleratedSurfaceMsg_BufferPresented(params.route_id,
327                                                 ack_params));
328 
329   RenderWidgetHostViewBase* view =
330       GetRenderWidgetHostViewFromSurfaceID(params.surface_id);
331   if (!view)
332     return;
333 
334   delayed_send.Cancel();
335 
336   GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params view_params = params;
337 
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]);
342 
343   // View must send ACK message after next composite.
344   view->AcceleratedSurfacePostSubBuffer(view_params, host_id_);
345   view->DidReceiveRendererFrame();
346 }
347 
OnAcceleratedSurfaceSuspend(int32 surface_id)348 void GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend(int32 surface_id) {
349   TRACE_EVENT0("renderer",
350       "GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend");
351 
352   RenderWidgetHostViewBase* view =
353       GetRenderWidgetHostViewFromSurfaceID(surface_id);
354   if (!view)
355     return;
356 
357   view->AcceleratedSurfaceSuspend();
358 }
359 
OnAcceleratedSurfaceRelease(const GpuHostMsg_AcceleratedSurfaceRelease_Params & params)360 void GpuProcessHostUIShim::OnAcceleratedSurfaceRelease(
361     const GpuHostMsg_AcceleratedSurfaceRelease_Params& params) {
362   RenderWidgetHostViewBase* view = GetRenderWidgetHostViewFromSurfaceID(
363       params.surface_id);
364   if (!view)
365     return;
366   view->AcceleratedSurfaceRelease();
367 }
368 
OnVideoMemoryUsageStatsReceived(const GPUVideoMemoryUsageStats & video_memory_usage_stats)369 void GpuProcessHostUIShim::OnVideoMemoryUsageStatsReceived(
370     const GPUVideoMemoryUsageStats& video_memory_usage_stats) {
371   GpuDataManagerImpl::GetInstance()->UpdateVideoMemoryUsageStats(
372       video_memory_usage_stats);
373 }
374 
375 }  // namespace content
376