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