Mandoline: Make TransferBufferManager RefCounted
[chromium-blink-merge.git] / gpu / command_buffer / service / context_group.cc
blobc975347ea68217a93b1dae9bbc406ada24719de1
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 : context_type_(CONTEXT_TYPE_UNDEFINED),
39 mailbox_manager_(mailbox_manager),
40 memory_tracker_(memory_tracker),
41 shader_translator_cache_(shader_translator_cache),
42 subscription_ref_set_(subscription_ref_set),
43 pending_valuebuffer_state_(pending_valuebuffer_state),
44 enforce_gl_minimums_(base::CommandLine::ForCurrentProcess()->HasSwitch(
45 switches::kEnforceGLMinimums)),
46 bind_generates_resource_(bind_generates_resource),
47 max_vertex_attribs_(0u),
48 max_texture_units_(0u),
49 max_texture_image_units_(0u),
50 max_vertex_texture_image_units_(0u),
51 max_fragment_uniform_vectors_(0u),
52 max_varying_vectors_(0u),
53 max_vertex_uniform_vectors_(0u),
54 max_color_attachments_(1u),
55 max_draw_buffers_(1u),
56 program_cache_(NULL),
57 feature_info_(feature_info),
58 draw_buffer_(GL_BACK) {
60 if (!mailbox_manager_.get())
61 mailbox_manager_ = new MailboxManagerImpl;
62 if (!subscription_ref_set_.get())
63 subscription_ref_set_ = new SubscriptionRefSet();
64 if (!pending_valuebuffer_state_.get())
65 pending_valuebuffer_state_ = new ValueStateMap();
66 if (!feature_info.get())
67 feature_info_ = new FeatureInfo;
68 TransferBufferManager* manager = new TransferBufferManager();
69 transfer_buffer_manager_ = manager;
70 manager->Initialize();
74 static void GetIntegerv(GLenum pname, uint32* var) {
75 GLint value = 0;
76 glGetIntegerv(pname, &value);
77 *var = value;
80 // static
81 ContextGroup::ContextType ContextGroup::GetContextType(
82 unsigned webgl_version) {
83 switch (webgl_version) {
84 case 0:
85 return CONTEXT_TYPE_OTHER;
86 case 1:
87 return CONTEXT_TYPE_WEBGL1;
88 case 2:
89 return CONTEXT_TYPE_WEBGL2;
90 default:
91 return CONTEXT_TYPE_UNDEFINED;
95 bool ContextGroup::Initialize(
96 GLES2Decoder* decoder,
97 ContextGroup::ContextType context_type,
98 const DisallowedFeatures& disallowed_features) {
99 if (context_type == CONTEXT_TYPE_UNDEFINED) {
100 LOG(ERROR) << "ContextGroup::Initialize failed because of unknown "
101 << "context type.";
102 return false;
104 if (context_type_ == CONTEXT_TYPE_UNDEFINED) {
105 context_type_ = context_type;
106 } else if (context_type_ != context_type) {
107 LOG(ERROR) << "ContextGroup::Initialize failed because the type of "
108 << "the context does not fit with the group.";
109 return false;
112 // If we've already initialized the group just add the context.
113 if (HaveContexts()) {
114 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
115 return true;
118 if (!feature_info_->Initialize(disallowed_features)) {
119 LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
120 << "initialization failed.";
121 return false;
124 const GLint kMinRenderbufferSize = 512; // GL says 1 pixel!
125 GLint max_renderbuffer_size = 0;
126 if (!QueryGLFeature(
127 GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize,
128 &max_renderbuffer_size)) {
129 LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
130 << "renderbuffer size too small (" << max_renderbuffer_size
131 << ", should be " << kMinRenderbufferSize << ").";
132 return false;
134 GLint max_samples = 0;
135 if (feature_info_->feature_flags().chromium_framebuffer_multisample ||
136 feature_info_->feature_flags().multisampled_render_to_texture) {
137 if (feature_info_->feature_flags(
138 ).use_img_for_multisampled_render_to_texture) {
139 glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples);
140 } else {
141 glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
145 if (feature_info_->feature_flags().ext_draw_buffers) {
146 GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments_);
147 if (max_color_attachments_ < 1)
148 max_color_attachments_ = 1;
149 GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers_);
150 if (max_draw_buffers_ < 1)
151 max_draw_buffers_ = 1;
152 draw_buffer_ = GL_BACK;
155 buffer_manager_.reset(
156 new BufferManager(memory_tracker_.get(), feature_info_.get()));
157 framebuffer_manager_.reset(
158 new FramebufferManager(max_draw_buffers_, max_color_attachments_));
159 renderbuffer_manager_.reset(new RenderbufferManager(
160 memory_tracker_.get(), max_renderbuffer_size, max_samples,
161 feature_info_.get()));
162 shader_manager_.reset(new ShaderManager());
163 valuebuffer_manager_.reset(
164 new ValuebufferManager(subscription_ref_set_.get(),
165 pending_valuebuffer_state_.get()));
167 // Lookup GL things we need to know.
168 const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
169 if (!QueryGLFeatureU(
170 GL_MAX_VERTEX_ATTRIBS, kGLES2RequiredMinimumVertexAttribs,
171 &max_vertex_attribs_)) {
172 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
173 << "vertex attributes supported.";
174 return false;
177 const GLuint kGLES2RequiredMinimumTextureUnits = 8u;
178 if (!QueryGLFeatureU(
179 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kGLES2RequiredMinimumTextureUnits,
180 &max_texture_units_)) {
181 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
182 << "texture units supported.";
183 return false;
186 GLint max_texture_size = 0;
187 GLint max_cube_map_texture_size = 0;
188 GLint max_rectangle_texture_size = 0;
189 GLint max_3d_texture_size = 0;
191 const GLint kMinTextureSize = 2048; // GL actually says 64!?!?
192 // TODO(zmo): In ES3, max cubemap size is required to be at least 2048.
193 const GLint kMinCubeMapSize = 256; // GL actually says 16!?!?
194 const GLint kMinRectangleTextureSize = 64;
195 const GLint kMin3DTextureSize = 256;
197 if (!QueryGLFeature(GL_MAX_TEXTURE_SIZE, kMinTextureSize,
198 &max_texture_size) ||
199 !QueryGLFeature(GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize,
200 &max_cube_map_texture_size) ||
201 (feature_info_->gl_version_info().IsES3Capable() &&
202 !QueryGLFeature(GL_MAX_3D_TEXTURE_SIZE, kMin3DTextureSize,
203 &max_3d_texture_size)) ||
204 (feature_info_->feature_flags().arb_texture_rectangle &&
205 !QueryGLFeature(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB,
206 kMinRectangleTextureSize,
207 &max_rectangle_texture_size))) {
208 LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
209 << "texture size is too small.";
210 return false;
213 if (feature_info_->workarounds().max_texture_size) {
214 max_texture_size = std::min(
215 max_texture_size,
216 feature_info_->workarounds().max_texture_size);
217 max_rectangle_texture_size = std::min(
218 max_rectangle_texture_size,
219 feature_info_->workarounds().max_texture_size);
221 if (feature_info_->workarounds().max_cube_map_texture_size) {
222 max_cube_map_texture_size = std::min(
223 max_cube_map_texture_size,
224 feature_info_->workarounds().max_cube_map_texture_size);
227 texture_manager_.reset(new TextureManager(memory_tracker_.get(),
228 feature_info_.get(),
229 max_texture_size,
230 max_cube_map_texture_size,
231 max_rectangle_texture_size,
232 max_3d_texture_size,
233 bind_generates_resource_));
234 texture_manager_->set_framebuffer_manager(framebuffer_manager_.get());
236 const GLint kMinTextureImageUnits = 8;
237 const GLint kMinVertexTextureImageUnits = 0;
238 if (!QueryGLFeatureU(
239 GL_MAX_TEXTURE_IMAGE_UNITS, kMinTextureImageUnits,
240 &max_texture_image_units_) ||
241 !QueryGLFeatureU(
242 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits,
243 &max_vertex_texture_image_units_)) {
244 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
245 << "texture units.";
246 return false;
249 if (feature_info_->gl_version_info().BehavesLikeGLES()) {
250 GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
251 &max_fragment_uniform_vectors_);
252 GetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors_);
253 GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &max_vertex_uniform_vectors_);
254 } else {
255 GetIntegerv(
256 GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max_fragment_uniform_vectors_);
257 max_fragment_uniform_vectors_ /= 4;
258 GetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_vectors_);
259 max_varying_vectors_ /= 4;
260 GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_vertex_uniform_vectors_);
261 max_vertex_uniform_vectors_ /= 4;
264 const GLint kMinFragmentUniformVectors = 16;
265 const GLint kMinVaryingVectors = 8;
266 const GLint kMinVertexUniformVectors = 128;
267 if (!CheckGLFeatureU(
268 kMinFragmentUniformVectors, &max_fragment_uniform_vectors_) ||
269 !CheckGLFeatureU(kMinVaryingVectors, &max_varying_vectors_) ||
270 !CheckGLFeatureU(
271 kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) {
272 LOG(ERROR) << "ContextGroup::Initialize failed because too few "
273 << "uniforms or varyings supported.";
274 return false;
277 // Some shaders in Skia need more than the min available vertex and
278 // fragment shader uniform vectors in case of OSMesa GL Implementation
279 if (feature_info_->workarounds().max_fragment_uniform_vectors) {
280 max_fragment_uniform_vectors_ = std::min(
281 max_fragment_uniform_vectors_,
282 static_cast<uint32>(
283 feature_info_->workarounds().max_fragment_uniform_vectors));
285 if (feature_info_->workarounds().max_varying_vectors) {
286 max_varying_vectors_ = std::min(
287 max_varying_vectors_,
288 static_cast<uint32>(feature_info_->workarounds().max_varying_vectors));
290 if (feature_info_->workarounds().max_vertex_uniform_vectors) {
291 max_vertex_uniform_vectors_ =
292 std::min(max_vertex_uniform_vectors_,
293 static_cast<uint32>(
294 feature_info_->workarounds().max_vertex_uniform_vectors));
297 program_manager_.reset(new ProgramManager(
298 program_cache_, max_varying_vectors_));
300 if (!texture_manager_->Initialize()) {
301 LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
302 << "failed to initialize.";
303 return false;
306 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
307 return true;
310 namespace {
312 bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) {
313 return !decoder.get();
316 template <typename T>
317 class WeakPtrEquals {
318 public:
319 explicit WeakPtrEquals(T* t) : t_(t) {}
321 bool operator()(const base::WeakPtr<T>& t) {
322 return t.get() == t_;
325 private:
326 T* const t_;
329 } // namespace anonymous
331 bool ContextGroup::HaveContexts() {
332 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull),
333 decoders_.end());
334 return !decoders_.empty();
337 void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) {
338 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(),
339 WeakPtrEquals<gles2::GLES2Decoder>(decoder)),
340 decoders_.end());
341 // If we still have contexts do nothing.
342 if (HaveContexts()) {
343 return;
346 if (buffer_manager_ != NULL) {
347 buffer_manager_->Destroy(have_context);
348 buffer_manager_.reset();
351 if (framebuffer_manager_ != NULL) {
352 framebuffer_manager_->Destroy(have_context);
353 if (texture_manager_)
354 texture_manager_->set_framebuffer_manager(NULL);
355 framebuffer_manager_.reset();
358 if (renderbuffer_manager_ != NULL) {
359 renderbuffer_manager_->Destroy(have_context);
360 renderbuffer_manager_.reset();
363 if (texture_manager_ != NULL) {
364 texture_manager_->Destroy(have_context);
365 texture_manager_.reset();
368 if (program_manager_ != NULL) {
369 program_manager_->Destroy(have_context);
370 program_manager_.reset();
373 if (shader_manager_ != NULL) {
374 shader_manager_->Destroy(have_context);
375 shader_manager_.reset();
378 if (valuebuffer_manager_ != NULL) {
379 valuebuffer_manager_->Destroy();
380 valuebuffer_manager_.reset();
383 memory_tracker_ = NULL;
386 uint32 ContextGroup::GetMemRepresented() const {
387 uint32 total = 0;
388 if (buffer_manager_.get())
389 total += buffer_manager_->mem_represented();
390 if (renderbuffer_manager_.get())
391 total += renderbuffer_manager_->mem_represented();
392 if (texture_manager_.get())
393 total += texture_manager_->mem_represented();
394 return total;
397 void ContextGroup::LoseContexts(error::ContextLostReason reason) {
398 for (size_t ii = 0; ii < decoders_.size(); ++ii) {
399 if (decoders_[ii].get()) {
400 decoders_[ii]->MarkContextLost(reason);
405 ContextGroup::~ContextGroup() {
406 CHECK(!HaveContexts());
409 bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) {
410 GLint value = *v;
411 if (enforce_gl_minimums_) {
412 value = std::min(min_required, value);
414 *v = value;
415 return value >= min_required;
418 bool ContextGroup::CheckGLFeatureU(GLint min_required, uint32* v) {
419 GLint value = *v;
420 if (enforce_gl_minimums_) {
421 value = std::min(min_required, value);
423 *v = value;
424 return value >= min_required;
427 bool ContextGroup::QueryGLFeature(
428 GLenum pname, GLint min_required, GLint* v) {
429 GLint value = 0;
430 glGetIntegerv(pname, &value);
431 *v = value;
432 return CheckGLFeature(min_required, v);
435 bool ContextGroup::QueryGLFeatureU(
436 GLenum pname, GLint min_required, uint32* v) {
437 uint32 value = 0;
438 GetIntegerv(pname, &value);
439 bool result = CheckGLFeatureU(min_required, &value);
440 *v = value;
441 return result;
444 bool ContextGroup::GetBufferServiceId(
445 GLuint client_id, GLuint* service_id) const {
446 Buffer* buffer = buffer_manager_->GetBuffer(client_id);
447 if (!buffer)
448 return false;
449 *service_id = buffer->service_id();
450 return true;
453 } // namespace gles2
454 } // namespace gpu