Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / pepper_platform_context_3d.cc
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   gpu::Mailbox mailbox = gpu::Mailbox::Generate();
104   if (!command_buffer_->ProduceFrontBuffer(mailbox))
105     return false;
106   mailbox_ = mailbox;
107
108   command_buffer_->SetChannelErrorCallback(
109       base::Bind(&PlatformContext3D::OnContextLost,
110                  weak_ptr_factory_.GetWeakPtr()));
111   command_buffer_->SetOnConsoleMessageCallback(
112       base::Bind(&PlatformContext3D::OnConsoleMessage,
113                  weak_ptr_factory_.GetWeakPtr()));
114
115   return true;
116 }
117
118 void PlatformContext3D::GetBackingMailbox(gpu::Mailbox* mailbox) {
119   *mailbox = mailbox_;
120 }
121
122 bool PlatformContext3D::IsOpaque() {
123   DCHECK(command_buffer_);
124   return !has_alpha_;
125 }
126
127 gpu::CommandBuffer* PlatformContext3D::GetCommandBuffer() {
128   return command_buffer_;
129 }
130
131 gpu::GpuControl* PlatformContext3D::GetGpuControl() {
132   return command_buffer_;
133 }
134
135 int PlatformContext3D::GetCommandBufferRouteId() {
136   DCHECK(command_buffer_);
137   return command_buffer_->GetRouteID();
138 }
139
140 void PlatformContext3D::SetContextLostCallback(const base::Closure& task) {
141   context_lost_callback_ = task;
142 }
143
144 void PlatformContext3D::SetOnConsoleMessageCallback(
145     const ConsoleMessageCallback& task) {
146   console_message_callback_ = task;
147 }
148
149 void PlatformContext3D::Echo(const base::Closure& task) {
150   command_buffer_->Echo(task);
151 }
152
153 void PlatformContext3D::OnContextLost() {
154   DCHECK(command_buffer_);
155
156   if (!context_lost_callback_.is_null())
157     context_lost_callback_.Run();
158 }
159
160 void PlatformContext3D::OnConsoleMessage(const std::string& msg, int id) {
161   DCHECK(command_buffer_);
162
163   if (!console_message_callback_.is_null())
164     console_message_callback_.Run(msg, id);
165 }
166
167 }  // namespace content