Home | History | Annotate | Download | only in renderer_host
      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 #if defined(OS_WIN)
      6 #include <windows.h>
      7 #endif
      8 
      9 #include "content/browser/renderer_host/gpu_message_filter.h"
     10 
     11 #include "base/bind.h"
     12 #include "base/command_line.h"
     13 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
     14 #include "content/browser/gpu/gpu_data_manager_impl_private.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_widget_helper.h"
     18 #include "content/common/gpu/gpu_messages.h"
     19 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
     20 #include "content/public/common/content_switches.h"
     21 #include "gpu/command_buffer/service/gpu_switches.h"
     22 
     23 namespace content {
     24 
     25 struct GpuMessageFilter::CreateViewCommandBufferRequest {
     26   CreateViewCommandBufferRequest(
     27       int32 surface_id,
     28       const GPUCreateCommandBufferConfig& init_params,
     29       scoped_ptr<IPC::Message> reply)
     30       : surface_id(surface_id),
     31         init_params(init_params),
     32         reply(reply.Pass()) {
     33   }
     34   int32 surface_id;
     35   GPUCreateCommandBufferConfig init_params;
     36   scoped_ptr<IPC::Message> reply;
     37 };
     38 
     39 struct GpuMessageFilter::FrameSubscription {
     40   FrameSubscription(
     41       int in_route_id,
     42       scoped_ptr<RenderWidgetHostViewFrameSubscriber> in_subscriber)
     43       : route_id(in_route_id),
     44         surface_id(0),
     45         subscriber(in_subscriber.Pass()),
     46         factory(subscriber.get()) {
     47   }
     48 
     49   int route_id;
     50   int surface_id;
     51   scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber;
     52   base::WeakPtrFactory<RenderWidgetHostViewFrameSubscriber> factory;
     53 };
     54 
     55 GpuMessageFilter::GpuMessageFilter(int render_process_id,
     56                                    RenderWidgetHelper* render_widget_helper)
     57     : BrowserMessageFilter(GpuMsgStart),
     58       gpu_process_id_(0),
     59       render_process_id_(render_process_id),
     60       render_widget_helper_(render_widget_helper),
     61       weak_ptr_factory_(this) {
     62   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     63 }
     64 
     65 GpuMessageFilter::~GpuMessageFilter() {
     66   DCHECK_CURRENTLY_ON(BrowserThread::IO);
     67   EndAllFrameSubscriptions();
     68 }
     69 
     70 bool GpuMessageFilter::OnMessageReceived(const IPC::Message& message) {
     71   bool handled = true;
     72   IPC_BEGIN_MESSAGE_MAP(GpuMessageFilter, message)
     73     IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_EstablishGpuChannel,
     74                                     OnEstablishGpuChannel)
     75     IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_CreateViewCommandBuffer,
     76                                     OnCreateViewCommandBuffer)
     77     IPC_MESSAGE_UNHANDLED(handled = false)
     78   IPC_END_MESSAGE_MAP()
     79   return handled;
     80 }
     81 
     82 void GpuMessageFilter::BeginFrameSubscription(
     83     int route_id,
     84     scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
     85   DCHECK_CURRENTLY_ON(BrowserThread::IO);
     86   linked_ptr<FrameSubscription> subscription(
     87       new FrameSubscription(route_id, subscriber.Pass()));
     88   BeginFrameSubscriptionInternal(subscription);
     89 }
     90 
     91 void GpuMessageFilter::EndFrameSubscription(int route_id) {
     92   DCHECK_CURRENTLY_ON(BrowserThread::IO);
     93   FrameSubscriptionList frame_subscription_list;
     94   frame_subscription_list.swap(frame_subscription_list_);
     95   for (FrameSubscriptionList::iterator it = frame_subscription_list.begin();
     96        it != frame_subscription_list.end(); ++it) {
     97     if ((*it)->route_id != route_id)
     98       frame_subscription_list_.push_back(*it);
     99     else
    100       EndFrameSubscriptionInternal(*it);
    101   }
    102 }
    103 
    104 void GpuMessageFilter::OnEstablishGpuChannel(
    105     CauseForGpuLaunch cause_for_gpu_launch,
    106     IPC::Message* reply_ptr) {
    107   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    108   scoped_ptr<IPC::Message> reply(reply_ptr);
    109 
    110   // TODO(apatrick): Eventually, this will return the route ID of a
    111   // GpuProcessStub, from which the renderer process will create a
    112   // GpuProcessProxy. The renderer will use the proxy for all subsequent
    113   // communication with the GPU process. This means if the GPU process
    114   // terminates, the renderer process will not find itself unknowingly sending
    115   // IPCs to a newly launched GPU process. Also, I will rename this function
    116   // to something like OnCreateGpuProcess.
    117   GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
    118   if (!host) {
    119     host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
    120                                cause_for_gpu_launch);
    121     if (!host) {
    122       reply->set_reply_error();
    123       Send(reply.release());
    124       return;
    125     }
    126 
    127     gpu_process_id_ = host->host_id();
    128 
    129     // Apply all frame subscriptions to the new GpuProcessHost.
    130     BeginAllFrameSubscriptions();
    131   }
    132 
    133   bool share_contexts = true;
    134   host->EstablishGpuChannel(
    135       render_process_id_,
    136       share_contexts,
    137       base::Bind(&GpuMessageFilter::EstablishChannelCallback,
    138                  weak_ptr_factory_.GetWeakPtr(),
    139                  base::Passed(&reply)));
    140 }
    141 
    142 void GpuMessageFilter::OnCreateViewCommandBuffer(
    143     int32 surface_id,
    144     const GPUCreateCommandBufferConfig& init_params,
    145     int32 route_id,
    146     IPC::Message* reply_ptr) {
    147   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    148   scoped_ptr<IPC::Message> reply(reply_ptr);
    149 
    150   GpuSurfaceTracker* surface_tracker = GpuSurfaceTracker::Get();
    151   gfx::GLSurfaceHandle compositing_surface;
    152 
    153   int renderer_id = 0;
    154   int render_widget_id = 0;
    155   bool result = surface_tracker->GetRenderWidgetIDForSurface(
    156       surface_id, &renderer_id, &render_widget_id);
    157   if (result && renderer_id == render_process_id_) {
    158     compositing_surface = surface_tracker->GetSurfaceHandle(surface_id);
    159   } else {
    160     DLOG(ERROR) << "Renderer " << render_process_id_
    161                 << " tried to access a surface for renderer " << renderer_id;
    162   }
    163 
    164   if (compositing_surface.parent_client_id &&
    165       !GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
    166     // For the renderer to fall back to software also.
    167     compositing_surface = gfx::GLSurfaceHandle();
    168   }
    169 
    170   GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
    171   if (!host || compositing_surface.is_null()) {
    172     // TODO(apatrick): Eventually, this IPC message will be routed to a
    173     // GpuProcessStub with a particular routing ID. The error will be set if
    174     // the GpuProcessStub with that routing ID is not in the MessageRouter.
    175     reply->set_reply_error();
    176     Send(reply.release());
    177     return;
    178   }
    179 
    180   host->CreateViewCommandBuffer(
    181       compositing_surface,
    182       surface_id,
    183       render_process_id_,
    184       init_params,
    185       route_id,
    186       base::Bind(&GpuMessageFilter::CreateCommandBufferCallback,
    187                  weak_ptr_factory_.GetWeakPtr(),
    188                  base::Passed(&reply)));
    189 }
    190 
    191 void GpuMessageFilter::EstablishChannelCallback(
    192     scoped_ptr<IPC::Message> reply,
    193     const IPC::ChannelHandle& channel,
    194     const gpu::GPUInfo& gpu_info) {
    195   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    196 
    197   GpuHostMsg_EstablishGpuChannel::WriteReplyParams(
    198       reply.get(), render_process_id_, channel, gpu_info);
    199   Send(reply.release());
    200 }
    201 
    202 void GpuMessageFilter::CreateCommandBufferCallback(
    203     scoped_ptr<IPC::Message> reply, CreateCommandBufferResult result) {
    204   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    205   GpuHostMsg_CreateViewCommandBuffer::WriteReplyParams(reply.get(), result);
    206   Send(reply.release());
    207 }
    208 
    209 void GpuMessageFilter::BeginAllFrameSubscriptions() {
    210   FrameSubscriptionList frame_subscription_list;
    211   frame_subscription_list.swap(frame_subscription_list_);
    212   for (FrameSubscriptionList::iterator it = frame_subscription_list.begin();
    213        it != frame_subscription_list.end(); ++it) {
    214     BeginFrameSubscriptionInternal(*it);
    215   }
    216 }
    217 
    218 void GpuMessageFilter::EndAllFrameSubscriptions() {
    219   for (FrameSubscriptionList::iterator it = frame_subscription_list_.begin();
    220        it != frame_subscription_list_.end(); ++it) {
    221     EndFrameSubscriptionInternal(*it);
    222   }
    223   frame_subscription_list_.clear();
    224 }
    225 
    226 void GpuMessageFilter::BeginFrameSubscriptionInternal(
    227     linked_ptr<FrameSubscription> subscription) {
    228   if (!subscription->surface_id) {
    229     GpuSurfaceTracker* surface_tracker = GpuSurfaceTracker::Get();
    230     subscription->surface_id = surface_tracker->LookupSurfaceForRenderer(
    231         render_process_id_, subscription->route_id);
    232 
    233     // If the surface ID cannot be found this subscription is dropped.
    234     if (!subscription->surface_id)
    235       return;
    236   }
    237   frame_subscription_list_.push_back(subscription);
    238 
    239   // Frame subscriber is owned by this object, but it is shared with
    240   // GpuProcessHost. GpuProcessHost can be destroyed in the case of crashing
    241   // and we do not get a signal. This object can also be destroyed independent
    242   // of GpuProcessHost. To ensure that GpuProcessHost does not reference a
    243   // deleted frame subscriber, a weak reference is shared.
    244   GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
    245   if (!host)
    246     return;
    247   host->BeginFrameSubscription(subscription->surface_id,
    248                                subscription->factory.GetWeakPtr());
    249 }
    250 
    251 void GpuMessageFilter::EndFrameSubscriptionInternal(
    252     linked_ptr<FrameSubscription> subscription) {
    253   GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
    254 
    255   // An empty surface ID means subscription has never started in GpuProcessHost
    256   // so it is not necessary to end it.
    257   if (!host || !subscription->surface_id)
    258     return;
    259 
    260   // Note that GpuProcessHost here might not be the same one that frame
    261   // subscription has applied.
    262   host->EndFrameSubscription(subscription->surface_id);
    263 }
    264 
    265 }  // namespace content
    266