Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / gpu / command_buffer / service / context_group.cc
blobfc42c1dd6d8f85fbfdbc2868a1bd97379ec01c51
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"
7 #include <algorithm>
8 #include <string>
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"
27 namespace gpu {
28 namespace gles2 {
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) {
55 TransferBufferManager* manager = new TransferBufferManager();
56 transfer_buffer_manager_.reset(manager);
57 manager->Initialize();
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);
70 static void GetIntegerv(GLenum pname, uint32* var) {
71 GLint value = 0;
72 glGetIntegerv(pname, &value);
73 *var = value;
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;
85 if (!feature_info_->Initialize(disallowed_features)) {
86 LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
87 << "initialization failed.";
88 return false;
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;
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);
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;
121 const bool depth24_supported = feature_info_->feature_flags().oes_depth24;
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());
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;
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;
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;
165 if (feature_info_->workarounds().max_texture_size) {
166 max_texture_size = std::min(
167 max_texture_size, feature_info_->workarounds().max_texture_size);
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);
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());
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;
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;
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;
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));
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));
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));
243 program_manager_.reset(new ProgramManager(
244 program_cache_, max_varying_vectors_));
246 if (!texture_manager_->Initialize()) {
247 LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
248 << "failed to initialize.";
249 return false;
252 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
253 return true;
256 namespace {
258 bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) {
259 return !decoder.get();
262 template <typename T>
263 class WeakPtrEquals {
264 public:
265 explicit WeakPtrEquals(T* t) : t_(t) {}
267 bool operator()(const base::WeakPtr<T>& t) {
268 return t.get() == t_;
271 private:
272 T* const t_;
275 } // namespace anonymous
277 bool ContextGroup::HaveContexts() {
278 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull),
279 decoders_.end());
280 return !decoders_.empty();
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;
292 if (buffer_manager_ != NULL) {
293 buffer_manager_->Destroy(have_context);
294 buffer_manager_.reset();
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();
304 if (renderbuffer_manager_ != NULL) {
305 renderbuffer_manager_->Destroy(have_context);
306 renderbuffer_manager_.reset();
309 if (texture_manager_ != NULL) {
310 texture_manager_->Destroy(have_context);
311 texture_manager_.reset();
314 if (program_manager_ != NULL) {
315 program_manager_->Destroy(have_context);
316 program_manager_.reset();
319 if (shader_manager_ != NULL) {
320 shader_manager_->Destroy(have_context);
321 shader_manager_.reset();
324 memory_tracker_ = NULL;
327 IdAllocatorInterface* ContextGroup::GetIdAllocator(unsigned namespace_id) {
328 if (namespace_id >= arraysize(id_namespaces_))
329 return NULL;
331 return id_namespaces_[namespace_id].get();
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;
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);
353 ContextGroup::~ContextGroup() {
354 CHECK(!HaveContexts());
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);
362 *v = value;
363 return value >= min_required;
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);
371 *v = value;
372 return value >= min_required;
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);
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;
392 } // namespace gles2
393 } // namespace gpu