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.
5 #include "gpu/command_buffer/service/context_group.h"
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/image_manager.h"
19 #include "gpu/command_buffer/service/mailbox_manager.h"
20 #include "gpu/command_buffer/service/memory_tracking.h"
21 #include "gpu/command_buffer/service/program_manager.h"
22 #include "gpu/command_buffer/service/renderbuffer_manager.h"
23 #include "gpu/command_buffer/service/shader_manager.h"
24 #include "gpu/command_buffer/service/texture_manager.h"
25 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
26 #include "ui/gl/gl_implementation.h"
31 ContextGroup::ContextGroup(
32 MailboxManager* mailbox_manager,
33 ImageManager* image_manager,
34 MemoryTracker* memory_tracker,
35 StreamTextureManager* stream_texture_manager,
36 bool bind_generates_resource)
37 : mailbox_manager_(mailbox_manager ? mailbox_manager : new MailboxManager),
38 image_manager_(image_manager ? image_manager : new ImageManager),
39 memory_tracker_(memory_tracker),
40 stream_texture_manager_(stream_texture_manager),
41 enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch(
42 switches::kEnforceGLMinimums)),
43 bind_generates_resource_(bind_generates_resource),
44 max_vertex_attribs_(0u),
45 max_texture_units_(0u),
46 max_texture_image_units_(0u),
47 max_vertex_texture_image_units_(0u),
48 max_fragment_uniform_vectors_(0u),
49 max_varying_vectors_(0u),
50 max_vertex_uniform_vectors_(0u),
51 max_color_attachments_(1u),
52 max_draw_buffers_(1u),
54 feature_info_(new FeatureInfo()),
55 draw_buffer_(GL_BACK) {
57 TransferBufferManager* manager = new TransferBufferManager();
58 transfer_buffer_manager_.reset(manager);
59 manager->Initialize();
62 id_namespaces_[id_namespaces::kBuffers].reset(new IdAllocator);
63 id_namespaces_[id_namespaces::kFramebuffers].reset(new IdAllocator);
64 id_namespaces_[id_namespaces::kProgramsAndShaders].reset(
65 new NonReusedIdAllocator);
66 id_namespaces_[id_namespaces::kRenderbuffers].reset(new IdAllocator);
67 id_namespaces_[id_namespaces::kTextures].reset(new IdAllocator);
68 id_namespaces_[id_namespaces::kQueries].reset(new IdAllocator);
69 id_namespaces_[id_namespaces::kVertexArrays].reset(new IdAllocator);
72 static void GetIntegerv(GLenum pname, uint32* var) {
74 glGetIntegerv(pname, &value);
78 bool ContextGroup::Initialize(
79 GLES2Decoder* decoder,
80 const DisallowedFeatures& disallowed_features) {
81 // If we've already initialized the group just add the context.
83 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
87 if (!feature_info_->Initialize(disallowed_features)) {
88 LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
89 << "initialization failed.";
93 const GLint kMinRenderbufferSize = 512; // GL says 1 pixel!
94 GLint max_renderbuffer_size = 0;
96 GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize,
97 &max_renderbuffer_size)) {
98 LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
99 << "renderbuffer size too small.";
102 GLint max_samples = 0;
103 if (feature_info_->feature_flags().chromium_framebuffer_multisample ||
104 feature_info_->feature_flags().multisampled_render_to_texture) {
105 if (feature_info_->feature_flags(
106 ).use_img_for_multisampled_render_to_texture) {
107 glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples);
109 glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
113 if (feature_info_->feature_flags().ext_draw_buffers) {
114 GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments_);
115 if (max_color_attachments_ < 1)
116 max_color_attachments_ = 1;
117 GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers_);
118 if (max_draw_buffers_ < 1)
119 max_draw_buffers_ = 1;
120 draw_buffer_ = GL_BACK;
123 const bool depth24_supported = feature_info_->feature_flags().oes_depth24;
125 buffer_manager_.reset(
126 new BufferManager(memory_tracker_.get(), feature_info_.get()));
127 framebuffer_manager_.reset(
128 new FramebufferManager(max_draw_buffers_, max_color_attachments_));
129 renderbuffer_manager_.reset(new RenderbufferManager(
130 memory_tracker_.get(), max_renderbuffer_size, max_samples,
132 shader_manager_.reset(new ShaderManager());
134 // Lookup GL things we need to know.
135 const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
136 if (!QueryGLFeatureU(
137 GL_MAX_VERTEX_ATTRIBS, kGLES2RequiredMinimumVertexAttribs,
138 &max_vertex_attribs_)) {
139 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
140 << "vertex attributes supported.";
144 const GLuint kGLES2RequiredMinimumTextureUnits = 8u;
145 if (!QueryGLFeatureU(
146 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kGLES2RequiredMinimumTextureUnits,
147 &max_texture_units_)) {
148 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
149 << "texture units supported.";
153 GLint max_texture_size = 0;
154 GLint max_cube_map_texture_size = 0;
155 const GLint kMinTextureSize = 2048; // GL actually says 64!?!?
156 const GLint kMinCubeMapSize = 256; // GL actually says 16!?!?
158 GL_MAX_TEXTURE_SIZE, kMinTextureSize, &max_texture_size) ||
160 GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize,
161 &max_cube_map_texture_size)) {
162 LOG(ERROR) << "ContextGroup::Initialize failed because maximum texture size"
167 if (feature_info_->workarounds().max_texture_size) {
168 max_texture_size = std::min(
169 max_texture_size, feature_info_->workarounds().max_texture_size);
171 if (feature_info_->workarounds().max_cube_map_texture_size) {
172 max_cube_map_texture_size = std::min(
173 max_cube_map_texture_size,
174 feature_info_->workarounds().max_cube_map_texture_size);
177 texture_manager_.reset(new TextureManager(memory_tracker_.get(),
180 max_cube_map_texture_size));
181 texture_manager_->set_framebuffer_manager(framebuffer_manager_.get());
182 texture_manager_->set_stream_texture_manager(stream_texture_manager_);
184 const GLint kMinTextureImageUnits = 8;
185 const GLint kMinVertexTextureImageUnits = 0;
186 if (!QueryGLFeatureU(
187 GL_MAX_TEXTURE_IMAGE_UNITS, kMinTextureImageUnits,
188 &max_texture_image_units_) ||
190 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits,
191 &max_vertex_texture_image_units_)) {
192 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
197 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
198 GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
199 &max_fragment_uniform_vectors_);
200 GetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors_);
201 GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &max_vertex_uniform_vectors_);
204 GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max_fragment_uniform_vectors_);
205 max_fragment_uniform_vectors_ /= 4;
206 GetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_vectors_);
207 max_varying_vectors_ /= 4;
208 GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_vertex_uniform_vectors_);
209 max_vertex_uniform_vectors_ /= 4;
212 const GLint kMinFragmentUniformVectors = 16;
213 const GLint kMinVaryingVectors = 8;
214 const GLint kMinVertexUniformVectors = 128;
215 if (!CheckGLFeatureU(
216 kMinFragmentUniformVectors, &max_fragment_uniform_vectors_) ||
217 !CheckGLFeatureU(kMinVaryingVectors, &max_varying_vectors_) ||
219 kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) {
220 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
221 << "uniforms or varyings supported.";
225 // TODO(gman): Use workarounds similar to max_texture_size above to implement.
226 if (gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL) {
227 // Some shaders in Skia needed more than the min.
228 max_fragment_uniform_vectors_ =
229 std::min(static_cast<uint32>(kMinFragmentUniformVectors * 2),
230 max_fragment_uniform_vectors_);
231 max_varying_vectors_ =
232 std::min(static_cast<uint32>(kMinVaryingVectors * 2),
233 max_varying_vectors_);
234 max_vertex_uniform_vectors_ =
235 std::min(static_cast<uint32>(kMinVertexUniformVectors * 2),
236 max_vertex_uniform_vectors_);
239 program_manager_.reset(new ProgramManager(
240 program_cache_, max_varying_vectors_));
242 if (!texture_manager_->Initialize()) {
243 LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
244 << "failed to initialize.";
248 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
254 bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) {
255 return !decoder.get();
258 template <typename T>
259 class WeakPtrEquals {
261 explicit WeakPtrEquals(T* t) : t_(t) {}
263 bool operator()(const base::WeakPtr<T>& t) {
264 return t.get() == t_;
271 } // namespace anonymous
273 bool ContextGroup::HaveContexts() {
274 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull),
276 return !decoders_.empty();
279 void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) {
280 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(),
281 WeakPtrEquals<gles2::GLES2Decoder>(decoder)),
283 // If we still have contexts do nothing.
284 if (HaveContexts()) {
288 if (buffer_manager_ != NULL) {
289 buffer_manager_->Destroy(have_context);
290 buffer_manager_.reset();
293 if (framebuffer_manager_ != NULL) {
294 framebuffer_manager_->Destroy(have_context);
295 if (texture_manager_)
296 texture_manager_->set_framebuffer_manager(NULL);
297 framebuffer_manager_.reset();
300 if (renderbuffer_manager_ != NULL) {
301 renderbuffer_manager_->Destroy(have_context);
302 renderbuffer_manager_.reset();
305 if (texture_manager_ != NULL) {
306 texture_manager_->Destroy(have_context);
307 texture_manager_.reset();
310 if (program_manager_ != NULL) {
311 program_manager_->Destroy(have_context);
312 program_manager_.reset();
315 if (shader_manager_ != NULL) {
316 shader_manager_->Destroy(have_context);
317 shader_manager_.reset();
320 memory_tracker_ = NULL;
321 stream_texture_manager_ = NULL;
324 IdAllocatorInterface* ContextGroup::GetIdAllocator(unsigned namespace_id) {
325 if (namespace_id >= arraysize(id_namespaces_))
328 return id_namespaces_[namespace_id].get();
331 uint32 ContextGroup::GetMemRepresented() const {
333 if (buffer_manager_.get())
334 total += buffer_manager_->mem_represented();
335 if (renderbuffer_manager_.get())
336 total += renderbuffer_manager_->mem_represented();
337 if (texture_manager_.get())
338 total += texture_manager_->mem_represented();
342 void ContextGroup::LoseContexts(GLenum reset_status) {
343 for (size_t ii = 0; ii < decoders_.size(); ++ii) {
344 if (decoders_[ii].get()) {
345 decoders_[ii]->LoseContext(reset_status);
350 ContextGroup::~ContextGroup() {
351 CHECK(!HaveContexts());
354 bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) {
356 if (enforce_gl_minimums_) {
357 value = std::min(min_required, value);
360 return value >= min_required;
363 bool ContextGroup::CheckGLFeatureU(GLint min_required, uint32* v) {
365 if (enforce_gl_minimums_) {
366 value = std::min(min_required, value);
369 return value >= min_required;
372 bool ContextGroup::QueryGLFeature(
373 GLenum pname, GLint min_required, GLint* v) {
375 glGetIntegerv(pname, &value);
377 return CheckGLFeature(min_required, v);
380 bool ContextGroup::QueryGLFeatureU(
381 GLenum pname, GLint min_required, uint32* v) {
383 GetIntegerv(pname, &value);
384 bool result = CheckGLFeatureU(min_required, &value);