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       false,
    138       base::Bind(&GpuMessageFilter::EstablishChannelCallback,
    139                  weak_ptr_factory_.GetWeakPtr(),
    140                  base::Passed(&reply)));
    141 }
    142 
    143 void GpuMessageFilter::OnCreateViewCommandBuffer(
    144     int32 surface_id,
    145     const GPUCreateCommandBufferConfig& init_params,
    146     int32 route_id,
    147     IPC::Message* reply_ptr) {
    148   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    149   scoped_ptr<IPC::Message> reply(reply_ptr);
    150 
    151   GpuSurfaceTracker* surface_tracker = GpuSurfaceTracker::Get();
    152   gfx::GLSurfaceHandle compositing_surface;
    153 
    154   int renderer_id = 0;
    155   int render_widget_id = 0;
    156   bool result = surface_tracker->GetRenderWidgetIDForSurface(
    157       surface_id, &renderer_id, &render_widget_id);
    158   if (result && renderer_id == render_process_id_) {
    159     compositing_surface = surface_tracker->GetSurfaceHandle(surface_id);
    160   } else {
    161     DLOG(ERROR) << "Renderer " << render_process_id_
    162                 << " tried to access a surface for renderer " << renderer_id;
    163   }
    164 
    165   if (compositing_surface.parent_client_id &&
    166       !GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
    167     // For the renderer to fall back to software also.
    168     compositing_surface = gfx::GLSurfaceHandle();
    169   }
    170 
    171   GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
    172   if (!host || compositing_surface.is_null()) {
    173     // TODO(apatrick): Eventually, this IPC message will be routed to a
    174     // GpuProcessStub with a particular routing ID. The error will be set if
    175     // the GpuProcessStub with that routing ID is not in the MessageRouter.
    176     reply->set_reply_error();
    177     Send(reply.release());
    178     return;
    179   }
    180 
    181   host->CreateViewCommandBuffer(
    182       compositing_surface,
    183       surface_id,
    184       render_process_id_,
    185       init_params,
    186       route_id,
    187       base::Bind(&GpuMessageFilter::CreateCommandBufferCallback,
    188                  weak_ptr_factory_.GetWeakPtr(),
    189                  base::Passed(&reply)));
    190 }
    191 
    192 void GpuMessageFilter::EstablishChannelCallback(
    193     scoped_ptr<IPC::Message> reply,
    194     const IPC::ChannelHandle& channel,
    195     const gpu::GPUInfo& gpu_info) {
    196   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    197 
    198   GpuHostMsg_EstablishGpuChannel::WriteReplyParams(
    199       reply.get(), render_process_id_, channel, gpu_info);
    200   Send(reply.release());
    201 }
    202 
    203 void GpuMessageFilter::CreateCommandBufferCallback(
    204     scoped_ptr<IPC::Message> reply, CreateCommandBufferResult result) {
    205   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    206   GpuHostMsg_CreateViewCommandBuffer::WriteReplyParams(reply.get(), result);
    207   Send(reply.release());
    208 }
    209 
    210 void GpuMessageFilter::BeginAllFrameSubscriptions() {
    211   FrameSubscriptionList frame_subscription_list;
    212   frame_subscription_list.swap(frame_subscription_list_);
    213   for (FrameSubscriptionList::iterator it = frame_subscription_list.begin();
    214        it != frame_subscription_list.end(); ++it) {
    215     BeginFrameSubscriptionInternal(*it);
    216   }
    217 }
    218 
    219 void GpuMessageFilter::EndAllFrameSubscriptions() {
    220   for (FrameSubscriptionList::iterator it = frame_subscription_list_.begin();
    221        it != frame_subscription_list_.end(); ++it) {
    222     EndFrameSubscriptionInternal(*it);
    223   }
    224   frame_subscription_list_.clear();
    225 }
    226 
    227 void GpuMessageFilter::BeginFrameSubscriptionInternal(
    228     linked_ptr<FrameSubscription> subscription) {
    229   if (!subscription->surface_id) {
    230     GpuSurfaceTracker* surface_tracker = GpuSurfaceTracker::Get();
    231     subscription->surface_id = surface_tracker->LookupSurfaceForRenderer(
    232         render_process_id_, subscription->route_id);
    233 
    234     // If the surface ID cannot be found this subscription is dropped.
    235     if (!subscription->surface_id)
    236       return;
    237   }
    238   frame_subscription_list_.push_back(subscription);
    239 
    240   // Frame subscriber is owned by this object, but it is shared with
    241   // GpuProcessHost. GpuProcessHost can be destroyed in the case of crashing
    242   // and we do not get a signal. This object can also be destroyed independent
    243   // of GpuProcessHost. To ensure that GpuProcessHost does not reference a
    244   // deleted frame subscriber, a weak reference is shared.
    245   GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
    246   if (!host)
    247     return;
    248   host->BeginFrameSubscription(subscription->surface_id,
    249                                subscription->factory.GetWeakPtr());
    250 }
    251 
    252 void GpuMessageFilter::EndFrameSubscriptionInternal(
    253     linked_ptr<FrameSubscription> subscription) {
    254   GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
    255 
    256   // An empty surface ID means subscription has never started in GpuProcessHost
    257   // so it is not necessary to end it.
    258   if (!host || !subscription->surface_id)
    259     return;
    260 
    261   // Note that GpuProcessHost here might not be the same one that frame
    262   // subscription has applied.
    263   host->EndFrameSubscription(subscription->surface_id);
    264 }
    265 
    266 }  // namespace content
    267