Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / context_group.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 "gpu/command_buffer/service/context_group.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "base/command_line.h"
11 #include "base/strings/string_util.h"
12 #include "base/sys_info.h"
13 #include "gpu/command_buffer/common/id_allocator.h"
14 #include "gpu/command_buffer/service/buffer_manager.h"
15 #include "gpu/command_buffer/service/framebuffer_manager.h"
16 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
17 #include "gpu/command_buffer/service/gpu_switches.h"
18 #include "gpu/command_buffer/service/mailbox_manager.h"
19 #include "gpu/command_buffer/service/memory_tracking.h"
20 #include "gpu/command_buffer/service/program_manager.h"
21 #include "gpu/command_buffer/service/renderbuffer_manager.h"
22 #include "gpu/command_buffer/service/shader_manager.h"
23 #include "gpu/command_buffer/service/texture_manager.h"
24 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
25 #include "ui/gl/gl_implementation.h"
26
27 namespace gpu {
28 namespace gles2 {
29
30 ContextGroup::ContextGroup(
31     MailboxManager* mailbox_manager,
32     MemoryTracker* memory_tracker,
33     ShaderTranslatorCache* shader_translator_cache,
34     FeatureInfo* feature_info,
35     bool bind_generates_resource)
36     : mailbox_manager_(mailbox_manager ? mailbox_manager : new MailboxManager),
37       memory_tracker_(memory_tracker),
38       shader_translator_cache_(shader_translator_cache),
39       enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch(
40           switches::kEnforceGLMinimums)),
41       bind_generates_resource_(bind_generates_resource),
42       max_vertex_attribs_(0u),
43       max_texture_units_(0u),
44       max_texture_image_units_(0u),
45       max_vertex_texture_image_units_(0u),
46       max_fragment_uniform_vectors_(0u),
47       max_varying_vectors_(0u),
48       max_vertex_uniform_vectors_(0u),
49       max_color_attachments_(1u),
50       max_draw_buffers_(1u),
51       program_cache_(NULL),
52       feature_info_(feature_info ? feature_info : new FeatureInfo),
53       draw_buffer_(GL_BACK) {
54   {
55     TransferBufferManager* manager = new TransferBufferManager();
56     transfer_buffer_manager_.reset(manager);
57     manager->Initialize();
58   }
59
60   id_namespaces_[id_namespaces::kBuffers].reset(new IdAllocator);
61   id_namespaces_[id_namespaces::kFramebuffers].reset(new IdAllocator);
62   id_namespaces_[id_namespaces::kProgramsAndShaders].reset(
63       new NonReusedIdAllocator);
64   id_namespaces_[id_namespaces::kRenderbuffers].reset(new IdAllocator);
65   id_namespaces_[id_namespaces::kTextures].reset(new IdAllocator);
66   id_namespaces_[id_namespaces::kQueries].reset(new IdAllocator);
67   id_namespaces_[id_namespaces::kVertexArrays].reset(new IdAllocator);
68 }
69
70 static void GetIntegerv(GLenum pname, uint32* var) {
71   GLint value = 0;
72   glGetIntegerv(pname, &value);
73   *var = value;
74 }
75
76 bool ContextGroup::Initialize(
77     GLES2Decoder* decoder,
78     const DisallowedFeatures& disallowed_features) {
79   // If we've already initialized the group just add the context.
80   if (HaveContexts()) {
81     decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
82     return true;
83   }
84
85   if (!feature_info_->Initialize(disallowed_features)) {
86     LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
87                << "initialization failed.";
88     return false;
89   }
90
91   const GLint kMinRenderbufferSize = 512;  // GL says 1 pixel!
92   GLint max_renderbuffer_size = 0;
93   if (!QueryGLFeature(
94       GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize,
95       &max_renderbuffer_size)) {
96     LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
97                << "renderbuffer size too small.";
98     return false;
99   }
100   GLint max_samples = 0;
101   if (feature_info_->feature_flags().chromium_framebuffer_multisample ||
102       feature_info_->feature_flags().multisampled_render_to_texture) {
103     if (feature_info_->feature_flags(
104             ).use_img_for_multisampled_render_to_texture) {
105       glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples);
106     } else {
107       glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
108     }
109   }
110
111   if (feature_info_->feature_flags().ext_draw_buffers) {
112     GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments_);
113     if (max_color_attachments_ < 1)
114       max_color_attachments_ = 1;
115     GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers_);
116     if (max_draw_buffers_ < 1)
117       max_draw_buffers_ = 1;
118     draw_buffer_ = GL_BACK;
119   }
120
121   const bool depth24_supported = feature_info_->feature_flags().oes_depth24;
122
123   buffer_manager_.reset(
124       new BufferManager(memory_tracker_.get(), feature_info_.get()));
125   framebuffer_manager_.reset(
126       new FramebufferManager(max_draw_buffers_, max_color_attachments_));
127   renderbuffer_manager_.reset(new RenderbufferManager(
128       memory_tracker_.get(), max_renderbuffer_size, max_samples,
129       depth24_supported));
130   shader_manager_.reset(new ShaderManager());
131
132   // Lookup GL things we need to know.
133   const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
134   if (!QueryGLFeatureU(
135       GL_MAX_VERTEX_ATTRIBS, kGLES2RequiredMinimumVertexAttribs,
136       &max_vertex_attribs_)) {
137     LOG(ERROR) << "ContextGroup::Initialize failed because too few "
138                << "vertex attributes supported.";
139     return false;
140   }
141
142   const GLuint kGLES2RequiredMinimumTextureUnits = 8u;
143   if (!QueryGLFeatureU(
144       GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kGLES2RequiredMinimumTextureUnits,
145       &max_texture_units_)) {
146     LOG(ERROR) << "ContextGroup::Initialize failed because too few "
147                << "texture units supported.";
148     return false;
149   }
150
151   GLint max_texture_size = 0;
152   GLint max_cube_map_texture_size = 0;
153   const GLint kMinTextureSize = 2048;  // GL actually says 64!?!?
154   const GLint kMinCubeMapSize = 256;  // GL actually says 16!?!?
155   if (!QueryGLFeature(
156       GL_MAX_TEXTURE_SIZE, kMinTextureSize, &max_texture_size) ||
157       !QueryGLFeature(
158       GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize,
159       &max_cube_map_texture_size)) {
160     LOG(ERROR) << "ContextGroup::Initialize failed because maximum texture size"
161                << "is too small.";
162     return false;
163   }
164
165   if (feature_info_->workarounds().max_texture_size) {
166     max_texture_size = std::min(
167         max_texture_size, feature_info_->workarounds().max_texture_size);
168   }
169   if (feature_info_->workarounds().max_cube_map_texture_size) {
170     max_cube_map_texture_size = std::min(
171         max_cube_map_texture_size,
172         feature_info_->workarounds().max_cube_map_texture_size);
173   }
174
175   texture_manager_.reset(new TextureManager(memory_tracker_.get(),
176                                             feature_info_.get(),
177                                             max_texture_size,
178                                             max_cube_map_texture_size,
179                                             bind_generates_resource_));
180   texture_manager_->set_framebuffer_manager(framebuffer_manager_.get());
181
182   const GLint kMinTextureImageUnits = 8;
183   const GLint kMinVertexTextureImageUnits = 0;
184   if (!QueryGLFeatureU(
185       GL_MAX_TEXTURE_IMAGE_UNITS, kMinTextureImageUnits,
186       &max_texture_image_units_) ||
187       !QueryGLFeatureU(
188       GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits,
189       &max_vertex_texture_image_units_)) {
190     LOG(ERROR) << "ContextGroup::Initialize failed because too few "
191                << "texture units.";
192     return false;
193   }
194
195   if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
196     GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
197         &max_fragment_uniform_vectors_);
198     GetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors_);
199     GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &max_vertex_uniform_vectors_);
200   } else {
201     GetIntegerv(
202         GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max_fragment_uniform_vectors_);
203     max_fragment_uniform_vectors_ /= 4;
204     GetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_vectors_);
205     max_varying_vectors_ /= 4;
206     GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_vertex_uniform_vectors_);
207     max_vertex_uniform_vectors_ /= 4;
208   }
209
210   const GLint kMinFragmentUniformVectors = 16;
211   const GLint kMinVaryingVectors = 8;
212   const GLint kMinVertexUniformVectors = 128;
213   if (!CheckGLFeatureU(
214       kMinFragmentUniformVectors, &max_fragment_uniform_vectors_) ||
215       !CheckGLFeatureU(kMinVaryingVectors, &max_varying_vectors_) ||
216       !CheckGLFeatureU(
217       kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) {
218     LOG(ERROR) << "ContextGroup::Initialize failed because too few "
219                << "uniforms or varyings supported.";
220     return false;
221   }
222
223   // Some shaders in Skia need more than the min available vertex and
224   // fragment shader uniform vectors in case of OSMesa GL Implementation
225   if (feature_info_->workarounds().max_fragment_uniform_vectors) {
226     max_fragment_uniform_vectors_ = std::min(
227         max_fragment_uniform_vectors_,
228         static_cast<uint32>(
229             feature_info_->workarounds().max_fragment_uniform_vectors));
230   }
231   if (feature_info_->workarounds().max_varying_vectors) {
232     max_varying_vectors_ = std::min(
233         max_varying_vectors_,
234         static_cast<uint32>(feature_info_->workarounds().max_varying_vectors));
235   }
236   if (feature_info_->workarounds().max_vertex_uniform_vectors) {
237     max_vertex_uniform_vectors_ =
238         std::min(max_vertex_uniform_vectors_,
239                  static_cast<uint32>(
240                      feature_info_->workarounds().max_vertex_uniform_vectors));
241   }
242
243   program_manager_.reset(new ProgramManager(
244       program_cache_, max_varying_vectors_));
245
246   if (!texture_manager_->Initialize()) {
247     LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
248                << "failed to initialize.";
249     return false;
250   }
251
252   decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
253   return true;
254 }
255
256 namespace {
257
258 bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) {
259   return !decoder.get();
260 }
261
262 template <typename T>
263 class WeakPtrEquals {
264  public:
265   explicit WeakPtrEquals(T* t) : t_(t) {}
266
267   bool operator()(const base::WeakPtr<T>& t) {
268     return t.get() == t_;
269   }
270
271  private:
272   T* const t_;
273 };
274
275 }  // namespace anonymous
276
277 bool ContextGroup::HaveContexts() {
278   decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull),
279                   decoders_.end());
280   return !decoders_.empty();
281 }
282
283 void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) {
284   decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(),
285                                  WeakPtrEquals<gles2::GLES2Decoder>(decoder)),
286                   decoders_.end());
287   // If we still have contexts do nothing.
288   if (HaveContexts()) {
289     return;
290   }
291
292   if (buffer_manager_ != NULL) {
293     buffer_manager_->Destroy(have_context);
294     buffer_manager_.reset();
295   }
296
297   if (framebuffer_manager_ != NULL) {
298     framebuffer_manager_->Destroy(have_context);
299     if (texture_manager_)
300       texture_manager_->set_framebuffer_manager(NULL);
301     framebuffer_manager_.reset();
302   }
303
304   if (renderbuffer_manager_ != NULL) {
305     renderbuffer_manager_->Destroy(have_context);
306     renderbuffer_manager_.reset();
307   }
308
309   if (texture_manager_ != NULL) {
310     texture_manager_->Destroy(have_context);
311     texture_manager_.reset();
312   }
313
314   if (program_manager_ != NULL) {
315     program_manager_->Destroy(have_context);
316     program_manager_.reset();
317   }
318
319   if (shader_manager_ != NULL) {
320     shader_manager_->Destroy(have_context);
321     shader_manager_.reset();
322   }
323
324   memory_tracker_ = NULL;
325 }
326
327 IdAllocatorInterface* ContextGroup::GetIdAllocator(unsigned namespace_id) {
328   if (namespace_id >= arraysize(id_namespaces_))
329     return NULL;
330
331   return id_namespaces_[namespace_id].get();
332 }
333
334 uint32 ContextGroup::GetMemRepresented() const {
335   uint32 total = 0;
336   if (buffer_manager_.get())
337     total += buffer_manager_->mem_represented();
338   if (renderbuffer_manager_.get())
339     total += renderbuffer_manager_->mem_represented();
340   if (texture_manager_.get())
341     total += texture_manager_->mem_represented();
342   return total;
343 }
344
345 void ContextGroup::LoseContexts(GLenum reset_status) {
346   for (size_t ii = 0; ii < decoders_.size(); ++ii) {
347     if (decoders_[ii].get()) {
348       decoders_[ii]->LoseContext(reset_status);
349     }
350   }
351 }
352
353 ContextGroup::~ContextGroup() {
354   CHECK(!HaveContexts());
355 }
356
357 bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) {
358   GLint value = *v;
359   if (enforce_gl_minimums_) {
360     value = std::min(min_required, value);
361   }
362   *v = value;
363   return value >= min_required;
364 }
365
366 bool ContextGroup::CheckGLFeatureU(GLint min_required, uint32* v) {
367   GLint value = *v;
368   if (enforce_gl_minimums_) {
369     value = std::min(min_required, value);
370   }
371   *v = value;
372   return value >= min_required;
373 }
374
375 bool ContextGroup::QueryGLFeature(
376     GLenum pname, GLint min_required, GLint* v) {
377   GLint value = 0;
378   glGetIntegerv(pname, &value);
379   *v = value;
380   return CheckGLFeature(min_required, v);
381 }
382
383 bool ContextGroup::QueryGLFeatureU(
384     GLenum pname, GLint min_required, uint32* v) {
385   uint32 value = 0;
386   GetIntegerv(pname, &value);
387   bool result = CheckGLFeatureU(min_required, &value);
388   *v = value;
389   return result;
390 }
391
392 }  // namespace gles2
393 }  // namespace gpu