Home | History | Annotate | Download | only in pepper
      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/renderer/pepper/pepper_platform_context_3d.h"
      6 
      7 #include "base/bind.h"
      8 #include "content/common/gpu/client/context_provider_command_buffer.h"
      9 #include "content/common/gpu/client/gpu_channel_host.h"
     10 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
     11 #include "content/renderer/render_thread_impl.h"
     12 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
     13 #include "gpu/command_buffer/client/gles2_implementation.h"
     14 #include "ppapi/c/pp_graphics_3d.h"
     15 #include "ui/gl/gpu_preference.h"
     16 #include "url/gurl.h"
     17 
     18 namespace content {
     19 
     20 PlatformContext3D::PlatformContext3D()
     21     : has_alpha_(false),
     22       command_buffer_(NULL),
     23       weak_ptr_factory_(this) {
     24 }
     25 
     26 PlatformContext3D::~PlatformContext3D() {
     27   if (command_buffer_) {
     28     DCHECK(channel_.get());
     29     channel_->DestroyCommandBuffer(command_buffer_);
     30     command_buffer_ = NULL;
     31   }
     32 
     33   channel_ = NULL;
     34 }
     35 
     36 bool PlatformContext3D::Init(const int32* attrib_list,
     37                              PlatformContext3D* share_context) {
     38   // Ignore initializing more than once.
     39   if (command_buffer_)
     40     return true;
     41 
     42   RenderThreadImpl* render_thread = RenderThreadImpl::current();
     43   if (!render_thread)
     44     return false;
     45 
     46   gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
     47 
     48   channel_ = render_thread->EstablishGpuChannelSync(
     49       CAUSE_FOR_GPU_LAUNCH_PEPPERPLATFORMCONTEXT3DIMPL_INITIALIZE);
     50   if (!channel_.get())
     51     return false;
     52 
     53   gfx::Size surface_size;
     54   std::vector<int32> attribs;
     55   // TODO(alokp): Change GpuChannelHost::CreateOffscreenCommandBuffer()
     56   // interface to accept width and height in the attrib_list so that
     57   // we do not need to filter for width and height here.
     58   if (attrib_list) {
     59     for (const int32_t* attr = attrib_list;
     60          attr[0] != PP_GRAPHICS3DATTRIB_NONE;
     61          attr += 2) {
     62       switch (attr[0]) {
     63         case PP_GRAPHICS3DATTRIB_WIDTH:
     64           surface_size.set_width(attr[1]);
     65           break;
     66         case PP_GRAPHICS3DATTRIB_HEIGHT:
     67           surface_size.set_height(attr[1]);
     68           break;
     69         case PP_GRAPHICS3DATTRIB_GPU_PREFERENCE:
     70           gpu_preference =
     71               (attr[1] == PP_GRAPHICS3DATTRIB_GPU_PREFERENCE_LOW_POWER) ?
     72                   gfx::PreferIntegratedGpu : gfx::PreferDiscreteGpu;
     73           break;
     74         case PP_GRAPHICS3DATTRIB_ALPHA_SIZE:
     75           has_alpha_ = attr[1] > 0;
     76         // fall-through
     77         default:
     78           attribs.push_back(attr[0]);
     79           attribs.push_back(attr[1]);
     80           break;
     81       }
     82     }
     83     attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
     84   }
     85 
     86   CommandBufferProxyImpl* share_buffer = NULL;
     87   if (share_context) {
     88     PlatformContext3D* share_impl =
     89         static_cast<PlatformContext3D*>(share_context);
     90     share_buffer = share_impl->command_buffer_;
     91   }
     92 
     93   command_buffer_ = channel_->CreateOffscreenCommandBuffer(
     94       surface_size,
     95       share_buffer,
     96       attribs,
     97       GURL::EmptyGURL(),
     98       gpu_preference);
     99   if (!command_buffer_)
    100     return false;
    101   if (!command_buffer_->Initialize())
    102     return false;
    103   std::vector<gpu::Mailbox> names;
    104   if (!command_buffer_->GenerateMailboxNames(1, &names))
    105     return false;
    106   DCHECK_EQ(names.size(), 1u);
    107   if (!command_buffer_->ProduceFrontBuffer(names[0]))
    108     return false;
    109   mailbox_ = names[0];
    110   sync_point_ = command_buffer_->InsertSyncPoint();
    111 
    112   command_buffer_->SetChannelErrorCallback(
    113       base::Bind(&PlatformContext3D::OnContextLost,
    114                  weak_ptr_factory_.GetWeakPtr()));
    115   command_buffer_->SetOnConsoleMessageCallback(
    116       base::Bind(&PlatformContext3D::OnConsoleMessage,
    117                  weak_ptr_factory_.GetWeakPtr()));
    118 
    119   return true;
    120 }
    121 
    122 void PlatformContext3D::GetBackingMailbox(gpu::Mailbox* mailbox,
    123                                           uint32* sync_point) {
    124   *mailbox = mailbox_;
    125   *sync_point = sync_point_;
    126 }
    127 
    128 void PlatformContext3D::InsertSyncPointForBackingMailbox() {
    129   DCHECK(command_buffer_);
    130   sync_point_ = command_buffer_->InsertSyncPoint();
    131 }
    132 
    133 bool PlatformContext3D::IsOpaque() {
    134   DCHECK(command_buffer_);
    135   return !has_alpha_;
    136 }
    137 
    138 gpu::CommandBuffer* PlatformContext3D::GetCommandBuffer() {
    139   return command_buffer_;
    140 }
    141 
    142 gpu::GpuControl* PlatformContext3D::GetGpuControl() {
    143   return command_buffer_;
    144 }
    145 
    146 int PlatformContext3D::GetCommandBufferRouteId() {
    147   DCHECK(command_buffer_);
    148   return command_buffer_->GetRouteID();
    149 }
    150 
    151 void PlatformContext3D::SetContextLostCallback(const base::Closure& task) {
    152   context_lost_callback_ = task;
    153 }
    154 
    155 void PlatformContext3D::SetOnConsoleMessageCallback(
    156     const ConsoleMessageCallback& task) {
    157   console_message_callback_ = task;
    158 }
    159 
    160 void PlatformContext3D::Echo(const base::Closure& task) {
    161   command_buffer_->Echo(task);
    162 }
    163 
    164 void PlatformContext3D::OnContextLost() {
    165   DCHECK(command_buffer_);
    166 
    167   if (!context_lost_callback_.is_null())
    168     context_lost_callback_.Run();
    169 }
    170 
    171 void PlatformContext3D::OnConsoleMessage(const std::string& msg, int id) {
    172   DCHECK(command_buffer_);
    173 
    174   if (!console_message_callback_.is_null())
    175     console_message_callback_.Run(msg, id);
    176 }
    177 
    178 }  // namespace content
    179