Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / gpu / command_buffer / service / context_group.cc
blob1cc8f243ce69b00e5d1cf3562bf87dd5b5ea179c
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/service/buffer_manager.h"
14 #include "gpu/command_buffer/service/framebuffer_manager.h"
15 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
16 #include "gpu/command_buffer/service/gpu_switches.h"
17 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
18 #include "gpu/command_buffer/service/memory_tracking.h"
19 #include "gpu/command_buffer/service/path_manager.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 "gpu/command_buffer/service/valuebuffer_manager.h"
26 #include "ui/gl/gl_implementation.h"
28 namespace gpu {
29 namespace gles2 {
31 ContextGroup::ContextGroup(
32 const scoped_refptr<MailboxManager>& mailbox_manager,
33 const scoped_refptr<MemoryTracker>& memory_tracker,
34 const scoped_refptr<ShaderTranslatorCache>& shader_translator_cache,
35 const scoped_refptr<FeatureInfo>& feature_info,
36 const scoped_refptr<SubscriptionRefSet>& subscription_ref_set,
37 const scoped_refptr<ValueStateMap>& pending_valuebuffer_state,
38 bool bind_generates_resource)
39 : context_type_(CONTEXT_TYPE_UNDEFINED),
40 mailbox_manager_(mailbox_manager),
41 memory_tracker_(memory_tracker),
42 shader_translator_cache_(shader_translator_cache),
43 subscription_ref_set_(subscription_ref_set),
44 pending_valuebuffer_state_(pending_valuebuffer_state),
45 enforce_gl_minimums_(base::CommandLine::ForCurrentProcess()->HasSwitch(
46 switches::kEnforceGLMinimums)),
47 bind_generates_resource_(bind_generates_resource),
48 max_vertex_attribs_(0u),
49 max_texture_units_(0u),
50 max_texture_image_units_(0u),
51 max_vertex_texture_image_units_(0u),
52 max_fragment_uniform_vectors_(0u),
53 max_varying_vectors_(0u),
54 max_vertex_uniform_vectors_(0u),
55 max_color_attachments_(1u),
56 max_draw_buffers_(1u),
57 program_cache_(NULL),
58 feature_info_(feature_info),
59 draw_buffer_(GL_BACK) {
61 if (!mailbox_manager_.get())
62 mailbox_manager_ = new MailboxManagerImpl;
63 if (!subscription_ref_set_.get())
64 subscription_ref_set_ = new SubscriptionRefSet();
65 if (!pending_valuebuffer_state_.get())
66 pending_valuebuffer_state_ = new ValueStateMap();
67 if (!feature_info.get())
68 feature_info_ = new FeatureInfo;
69 TransferBufferManager* manager = new TransferBufferManager();
70 transfer_buffer_manager_ = manager;
71 manager->Initialize();
75 static void GetIntegerv(GLenum pname, uint32* var) {
76 GLint value = 0;
77 glGetIntegerv(pname, &value);
78 *var = value;
81 // static
82 ContextGroup::ContextType ContextGroup::GetContextType(
83 unsigned webgl_version) {
84 switch (webgl_version) {
85 case 0:
86 return CONTEXT_TYPE_OTHER;
87 case 1:
88 return CONTEXT_TYPE_WEBGL1;
89 case 2:
90 return CONTEXT_TYPE_WEBGL2;
91 default:
92 return CONTEXT_TYPE_UNDEFINED;
96 bool ContextGroup::Initialize(
97 GLES2Decoder* decoder,
98 ContextGroup::ContextType context_type,
99 const DisallowedFeatures& disallowed_features) {
100 if (context_type == CONTEXT_TYPE_UNDEFINED) {
101 LOG(ERROR) << "ContextGroup::Initialize failed because of unknown "
102 << "context type.";
103 return false;
105 if (context_type_ == CONTEXT_TYPE_UNDEFINED) {
106 context_type_ = context_type;
107 } else if (context_type_ != context_type) {
108 LOG(ERROR) << "ContextGroup::Initialize failed because the type of "
109 << "the context does not fit with the group.";
110 return false;
113 // If we've already initialized the group just add the context.
114 if (HaveContexts()) {
115 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
116 return true;
119 if (!feature_info_->Initialize(disallowed_features)) {
120 LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
121 << "initialization failed.";
122 return false;
125 const GLint kMinRenderbufferSize = 512; // GL says 1 pixel!
126 GLint max_renderbuffer_size = 0;
127 if (!QueryGLFeature(
128 GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize,
129 &max_renderbuffer_size)) {
130 LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
131 << "renderbuffer size too small (" << max_renderbuffer_size
132 << ", should be " << kMinRenderbufferSize << ").";
133 return false;
135 GLint max_samples = 0;
136 if (feature_info_->feature_flags().chromium_framebuffer_multisample ||
137 feature_info_->feature_flags().multisampled_render_to_texture) {
138 if (feature_info_->feature_flags(
139 ).use_img_for_multisampled_render_to_texture) {
140 glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples);
141 } else {
142 glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
146 if (feature_info_->feature_flags().ext_draw_buffers) {
147 GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments_);
148 if (max_color_attachments_ < 1)
149 max_color_attachments_ = 1;
150 GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers_);
151 if (max_draw_buffers_ < 1)
152 max_draw_buffers_ = 1;
153 draw_buffer_ = GL_BACK;
156 buffer_manager_.reset(
157 new BufferManager(memory_tracker_.get(), feature_info_.get()));
158 framebuffer_manager_.reset(new FramebufferManager(
159 max_draw_buffers_, max_color_attachments_, context_type));
160 renderbuffer_manager_.reset(new RenderbufferManager(
161 memory_tracker_.get(), max_renderbuffer_size, max_samples,
162 feature_info_.get()));
163 shader_manager_.reset(new ShaderManager());
164 valuebuffer_manager_.reset(
165 new ValuebufferManager(subscription_ref_set_.get(),
166 pending_valuebuffer_state_.get()));
168 // Lookup GL things we need to know.
169 const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
170 if (!QueryGLFeatureU(
171 GL_MAX_VERTEX_ATTRIBS, kGLES2RequiredMinimumVertexAttribs,
172 &max_vertex_attribs_)) {
173 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
174 << "vertex attributes supported.";
175 return false;
178 const GLuint kGLES2RequiredMinimumTextureUnits = 8u;
179 if (!QueryGLFeatureU(
180 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kGLES2RequiredMinimumTextureUnits,
181 &max_texture_units_)) {
182 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
183 << "texture units supported.";
184 return false;
187 GLint max_texture_size = 0;
188 GLint max_cube_map_texture_size = 0;
189 GLint max_rectangle_texture_size = 0;
190 GLint max_3d_texture_size = 0;
192 const GLint kMinTextureSize = 2048; // GL actually says 64!?!?
193 // TODO(zmo): In ES3, max cubemap size is required to be at least 2048.
194 const GLint kMinCubeMapSize = 256; // GL actually says 16!?!?
195 const GLint kMinRectangleTextureSize = 64;
196 const GLint kMin3DTextureSize = 256;
198 if (!QueryGLFeature(GL_MAX_TEXTURE_SIZE, kMinTextureSize,
199 &max_texture_size) ||
200 !QueryGLFeature(GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize,
201 &max_cube_map_texture_size) ||
202 (feature_info_->gl_version_info().IsES3Capable() &&
203 !QueryGLFeature(GL_MAX_3D_TEXTURE_SIZE, kMin3DTextureSize,
204 &max_3d_texture_size)) ||
205 (feature_info_->feature_flags().arb_texture_rectangle &&
206 !QueryGLFeature(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB,
207 kMinRectangleTextureSize,
208 &max_rectangle_texture_size))) {
209 LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
210 << "texture size is too small.";
211 return false;
214 if (feature_info_->workarounds().max_texture_size) {
215 max_texture_size = std::min(
216 max_texture_size,
217 feature_info_->workarounds().max_texture_size);
218 max_rectangle_texture_size = std::min(
219 max_rectangle_texture_size,
220 feature_info_->workarounds().max_texture_size);
222 if (feature_info_->workarounds().max_cube_map_texture_size) {
223 max_cube_map_texture_size = std::min(
224 max_cube_map_texture_size,
225 feature_info_->workarounds().max_cube_map_texture_size);
228 texture_manager_.reset(new TextureManager(memory_tracker_.get(),
229 feature_info_.get(),
230 max_texture_size,
231 max_cube_map_texture_size,
232 max_rectangle_texture_size,
233 max_3d_texture_size,
234 bind_generates_resource_));
235 texture_manager_->set_framebuffer_manager(framebuffer_manager_.get());
237 const GLint kMinTextureImageUnits = 8;
238 const GLint kMinVertexTextureImageUnits = 0;
239 if (!QueryGLFeatureU(
240 GL_MAX_TEXTURE_IMAGE_UNITS, kMinTextureImageUnits,
241 &max_texture_image_units_) ||
242 !QueryGLFeatureU(
243 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits,
244 &max_vertex_texture_image_units_)) {
245 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
246 << "texture units.";
247 return false;
250 if (feature_info_->gl_version_info().BehavesLikeGLES()) {
251 GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
252 &max_fragment_uniform_vectors_);
253 GetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors_);
254 GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &max_vertex_uniform_vectors_);
255 } else {
256 GetIntegerv(
257 GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max_fragment_uniform_vectors_);
258 max_fragment_uniform_vectors_ /= 4;
259 GetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_vectors_);
260 max_varying_vectors_ /= 4;
261 GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_vertex_uniform_vectors_);
262 max_vertex_uniform_vectors_ /= 4;
265 const GLint kMinFragmentUniformVectors = 16;
266 const GLint kMinVaryingVectors = 8;
267 const GLint kMinVertexUniformVectors = 128;
268 if (!CheckGLFeatureU(
269 kMinFragmentUniformVectors, &max_fragment_uniform_vectors_) ||
270 !CheckGLFeatureU(kMinVaryingVectors, &max_varying_vectors_) ||
271 !CheckGLFeatureU(
272 kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) {
273 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
274 << "uniforms or varyings supported.";
275 return false;
278 // Some shaders in Skia need more than the min available vertex and
279 // fragment shader uniform vectors in case of OSMesa GL Implementation
280 if (feature_info_->workarounds().max_fragment_uniform_vectors) {
281 max_fragment_uniform_vectors_ = std::min(
282 max_fragment_uniform_vectors_,
283 static_cast<uint32>(
284 feature_info_->workarounds().max_fragment_uniform_vectors));
286 if (feature_info_->workarounds().max_varying_vectors) {
287 max_varying_vectors_ = std::min(
288 max_varying_vectors_,
289 static_cast<uint32>(feature_info_->workarounds().max_varying_vectors));
291 if (feature_info_->workarounds().max_vertex_uniform_vectors) {
292 max_vertex_uniform_vectors_ =
293 std::min(max_vertex_uniform_vectors_,
294 static_cast<uint32>(
295 feature_info_->workarounds().max_vertex_uniform_vectors));
298 path_manager_.reset(new PathManager());
300 program_manager_.reset(new ProgramManager(
301 program_cache_, max_varying_vectors_));
303 if (!texture_manager_->Initialize()) {
304 LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
305 << "failed to initialize.";
306 return false;
309 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
310 return true;
313 namespace {
315 bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) {
316 return !decoder.get();
319 template <typename T>
320 class WeakPtrEquals {
321 public:
322 explicit WeakPtrEquals(T* t) : t_(t) {}
324 bool operator()(const base::WeakPtr<T>& t) {
325 return t.get() == t_;
328 private:
329 T* const t_;
332 } // namespace anonymous
334 bool ContextGroup::HaveContexts() {
335 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull),
336 decoders_.end());
337 return !decoders_.empty();
340 void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) {
341 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(),
342 WeakPtrEquals<gles2::GLES2Decoder>(decoder)),
343 decoders_.end());
344 // If we still have contexts do nothing.
345 if (HaveContexts()) {
346 return;
349 if (buffer_manager_ != NULL) {
350 buffer_manager_->Destroy(have_context);
351 buffer_manager_.reset();
354 if (framebuffer_manager_ != NULL) {
355 framebuffer_manager_->Destroy(have_context);
356 if (texture_manager_)
357 texture_manager_->set_framebuffer_manager(NULL);
358 framebuffer_manager_.reset();
361 if (renderbuffer_manager_ != NULL) {
362 renderbuffer_manager_->Destroy(have_context);
363 renderbuffer_manager_.reset();
366 if (texture_manager_ != NULL) {
367 texture_manager_->Destroy(have_context);
368 texture_manager_.reset();
371 if (path_manager_ != NULL) {
372 path_manager_->Destroy(have_context);
373 path_manager_.reset();
376 if (program_manager_ != NULL) {
377 program_manager_->Destroy(have_context);
378 program_manager_.reset();
381 if (shader_manager_ != NULL) {
382 shader_manager_->Destroy(have_context);
383 shader_manager_.reset();
386 if (valuebuffer_manager_ != NULL) {
387 valuebuffer_manager_->Destroy();
388 valuebuffer_manager_.reset();
391 memory_tracker_ = NULL;
394 uint32 ContextGroup::GetMemRepresented() const {
395 uint32 total = 0;
396 if (buffer_manager_.get())
397 total += buffer_manager_->mem_represented();
398 if (renderbuffer_manager_.get())
399 total += renderbuffer_manager_->mem_represented();
400 if (texture_manager_.get())
401 total += texture_manager_->mem_represented();
402 return total;
405 void ContextGroup::LoseContexts(error::ContextLostReason reason) {
406 for (size_t ii = 0; ii < decoders_.size(); ++ii) {
407 if (decoders_[ii].get()) {
408 decoders_[ii]->MarkContextLost(reason);
413 ContextGroup::~ContextGroup() {
414 CHECK(!HaveContexts());
417 bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) {
418 GLint value = *v;
419 if (enforce_gl_minimums_) {
420 value = std::min(min_required, value);
422 *v = value;
423 return value >= min_required;
426 bool ContextGroup::CheckGLFeatureU(GLint min_required, uint32* v) {
427 GLint value = *v;
428 if (enforce_gl_minimums_) {
429 value = std::min(min_required, value);
431 *v = value;
432 return value >= min_required;
435 bool ContextGroup::QueryGLFeature(
436 GLenum pname, GLint min_required, GLint* v) {
437 GLint value = 0;
438 glGetIntegerv(pname, &value);
439 *v = value;
440 return CheckGLFeature(min_required, v);
443 bool ContextGroup::QueryGLFeatureU(
444 GLenum pname, GLint min_required, uint32* v) {
445 uint32 value = 0;
446 GetIntegerv(pname, &value);
447 bool result = CheckGLFeatureU(min_required, &value);
448 *v = value;
449 return result;
452 bool ContextGroup::GetBufferServiceId(
453 GLuint client_id, GLuint* service_id) const {
454 Buffer* buffer = buffer_manager_->GetBuffer(client_id);
455 if (!buffer)
456 return false;
457 *service_id = buffer->service_id();
458 return true;
461 } // namespace gles2
462 } // namespace gpu