Home | History | Annotate | Download | only in gpu
      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 
     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:
     56   ScopedSendOnIOThread(int host_id, IPC::Message* msg)
     57       : host_id_(host_id),
     58         msg_(msg),
     59         cancelled_(false) {
     60   }
     61 
     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 
     72   void Cancel() { cancelled_ = true; }
     73 
     74  private:
     75   int host_id_;
     76   scoped_ptr<IPC::Message> msg_;
     77   bool cancelled_;
     78 };
     79 
     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 
     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 
    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
    112 GpuProcessHostUIShim* GpuProcessHostUIShim::Create(int host_id) {
    113   DCHECK(!FromID(host_id));
    114   return new GpuProcessHostUIShim(host_id);
    115 }
    116 
    117 // static
    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
    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
    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
    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 
    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 
    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 
    183 void GpuProcessHostUIShim::SimulateRemoveAllContext() {
    184   Send(new GpuMsg_Clean());
    185 }
    186 
    187 void GpuProcessHostUIShim::SimulateCrash() {
    188   Send(new GpuMsg_Crash());
    189 }
    190 
    191 void GpuProcessHostUIShim::SimulateHang() {
    192   Send(new GpuMsg_Hang());
    193 }
    194 
    195 GpuProcessHostUIShim::~GpuProcessHostUIShim() {
    196   DCHECK(CalledOnValidThread());
    197   g_hosts_by_id.Pointer()->Remove(host_id_);
    198 }
    199 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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