| Index: content/common/gpu/gpu_channel.cc
 | 
| ===================================================================
 | 
| --- content/common/gpu/gpu_channel.cc	(revision 104937)
 | 
| +++ content/common/gpu/gpu_channel.cc	(working copy)
 | 
| @@ -37,6 +37,7 @@
 | 
|        watchdog_(watchdog),
 | 
|        software_(software),
 | 
|        handle_messages_scheduled_(false),
 | 
| +      num_contexts_preferring_discrete_gpu_(0),
 | 
|        task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
 | 
|    DCHECK(gpu_channel_manager);
 | 
|    DCHECK(renderer_id);
 | 
| @@ -167,6 +168,8 @@
 | 
|    content::GetContentClient()->SetActiveURL(init_params.active_url);
 | 
|  
 | 
|  #if defined(ENABLE_GPU)
 | 
| +  WillCreateCommandBuffer(init_params.gpu_preference);
 | 
| +
 | 
|    GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
 | 
|  
 | 
|    *route_id = GenerateRouteID();
 | 
| @@ -178,6 +181,7 @@
 | 
|        disallowed_features_,
 | 
|        init_params.allowed_extensions,
 | 
|        init_params.attribs,
 | 
| +      init_params.gpu_preference,
 | 
|        *route_id,
 | 
|        renderer_id_,
 | 
|        render_view_id,
 | 
| @@ -213,6 +217,9 @@
 | 
|      IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture,
 | 
|          OnCreateTransportTexture)
 | 
|      IPC_MESSAGE_HANDLER(GpuChannelMsg_Echo, OnEcho);
 | 
| +    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_WillGpuSwitchOccur,
 | 
| +                                    OnWillGpuSwitchOccur)
 | 
| +    IPC_MESSAGE_HANDLER(GpuChannelMsg_CloseChannel, OnCloseChannel)
 | 
|      IPC_MESSAGE_UNHANDLED(handled = false)
 | 
|    IPC_END_MESSAGE_MAP()
 | 
|    DCHECK(handled) << msg.type();
 | 
| @@ -271,6 +278,10 @@
 | 
|    router_.RemoveRoute(route_id);
 | 
|  }
 | 
|  
 | 
| +bool GpuChannel::ShouldPreferDiscreteGpu() const {
 | 
| +  return num_contexts_preferring_discrete_gpu_ > 0;
 | 
| +}
 | 
| +
 | 
|  void GpuChannel::OnInitialize(base::ProcessHandle renderer_process) {
 | 
|    // Initialize should only happen once.
 | 
|    DCHECK(!renderer_process_);
 | 
| @@ -288,6 +299,8 @@
 | 
|  
 | 
|    content::GetContentClient()->SetActiveURL(init_params.active_url);
 | 
|  #if defined(ENABLE_GPU)
 | 
| +  WillCreateCommandBuffer(init_params.gpu_preference);
 | 
| +
 | 
|    GpuCommandBufferStub* share_group = stubs_.Lookup(init_params.share_group_id);
 | 
|  
 | 
|    route_id = GenerateRouteID();
 | 
| @@ -300,6 +313,7 @@
 | 
|        disallowed_features_,
 | 
|        init_params.allowed_extensions,
 | 
|        init_params.attribs,
 | 
| +      init_params.gpu_preference,
 | 
|        route_id,
 | 
|        0, 0, watchdog_,
 | 
|        software_));
 | 
| @@ -323,12 +337,15 @@
 | 
|    if (router_.ResolveRoute(route_id)) {
 | 
|      GpuCommandBufferStub* stub = stubs_.Lookup(route_id);
 | 
|      bool need_reschedule = (stub && !stub->IsScheduled());
 | 
| +    gfx::GpuPreference gpu_preference =
 | 
| +        stub ? stub->gpu_preference() : gfx::PreferIntegratedGpu;
 | 
|      router_.RemoveRoute(route_id);
 | 
|      stubs_.Remove(route_id);
 | 
|      // In case the renderer is currently blocked waiting for a sync reply from
 | 
|      // the stub, we need to make sure to reschedule the GpuChannel here.
 | 
|      if (need_reschedule)
 | 
|        OnScheduled();
 | 
| +    DidDestroyCommandBuffer(gpu_preference);
 | 
|    }
 | 
|  #endif
 | 
|  
 | 
| @@ -359,6 +376,33 @@
 | 
|    Send(new IPC::Message(message));
 | 
|  }
 | 
|  
 | 
| +void GpuChannel::OnWillGpuSwitchOccur(bool is_creating_context,
 | 
| +                                      gfx::GpuPreference gpu_preference,
 | 
| +                                      IPC::Message* reply_message) {
 | 
| +  TRACE_EVENT0("gpu", "GpuChannel::OnWillGpuSwitchOccur");
 | 
| +
 | 
| +  bool will_switch_occur = false;
 | 
| +
 | 
| +  if (gpu_preference == gfx::PreferDiscreteGpu &&
 | 
| +      gfx::GLContext::SupportsDualGpus()) {
 | 
| +    if (is_creating_context) {
 | 
| +      will_switch_occur = !num_contexts_preferring_discrete_gpu_;
 | 
| +    } else {
 | 
| +      will_switch_occur = (num_contexts_preferring_discrete_gpu_ == 1);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  GpuChannelMsg_WillGpuSwitchOccur::WriteReplyParams(
 | 
| +      reply_message,
 | 
| +      will_switch_occur);
 | 
| +  Send(reply_message);
 | 
| +}
 | 
| +
 | 
| +void GpuChannel::OnCloseChannel() {
 | 
| +  gpu_channel_manager_->RemoveChannel(renderer_id_);
 | 
| +  // At this point "this" is deleted!
 | 
| +}
 | 
| +
 | 
|  bool GpuChannel::Init(base::MessageLoopProxy* io_message_loop,
 | 
|                        base::WaitableEvent* shutdown_event) {
 | 
|    // Check whether we're already initialized.
 | 
| @@ -378,6 +422,16 @@
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| +void GpuChannel::WillCreateCommandBuffer(gfx::GpuPreference gpu_preference) {
 | 
| +  if (gpu_preference == gfx::PreferDiscreteGpu)
 | 
| +    ++num_contexts_preferring_discrete_gpu_;
 | 
| +}
 | 
| +
 | 
| +void GpuChannel::DidDestroyCommandBuffer(gfx::GpuPreference gpu_preference) {
 | 
| +  if (gpu_preference == gfx::PreferDiscreteGpu)
 | 
| +    --num_contexts_preferring_discrete_gpu_;
 | 
| +}
 | 
| +
 | 
|  std::string GpuChannel::GetChannelName() {
 | 
|    return StringPrintf("%d.r%d.gpu", base::GetCurrentProcId(), renderer_id_);
 | 
|  }
 | 
| 
 |