• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
6 
7 #include <GLES2/gl2.h>
8 #ifndef GL_GLEXT_PROTOTYPES
9 #define GL_GLEXT_PROTOTYPES 1
10 #endif
11 #include <GLES2/gl2ext.h>
12 #include <GLES2/gl2extchromium.h>
13 
14 #include <string>
15 
16 #include "base/atomicops.h"
17 #include "base/bind.h"
18 #include "base/bind_helpers.h"
19 #include "base/callback.h"
20 #include "base/lazy_instance.h"
21 #include "base/logging.h"
22 #include "gpu/command_buffer/client/gles2_implementation.h"
23 #include "gpu/command_buffer/client/gles2_lib.h"
24 #include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
25 #include "ui/gfx/size.h"
26 #include "ui/gl/gl_implementation.h"
27 
28 using gpu::gles2::GLES2Implementation;
29 using gpu::GLInProcessContext;
30 
31 namespace webkit {
32 namespace gpu {
33 
34 namespace {
35 
36 const int32 kCommandBufferSize = 1024 * 1024;
37 // TODO(kbr): make the transfer buffer size configurable via context
38 // creation attributes.
39 const size_t kStartTransferBufferSize = 4 * 1024 * 1024;
40 const size_t kMinTransferBufferSize = 1 * 256 * 1024;
41 const size_t kMaxTransferBufferSize = 16 * 1024 * 1024;
42 
43 // Singleton used to initialize and terminate the gles2 library.
44 class GLES2Initializer {
45  public:
GLES2Initializer()46   GLES2Initializer() {
47     ::gles2::Initialize();
48   }
49 
~GLES2Initializer()50   ~GLES2Initializer() {
51     ::gles2::Terminate();
52   }
53 
54  private:
55   DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
56 };
57 
58 static base::LazyInstance<GLES2Initializer> g_gles2_initializer =
59     LAZY_INSTANCE_INITIALIZER;
60 
61 }  // namespace anonymous
62 
63 // static
64 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
CreateViewContext(const blink::WebGraphicsContext3D::Attributes & attributes,bool lose_context_when_out_of_memory,gfx::AcceleratedWidget window)65 WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext(
66     const blink::WebGraphicsContext3D::Attributes& attributes,
67     bool lose_context_when_out_of_memory,
68     gfx::AcceleratedWidget window) {
69   DCHECK_NE(gfx::GetGLImplementation(), gfx::kGLImplementationNone);
70   bool is_offscreen = false;
71   return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl(
72       scoped_ptr< ::gpu::GLInProcessContext>(),
73       attributes,
74       lose_context_when_out_of_memory,
75       is_offscreen,
76       window));
77 }
78 
79 // static
80 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
CreateOffscreenContext(const blink::WebGraphicsContext3D::Attributes & attributes,bool lose_context_when_out_of_memory)81 WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext(
82     const blink::WebGraphicsContext3D::Attributes& attributes,
83     bool lose_context_when_out_of_memory) {
84   bool is_offscreen = true;
85   return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl(
86       scoped_ptr< ::gpu::GLInProcessContext>(),
87       attributes,
88       lose_context_when_out_of_memory,
89       is_offscreen,
90       gfx::kNullAcceleratedWidget));
91 }
92 
93 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl>
WrapContext(scoped_ptr<::gpu::GLInProcessContext> context,const blink::WebGraphicsContext3D::Attributes & attributes)94 WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
95     scoped_ptr< ::gpu::GLInProcessContext> context,
96     const blink::WebGraphicsContext3D::Attributes& attributes) {
97   bool lose_context_when_out_of_memory = false;  // Not used.
98   bool is_offscreen = true;                      // Not used.
99   return make_scoped_ptr(new WebGraphicsContext3DInProcessCommandBufferImpl(
100       context.Pass(),
101       attributes,
102       lose_context_when_out_of_memory,
103       is_offscreen,
104       gfx::kNullAcceleratedWidget /* window. Not used. */));
105 }
106 
107 WebGraphicsContext3DInProcessCommandBufferImpl::
WebGraphicsContext3DInProcessCommandBufferImpl(scoped_ptr<::gpu::GLInProcessContext> context,const blink::WebGraphicsContext3D::Attributes & attributes,bool lose_context_when_out_of_memory,bool is_offscreen,gfx::AcceleratedWidget window)108     WebGraphicsContext3DInProcessCommandBufferImpl(
109         scoped_ptr< ::gpu::GLInProcessContext> context,
110         const blink::WebGraphicsContext3D::Attributes& attributes,
111         bool lose_context_when_out_of_memory,
112         bool is_offscreen,
113         gfx::AcceleratedWidget window)
114     : share_resources_(attributes.shareResources),
115       webgl_context_(attributes.noExtensions),
116       is_offscreen_(is_offscreen),
117       window_(window),
118       context_(context.Pass()) {
119   ConvertAttributes(attributes, &attribs_);
120   attribs_.lose_context_when_out_of_memory = lose_context_when_out_of_memory;
121 }
122 
123 WebGraphicsContext3DInProcessCommandBufferImpl::
~WebGraphicsContext3DInProcessCommandBufferImpl()124     ~WebGraphicsContext3DInProcessCommandBufferImpl() {
125 }
126 
127 // static
ConvertAttributes(const blink::WebGraphicsContext3D::Attributes & attributes,::gpu::GLInProcessContextAttribs * output_attribs)128 void WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
129     const blink::WebGraphicsContext3D::Attributes& attributes,
130     ::gpu::GLInProcessContextAttribs* output_attribs) {
131   output_attribs->alpha_size = attributes.alpha ? 8 : 0;
132   output_attribs->depth_size = attributes.depth ? 24 : 0;
133   output_attribs->stencil_size = attributes.stencil ? 8 : 0;
134   output_attribs->samples = attributes.antialias ? 4 : 0;
135   output_attribs->sample_buffers = attributes.antialias ? 1 : 0;
136   output_attribs->fail_if_major_perf_caveat =
137       attributes.failIfMajorPerformanceCaveat ? 1 : 0;
138 }
139 
MaybeInitializeGL()140 bool WebGraphicsContext3DInProcessCommandBufferImpl::MaybeInitializeGL() {
141   if (initialized_)
142     return true;
143 
144   if (initialize_failed_)
145     return false;
146 
147   // Ensure the gles2 library is initialized first in a thread safe way.
148   g_gles2_initializer.Get();
149 
150   if (!context_) {
151     // TODO(kbr): More work will be needed in this implementation to
152     // properly support GPU switching. Like in the out-of-process
153     // command buffer implementation, all previously created contexts
154     // will need to be lost either when the first context requesting the
155     // discrete GPU is created, or the last one is destroyed.
156     gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
157     context_.reset(GLInProcessContext::Create(NULL, /* service */
158                                               NULL, /* surface */
159                                               is_offscreen_,
160                                               window_,
161                                               gfx::Size(1, 1),
162                                               NULL, /* share_context */
163                                               share_resources_,
164                                               attribs_,
165                                               gpu_preference));
166   }
167 
168   if (context_) {
169     base::Closure context_lost_callback = base::Bind(
170         &WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost,
171         base::Unretained(this));
172     context_->SetContextLostCallback(context_lost_callback);
173   } else {
174     initialize_failed_ = true;
175     return false;
176   }
177 
178   real_gl_ = context_->GetImplementation();
179   setGLInterface(real_gl_);
180 
181   if (real_gl_ && webgl_context_)
182     real_gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation");
183 
184   initialized_ = true;
185   return true;
186 }
187 
makeContextCurrent()188 bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() {
189   if (!MaybeInitializeGL())
190     return false;
191   ::gles2::SetGLContext(GetGLInterface());
192   return context_ && !isContextLost();
193 }
194 
isContextLost()195 bool WebGraphicsContext3DInProcessCommandBufferImpl::isContextLost() {
196   return context_lost_reason_ != GL_NO_ERROR;
197 }
198 
199 WGC3Denum WebGraphicsContext3DInProcessCommandBufferImpl::
getGraphicsResetStatusARB()200     getGraphicsResetStatusARB() {
201   return context_lost_reason_;
202 }
203 
204 ::gpu::ContextSupport*
GetContextSupport()205 WebGraphicsContext3DInProcessCommandBufferImpl::GetContextSupport() {
206   return real_gl_;
207 }
208 
OnContextLost()209 void WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost() {
210   // TODO(kbr): improve the precision here.
211   context_lost_reason_ = GL_UNKNOWN_CONTEXT_RESET_ARB;
212   if (context_lost_callback_) {
213     context_lost_callback_->onContextLost();
214   }
215 }
216 
217 }  // namespace gpu
218 }  // namespace webkit
219