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