cc: Use worker context for one-copy tile initialization.
[chromium-blink-merge.git] / gpu / command_buffer / service / context_group.cc
blob41a739b774149b70c096599783fe4968e66401e3
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 "gpu/command_buffer/common/value_state.h"
12 #include "gpu/command_buffer/service/buffer_manager.h"
13 #include "gpu/command_buffer/service/framebuffer_manager.h"
14 #include "gpu/command_buffer/service/gpu_switches.h"
15 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
16 #include "gpu/command_buffer/service/path_manager.h"
17 #include "gpu/command_buffer/service/program_manager.h"
18 #include "gpu/command_buffer/service/renderbuffer_manager.h"
19 #include "gpu/command_buffer/service/shader_manager.h"
20 #include "gpu/command_buffer/service/texture_manager.h"
21 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
22 #include "gpu/command_buffer/service/valuebuffer_manager.h"
23 #include "ui/gl/gl_bindings.h"
24 #include "ui/gl/gl_version_info.h"
26 namespace gpu {
27 namespace gles2 {
29 ContextGroup::ContextGroup(
30 const scoped_refptr<MailboxManager>& mailbox_manager,
31 const scoped_refptr<MemoryTracker>& memory_tracker,
32 const scoped_refptr<ShaderTranslatorCache>& shader_translator_cache,
33 const scoped_refptr<FeatureInfo>& feature_info,
34 const scoped_refptr<SubscriptionRefSet>& subscription_ref_set,
35 const scoped_refptr<ValueStateMap>& pending_valuebuffer_state,
36 bool bind_generates_resource)
37 : context_type_(CONTEXT_TYPE_UNDEFINED),
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_ = manager;
69 manager->Initialize();
73 static void GetIntegerv(GLenum pname, uint32* var) {
74 GLint value = 0;
75 glGetIntegerv(pname, &value);
76 *var = value;
79 // static
80 ContextGroup::ContextType ContextGroup::GetContextType(
81 unsigned webgl_version) {
82 switch (webgl_version) {
83 case 0:
84 return CONTEXT_TYPE_OTHER;
85 case 1:
86 return CONTEXT_TYPE_WEBGL1;
87 case 2:
88 return CONTEXT_TYPE_WEBGL2;
89 default:
90 return CONTEXT_TYPE_UNDEFINED;
94 bool ContextGroup::Initialize(
95 GLES2Decoder* decoder,
96 ContextGroup::ContextType context_type,
97 const DisallowedFeatures& disallowed_features) {
98 if (context_type == CONTEXT_TYPE_UNDEFINED) {
99 LOG(ERROR) << "ContextGroup::Initialize failed because of unknown "
100 << "context type.";
101 return false;
103 if (context_type_ == CONTEXT_TYPE_UNDEFINED) {
104 context_type_ = context_type;
105 } else if (context_type_ != context_type) {
106 LOG(ERROR) << "ContextGroup::Initialize failed because the type of "
107 << "the context does not fit with the group.";
108 return false;
111 // If we've already initialized the group just add the context.
112 if (HaveContexts()) {
113 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
114 return true;
117 if (!feature_info_->Initialize(disallowed_features)) {
118 LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
119 << "initialization failed.";
120 return false;
123 const GLint kMinRenderbufferSize = 512; // GL says 1 pixel!
124 GLint max_renderbuffer_size = 0;
125 if (!QueryGLFeature(
126 GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize,
127 &max_renderbuffer_size)) {
128 LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
129 << "renderbuffer size too small (" << max_renderbuffer_size
130 << ", should be " << kMinRenderbufferSize << ").";
131 return false;
133 GLint max_samples = 0;
134 if (feature_info_->feature_flags().chromium_framebuffer_multisample ||
135 feature_info_->feature_flags().multisampled_render_to_texture) {
136 if (feature_info_->feature_flags(
137 ).use_img_for_multisampled_render_to_texture) {
138 glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples);
139 } else {
140 glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
144 if (feature_info_->feature_flags().ext_draw_buffers) {
145 GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments_);
146 if (max_color_attachments_ < 1)
147 max_color_attachments_ = 1;
148 GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers_);
149 if (max_draw_buffers_ < 1)
150 max_draw_buffers_ = 1;
151 draw_buffer_ = GL_BACK;
154 buffer_manager_.reset(
155 new BufferManager(memory_tracker_.get(), feature_info_.get()));
156 framebuffer_manager_.reset(new FramebufferManager(
157 max_draw_buffers_, max_color_attachments_, context_type));
158 renderbuffer_manager_.reset(new RenderbufferManager(
159 memory_tracker_.get(), max_renderbuffer_size, max_samples,
160 feature_info_.get()));
161 shader_manager_.reset(new ShaderManager());
162 valuebuffer_manager_.reset(
163 new ValuebufferManager(subscription_ref_set_.get(),
164 pending_valuebuffer_state_.get()));
166 // Lookup GL things we need to know.
167 const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
168 if (!QueryGLFeatureU(
169 GL_MAX_VERTEX_ATTRIBS, kGLES2RequiredMinimumVertexAttribs,
170 &max_vertex_attribs_)) {
171 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
172 << "vertex attributes supported.";
173 return false;
176 const GLuint kGLES2RequiredMinimumTextureUnits = 8u;
177 if (!QueryGLFeatureU(
178 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kGLES2RequiredMinimumTextureUnits,
179 &max_texture_units_)) {
180 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
181 << "texture units supported.";
182 return false;
185 GLint max_texture_size = 0;
186 GLint max_cube_map_texture_size = 0;
187 GLint max_rectangle_texture_size = 0;
188 GLint max_3d_texture_size = 0;
190 const GLint kMinTextureSize = 2048; // GL actually says 64!?!?
191 // TODO(zmo): In ES3, max cubemap size is required to be at least 2048.
192 const GLint kMinCubeMapSize = 256; // GL actually says 16!?!?
193 const GLint kMinRectangleTextureSize = 64;
194 const GLint kMin3DTextureSize = 256;
196 if (!QueryGLFeature(GL_MAX_TEXTURE_SIZE, kMinTextureSize,
197 &max_texture_size) ||
198 !QueryGLFeature(GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize,
199 &max_cube_map_texture_size) ||
200 (feature_info_->gl_version_info().IsES3Capable() &&
201 !QueryGLFeature(GL_MAX_3D_TEXTURE_SIZE, kMin3DTextureSize,
202 &max_3d_texture_size)) ||
203 (feature_info_->feature_flags().arb_texture_rectangle &&
204 !QueryGLFeature(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB,
205 kMinRectangleTextureSize,
206 &max_rectangle_texture_size))) {
207 LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
208 << "texture size is too small.";
209 return false;
212 if (feature_info_->workarounds().max_texture_size) {
213 max_texture_size = std::min(
214 max_texture_size,
215 feature_info_->workarounds().max_texture_size);
216 max_rectangle_texture_size = std::min(
217 max_rectangle_texture_size,
218 feature_info_->workarounds().max_texture_size);
220 if (feature_info_->workarounds().max_cube_map_texture_size) {
221 max_cube_map_texture_size = std::min(
222 max_cube_map_texture_size,
223 feature_info_->workarounds().max_cube_map_texture_size);
226 texture_manager_.reset(new TextureManager(memory_tracker_.get(),
227 feature_info_.get(),
228 max_texture_size,
229 max_cube_map_texture_size,
230 max_rectangle_texture_size,
231 max_3d_texture_size,
232 bind_generates_resource_));
233 texture_manager_->set_framebuffer_manager(framebuffer_manager_.get());
235 const GLint kMinTextureImageUnits = 8;
236 const GLint kMinVertexTextureImageUnits = 0;
237 if (!QueryGLFeatureU(
238 GL_MAX_TEXTURE_IMAGE_UNITS, kMinTextureImageUnits,
239 &max_texture_image_units_) ||
240 !QueryGLFeatureU(
241 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits,
242 &max_vertex_texture_image_units_)) {
243 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
244 << "texture units.";
245 return false;
248 if (feature_info_->gl_version_info().BehavesLikeGLES()) {
249 GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
250 &max_fragment_uniform_vectors_);
251 GetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors_);
252 GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &max_vertex_uniform_vectors_);
253 } else {
254 GetIntegerv(
255 GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max_fragment_uniform_vectors_);
256 max_fragment_uniform_vectors_ /= 4;
257 GetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_vectors_);
258 max_varying_vectors_ /= 4;
259 GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_vertex_uniform_vectors_);
260 max_vertex_uniform_vectors_ /= 4;
263 const GLint kMinFragmentUniformVectors = 16;
264 const GLint kMinVaryingVectors = 8;
265 const GLint kMinVertexUniformVectors = 128;
266 if (!CheckGLFeatureU(
267 kMinFragmentUniformVectors, &max_fragment_uniform_vectors_) ||
268 !CheckGLFeatureU(kMinVaryingVectors, &max_varying_vectors_) ||
269 !CheckGLFeatureU(
270 kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) {
271 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
272 << "uniforms or varyings supported.";
273 return false;
276 // Some shaders in Skia need more than the min available vertex and
277 // fragment shader uniform vectors in case of OSMesa GL Implementation
278 if (feature_info_->workarounds().max_fragment_uniform_vectors) {
279 max_fragment_uniform_vectors_ = std::min(
280 max_fragment_uniform_vectors_,
281 static_cast<uint32>(
282 feature_info_->workarounds().max_fragment_uniform_vectors));
284 if (feature_info_->workarounds().max_varying_vectors) {
285 max_varying_vectors_ = std::min(
286 max_varying_vectors_,
287 static_cast<uint32>(feature_info_->workarounds().max_varying_vectors));
289 if (feature_info_->workarounds().max_vertex_uniform_vectors) {
290 max_vertex_uniform_vectors_ =
291 std::min(max_vertex_uniform_vectors_,
292 static_cast<uint32>(
293 feature_info_->workarounds().max_vertex_uniform_vectors));
296 path_manager_.reset(new PathManager());
298 program_manager_.reset(new ProgramManager(
299 program_cache_, max_varying_vectors_));
301 if (!texture_manager_->Initialize()) {
302 LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
303 << "failed to initialize.";
304 return false;
307 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
308 return true;
311 namespace {
313 bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) {
314 return !decoder.get();
317 template <typename T>
318 class WeakPtrEquals {
319 public:
320 explicit WeakPtrEquals(T* t) : t_(t) {}
322 bool operator()(const base::WeakPtr<T>& t) {
323 return t.get() == t_;
326 private:
327 T* const t_;
330 } // namespace anonymous
332 bool ContextGroup::HaveContexts() {
333 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull),
334 decoders_.end());
335 return !decoders_.empty();
338 void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) {
339 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(),
340 WeakPtrEquals<gles2::GLES2Decoder>(decoder)),
341 decoders_.end());
342 // If we still have contexts do nothing.
343 if (HaveContexts()) {
344 return;
347 if (buffer_manager_ != NULL) {
348 buffer_manager_->Destroy(have_context);
349 buffer_manager_.reset();
352 if (framebuffer_manager_ != NULL) {
353 framebuffer_manager_->Destroy(have_context);
354 if (texture_manager_)
355 texture_manager_->set_framebuffer_manager(NULL);
356 framebuffer_manager_.reset();
359 if (renderbuffer_manager_ != NULL) {
360 renderbuffer_manager_->Destroy(have_context);
361 renderbuffer_manager_.reset();
364 if (texture_manager_ != NULL) {
365 texture_manager_->Destroy(have_context);
366 texture_manager_.reset();
369 if (path_manager_ != NULL) {
370 path_manager_->Destroy(have_context);
371 path_manager_.reset();
374 if (program_manager_ != NULL) {
375 program_manager_->Destroy(have_context);
376 program_manager_.reset();
379 if (shader_manager_ != NULL) {
380 shader_manager_->Destroy(have_context);
381 shader_manager_.reset();
384 if (valuebuffer_manager_ != NULL) {
385 valuebuffer_manager_->Destroy();
386 valuebuffer_manager_.reset();
389 memory_tracker_ = NULL;
392 uint32 ContextGroup::GetMemRepresented() const {
393 uint32 total = 0;
394 if (buffer_manager_.get())
395 total += buffer_manager_->mem_represented();
396 if (renderbuffer_manager_.get())
397 total += renderbuffer_manager_->mem_represented();
398 if (texture_manager_.get())
399 total += texture_manager_->mem_represented();
400 return total;
403 void ContextGroup::LoseContexts(error::ContextLostReason reason) {
404 for (size_t ii = 0; ii < decoders_.size(); ++ii) {
405 if (decoders_[ii].get()) {
406 decoders_[ii]->MarkContextLost(reason);
411 ContextGroup::~ContextGroup() {
412 CHECK(!HaveContexts());
415 bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) {
416 GLint value = *v;
417 if (enforce_gl_minimums_) {
418 value = std::min(min_required, value);
420 *v = value;
421 return value >= min_required;
424 bool ContextGroup::CheckGLFeatureU(GLint min_required, uint32* v) {
425 GLint value = *v;
426 if (enforce_gl_minimums_) {
427 value = std::min(min_required, value);
429 *v = value;
430 return value >= min_required;
433 bool ContextGroup::QueryGLFeature(
434 GLenum pname, GLint min_required, GLint* v) {
435 GLint value = 0;
436 glGetIntegerv(pname, &value);
437 *v = value;
438 return CheckGLFeature(min_required, v);
441 bool ContextGroup::QueryGLFeatureU(
442 GLenum pname, GLint min_required, uint32* v) {
443 uint32 value = 0;
444 GetIntegerv(pname, &value);
445 bool result = CheckGLFeatureU(min_required, &value);
446 *v = value;
447 return result;
450 bool ContextGroup::GetBufferServiceId(
451 GLuint client_id, GLuint* service_id) const {
452 Buffer* buffer = buffer_manager_->GetBuffer(client_id);
453 if (!buffer)
454 return false;
455 *service_id = buffer->service_id();
456 return true;
459 } // namespace gles2
460 } // namespace gpu