Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / gpu / command_buffer / service / context_group.cc
blob98ebbdbd033b0e93339a1395fcb08dde3193e89d
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/program_manager.h"
20 #include "gpu/command_buffer/service/renderbuffer_manager.h"
21 #include "gpu/command_buffer/service/shader_manager.h"
22 #include "gpu/command_buffer/service/texture_manager.h"
23 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
24 #include "gpu/command_buffer/service/valuebuffer_manager.h"
25 #include "ui/gl/gl_implementation.h"
27 namespace gpu {
28 namespace gles2 {
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 const scoped_refptr<SubscriptionRefSet>& subscription_ref_set,
36 const scoped_refptr<ValueStateMap>& pending_valuebuffer_state,
37 bool bind_generates_resource)
38 : mailbox_manager_(mailbox_manager),
39 memory_tracker_(memory_tracker),
40 shader_translator_cache_(shader_translator_cache),
41 subscription_ref_set_(subscription_ref_set),
42 pending_valuebuffer_state_(pending_valuebuffer_state),
43 enforce_gl_minimums_(base::CommandLine::ForCurrentProcess()->HasSwitch(
44 switches::kEnforceGLMinimums)),
45 bind_generates_resource_(bind_generates_resource),
46 max_vertex_attribs_(0u),
47 max_texture_units_(0u),
48 max_texture_image_units_(0u),
49 max_vertex_texture_image_units_(0u),
50 max_fragment_uniform_vectors_(0u),
51 max_varying_vectors_(0u),
52 max_vertex_uniform_vectors_(0u),
53 max_color_attachments_(1u),
54 max_draw_buffers_(1u),
55 program_cache_(NULL),
56 feature_info_(feature_info),
57 draw_buffer_(GL_BACK) {
59 if (!mailbox_manager_.get())
60 mailbox_manager_ = new MailboxManagerImpl;
61 if (!subscription_ref_set_.get())
62 subscription_ref_set_ = new SubscriptionRefSet();
63 if (!pending_valuebuffer_state_.get())
64 pending_valuebuffer_state_ = new ValueStateMap();
65 if (!feature_info.get())
66 feature_info_ = new FeatureInfo;
67 TransferBufferManager* manager = new TransferBufferManager();
68 transfer_buffer_manager_.reset(manager);
69 manager->Initialize();
73 static void GetIntegerv(GLenum pname, uint32* var) {
74 GLint value = 0;
75 glGetIntegerv(pname, &value);
76 *var = value;
79 bool ContextGroup::Initialize(
80 GLES2Decoder* decoder,
81 const DisallowedFeatures& disallowed_features) {
82 // If we've already initialized the group just add the context.
83 if (HaveContexts()) {
84 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
85 return true;
88 if (!feature_info_->Initialize(disallowed_features)) {
89 LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
90 << "initialization failed.";
91 return false;
94 const GLint kMinRenderbufferSize = 512; // GL says 1 pixel!
95 GLint max_renderbuffer_size = 0;
96 if (!QueryGLFeature(
97 GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize,
98 &max_renderbuffer_size)) {
99 LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
100 << "renderbuffer size too small (" << max_renderbuffer_size
101 << ", should be " << kMinRenderbufferSize << ").";
102 return false;
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);
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;
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,
131 feature_info_.get()));
132 shader_manager_.reset(new ShaderManager());
133 valuebuffer_manager_.reset(
134 new ValuebufferManager(subscription_ref_set_.get(),
135 pending_valuebuffer_state_.get()));
137 // Lookup GL things we need to know.
138 const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
139 if (!QueryGLFeatureU(
140 GL_MAX_VERTEX_ATTRIBS, kGLES2RequiredMinimumVertexAttribs,
141 &max_vertex_attribs_)) {
142 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
143 << "vertex attributes supported.";
144 return false;
147 const GLuint kGLES2RequiredMinimumTextureUnits = 8u;
148 if (!QueryGLFeatureU(
149 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kGLES2RequiredMinimumTextureUnits,
150 &max_texture_units_)) {
151 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
152 << "texture units supported.";
153 return false;
156 GLint max_texture_size = 0;
157 GLint max_cube_map_texture_size = 0;
158 GLint max_rectangle_texture_size = 0;
159 GLint max_3d_texture_size = 0;
161 const GLint kMinTextureSize = 2048; // GL actually says 64!?!?
162 // TODO(zmo): In ES3, max cubemap size is required to be at least 2048.
163 const GLint kMinCubeMapSize = 256; // GL actually says 16!?!?
164 const GLint kMinRectangleTextureSize = 64;
165 const GLint kMin3DTextureSize = 256;
167 if (!QueryGLFeature(GL_MAX_TEXTURE_SIZE, kMinTextureSize,
168 &max_texture_size) ||
169 !QueryGLFeature(GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize,
170 &max_cube_map_texture_size) ||
171 (feature_info_->gl_version_info().IsES3Capable() &&
172 !QueryGLFeature(GL_MAX_3D_TEXTURE_SIZE, kMin3DTextureSize,
173 &max_3d_texture_size)) ||
174 (feature_info_->feature_flags().arb_texture_rectangle &&
175 !QueryGLFeature(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB,
176 kMinRectangleTextureSize,
177 &max_rectangle_texture_size))) {
178 LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
179 << "texture size is too small.";
180 return false;
183 if (feature_info_->workarounds().max_texture_size) {
184 max_texture_size = std::min(
185 max_texture_size,
186 feature_info_->workarounds().max_texture_size);
187 max_rectangle_texture_size = std::min(
188 max_rectangle_texture_size,
189 feature_info_->workarounds().max_texture_size);
191 if (feature_info_->workarounds().max_cube_map_texture_size) {
192 max_cube_map_texture_size = std::min(
193 max_cube_map_texture_size,
194 feature_info_->workarounds().max_cube_map_texture_size);
197 texture_manager_.reset(new TextureManager(memory_tracker_.get(),
198 feature_info_.get(),
199 max_texture_size,
200 max_cube_map_texture_size,
201 max_rectangle_texture_size,
202 max_3d_texture_size,
203 bind_generates_resource_));
204 texture_manager_->set_framebuffer_manager(framebuffer_manager_.get());
206 const GLint kMinTextureImageUnits = 8;
207 const GLint kMinVertexTextureImageUnits = 0;
208 if (!QueryGLFeatureU(
209 GL_MAX_TEXTURE_IMAGE_UNITS, kMinTextureImageUnits,
210 &max_texture_image_units_) ||
211 !QueryGLFeatureU(
212 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits,
213 &max_vertex_texture_image_units_)) {
214 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
215 << "texture units.";
216 return false;
219 if (feature_info_->gl_version_info().BehavesLikeGLES()) {
220 GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
221 &max_fragment_uniform_vectors_);
222 GetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors_);
223 GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &max_vertex_uniform_vectors_);
224 } else {
225 GetIntegerv(
226 GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max_fragment_uniform_vectors_);
227 max_fragment_uniform_vectors_ /= 4;
228 GetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_vectors_);
229 max_varying_vectors_ /= 4;
230 GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_vertex_uniform_vectors_);
231 max_vertex_uniform_vectors_ /= 4;
234 const GLint kMinFragmentUniformVectors = 16;
235 const GLint kMinVaryingVectors = 8;
236 const GLint kMinVertexUniformVectors = 128;
237 if (!CheckGLFeatureU(
238 kMinFragmentUniformVectors, &max_fragment_uniform_vectors_) ||
239 !CheckGLFeatureU(kMinVaryingVectors, &max_varying_vectors_) ||
240 !CheckGLFeatureU(
241 kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) {
242 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
243 << "uniforms or varyings supported.";
244 return false;
247 // Some shaders in Skia need more than the min available vertex and
248 // fragment shader uniform vectors in case of OSMesa GL Implementation
249 if (feature_info_->workarounds().max_fragment_uniform_vectors) {
250 max_fragment_uniform_vectors_ = std::min(
251 max_fragment_uniform_vectors_,
252 static_cast<uint32>(
253 feature_info_->workarounds().max_fragment_uniform_vectors));
255 if (feature_info_->workarounds().max_varying_vectors) {
256 max_varying_vectors_ = std::min(
257 max_varying_vectors_,
258 static_cast<uint32>(feature_info_->workarounds().max_varying_vectors));
260 if (feature_info_->workarounds().max_vertex_uniform_vectors) {
261 max_vertex_uniform_vectors_ =
262 std::min(max_vertex_uniform_vectors_,
263 static_cast<uint32>(
264 feature_info_->workarounds().max_vertex_uniform_vectors));
267 program_manager_.reset(new ProgramManager(
268 program_cache_, max_varying_vectors_));
270 if (!texture_manager_->Initialize()) {
271 LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
272 << "failed to initialize.";
273 return false;
276 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
277 return true;
280 namespace {
282 bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) {
283 return !decoder.get();
286 template <typename T>
287 class WeakPtrEquals {
288 public:
289 explicit WeakPtrEquals(T* t) : t_(t) {}
291 bool operator()(const base::WeakPtr<T>& t) {
292 return t.get() == t_;
295 private:
296 T* const t_;
299 } // namespace anonymous
301 bool ContextGroup::HaveContexts() {
302 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull),
303 decoders_.end());
304 return !decoders_.empty();
307 void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) {
308 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(),
309 WeakPtrEquals<gles2::GLES2Decoder>(decoder)),
310 decoders_.end());
311 // If we still have contexts do nothing.
312 if (HaveContexts()) {
313 return;
316 if (buffer_manager_ != NULL) {
317 buffer_manager_->Destroy(have_context);
318 buffer_manager_.reset();
321 if (framebuffer_manager_ != NULL) {
322 framebuffer_manager_->Destroy(have_context);
323 if (texture_manager_)
324 texture_manager_->set_framebuffer_manager(NULL);
325 framebuffer_manager_.reset();
328 if (renderbuffer_manager_ != NULL) {
329 renderbuffer_manager_->Destroy(have_context);
330 renderbuffer_manager_.reset();
333 if (texture_manager_ != NULL) {
334 texture_manager_->Destroy(have_context);
335 texture_manager_.reset();
338 if (program_manager_ != NULL) {
339 program_manager_->Destroy(have_context);
340 program_manager_.reset();
343 if (shader_manager_ != NULL) {
344 shader_manager_->Destroy(have_context);
345 shader_manager_.reset();
348 if (valuebuffer_manager_ != NULL) {
349 valuebuffer_manager_->Destroy();
350 valuebuffer_manager_.reset();
353 memory_tracker_ = NULL;
356 uint32 ContextGroup::GetMemRepresented() const {
357 uint32 total = 0;
358 if (buffer_manager_.get())
359 total += buffer_manager_->mem_represented();
360 if (renderbuffer_manager_.get())
361 total += renderbuffer_manager_->mem_represented();
362 if (texture_manager_.get())
363 total += texture_manager_->mem_represented();
364 return total;
367 void ContextGroup::LoseContexts(error::ContextLostReason reason) {
368 for (size_t ii = 0; ii < decoders_.size(); ++ii) {
369 if (decoders_[ii].get()) {
370 decoders_[ii]->MarkContextLost(reason);
375 ContextGroup::~ContextGroup() {
376 CHECK(!HaveContexts());
379 bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) {
380 GLint value = *v;
381 if (enforce_gl_minimums_) {
382 value = std::min(min_required, value);
384 *v = value;
385 return value >= min_required;
388 bool ContextGroup::CheckGLFeatureU(GLint min_required, uint32* v) {
389 GLint value = *v;
390 if (enforce_gl_minimums_) {
391 value = std::min(min_required, value);
393 *v = value;
394 return value >= min_required;
397 bool ContextGroup::QueryGLFeature(
398 GLenum pname, GLint min_required, GLint* v) {
399 GLint value = 0;
400 glGetIntegerv(pname, &value);
401 *v = value;
402 return CheckGLFeature(min_required, v);
405 bool ContextGroup::QueryGLFeatureU(
406 GLenum pname, GLint min_required, uint32* v) {
407 uint32 value = 0;
408 GetIntegerv(pname, &value);
409 bool result = CheckGLFeatureU(min_required, &value);
410 *v = value;
411 return result;
414 bool ContextGroup::GetBufferServiceId(
415 GLuint client_id, GLuint* service_id) const {
416 Buffer* buffer = buffer_manager_->GetBuffer(client_id);
417 if (!buffer)
418 return false;
419 *service_id = buffer->service_id();
420 return true;
423 } // namespace gles2
424 } // namespace gpu