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"
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/image_manager.h"
19 #include "gpu/command_buffer/service/mailbox_manager.h"
20 #include "gpu/command_buffer/service/memory_tracking.h"
21 #include "gpu/command_buffer/service/program_manager.h"
22 #include "gpu/command_buffer/service/renderbuffer_manager.h"
23 #include "gpu/command_buffer/service/shader_manager.h"
24 #include "gpu/command_buffer/service/texture_manager.h"
25 #include "gpu/command_buffer/service/transfer_buffer_manager.h"
26 #include "ui/gl/gl_implementation.h"
31 ContextGroup::ContextGroup(
32 MailboxManager
* mailbox_manager
,
33 ImageManager
* image_manager
,
34 MemoryTracker
* memory_tracker
,
35 ShaderTranslatorCache
* shader_translator_cache
,
36 FeatureInfo
* feature_info
,
37 bool bind_generates_resource
)
38 : mailbox_manager_(mailbox_manager
? mailbox_manager
: new MailboxManager
),
39 image_manager_(image_manager
? image_manager
: new ImageManager
),
40 memory_tracker_(memory_tracker
),
41 shader_translator_cache_(shader_translator_cache
),
42 enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch(
43 switches::kEnforceGLMinimums
)),
44 bind_generates_resource_(bind_generates_resource
),
45 max_vertex_attribs_(0u),
46 max_texture_units_(0u),
47 max_texture_image_units_(0u),
48 max_vertex_texture_image_units_(0u),
49 max_fragment_uniform_vectors_(0u),
50 max_varying_vectors_(0u),
51 max_vertex_uniform_vectors_(0u),
52 max_color_attachments_(1u),
53 max_draw_buffers_(1u),
55 feature_info_(feature_info
? feature_info
: new FeatureInfo
),
56 draw_buffer_(GL_BACK
) {
58 TransferBufferManager
* manager
= new TransferBufferManager();
59 transfer_buffer_manager_
.reset(manager
);
60 manager
->Initialize();
63 id_namespaces_
[id_namespaces::kBuffers
].reset(new IdAllocator
);
64 id_namespaces_
[id_namespaces::kFramebuffers
].reset(new IdAllocator
);
65 id_namespaces_
[id_namespaces::kProgramsAndShaders
].reset(
66 new NonReusedIdAllocator
);
67 id_namespaces_
[id_namespaces::kRenderbuffers
].reset(new IdAllocator
);
68 id_namespaces_
[id_namespaces::kTextures
].reset(new IdAllocator
);
69 id_namespaces_
[id_namespaces::kQueries
].reset(new IdAllocator
);
70 id_namespaces_
[id_namespaces::kVertexArrays
].reset(new IdAllocator
);
73 static void GetIntegerv(GLenum pname
, uint32
* var
) {
75 glGetIntegerv(pname
, &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.
84 decoders_
.push_back(base::AsWeakPtr
<GLES2Decoder
>(decoder
));
88 if (!feature_info_
->Initialize(disallowed_features
)) {
89 LOG(ERROR
) << "ContextGroup::Initialize failed because FeatureInfo "
90 << "initialization failed.";
94 const GLint kMinRenderbufferSize
= 512; // GL says 1 pixel!
95 GLint max_renderbuffer_size
= 0;
97 GL_MAX_RENDERBUFFER_SIZE
, kMinRenderbufferSize
,
98 &max_renderbuffer_size
)) {
99 LOG(ERROR
) << "ContextGroup::Initialize failed because maximum "
100 << "renderbuffer size too small.";
103 GLint max_samples
= 0;
104 if (feature_info_
->feature_flags().chromium_framebuffer_multisample
||
105 feature_info_
->feature_flags().multisampled_render_to_texture
) {
106 if (feature_info_
->feature_flags(
107 ).use_img_for_multisampled_render_to_texture
) {
108 glGetIntegerv(GL_MAX_SAMPLES_IMG
, &max_samples
);
110 glGetIntegerv(GL_MAX_SAMPLES
, &max_samples
);
114 if (feature_info_
->feature_flags().ext_draw_buffers
) {
115 GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT
, &max_color_attachments_
);
116 if (max_color_attachments_
< 1)
117 max_color_attachments_
= 1;
118 GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB
, &max_draw_buffers_
);
119 if (max_draw_buffers_
< 1)
120 max_draw_buffers_
= 1;
121 draw_buffer_
= GL_BACK
;
124 const bool depth24_supported
= feature_info_
->feature_flags().oes_depth24
;
126 buffer_manager_
.reset(
127 new BufferManager(memory_tracker_
.get(), feature_info_
.get()));
128 framebuffer_manager_
.reset(
129 new FramebufferManager(max_draw_buffers_
, max_color_attachments_
));
130 renderbuffer_manager_
.reset(new RenderbufferManager(
131 memory_tracker_
.get(), max_renderbuffer_size
, max_samples
,
133 shader_manager_
.reset(new ShaderManager());
135 // Lookup GL things we need to know.
136 const GLint kGLES2RequiredMinimumVertexAttribs
= 8u;
137 if (!QueryGLFeatureU(
138 GL_MAX_VERTEX_ATTRIBS
, kGLES2RequiredMinimumVertexAttribs
,
139 &max_vertex_attribs_
)) {
140 LOG(ERROR
) << "ContextGroup::Initialize failed because too few "
141 << "vertex attributes supported.";
145 const GLuint kGLES2RequiredMinimumTextureUnits
= 8u;
146 if (!QueryGLFeatureU(
147 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
, kGLES2RequiredMinimumTextureUnits
,
148 &max_texture_units_
)) {
149 LOG(ERROR
) << "ContextGroup::Initialize failed because too few "
150 << "texture units supported.";
154 GLint max_texture_size
= 0;
155 GLint max_cube_map_texture_size
= 0;
156 const GLint kMinTextureSize
= 2048; // GL actually says 64!?!?
157 const GLint kMinCubeMapSize
= 256; // GL actually says 16!?!?
159 GL_MAX_TEXTURE_SIZE
, kMinTextureSize
, &max_texture_size
) ||
161 GL_MAX_CUBE_MAP_TEXTURE_SIZE
, kMinCubeMapSize
,
162 &max_cube_map_texture_size
)) {
163 LOG(ERROR
) << "ContextGroup::Initialize failed because maximum texture size"
168 if (feature_info_
->workarounds().max_texture_size
) {
169 max_texture_size
= std::min(
170 max_texture_size
, feature_info_
->workarounds().max_texture_size
);
172 if (feature_info_
->workarounds().max_cube_map_texture_size
) {
173 max_cube_map_texture_size
= std::min(
174 max_cube_map_texture_size
,
175 feature_info_
->workarounds().max_cube_map_texture_size
);
178 texture_manager_
.reset(new TextureManager(memory_tracker_
.get(),
181 max_cube_map_texture_size
,
182 bind_generates_resource_
));
183 texture_manager_
->set_framebuffer_manager(framebuffer_manager_
.get());
185 const GLint kMinTextureImageUnits
= 8;
186 const GLint kMinVertexTextureImageUnits
= 0;
187 if (!QueryGLFeatureU(
188 GL_MAX_TEXTURE_IMAGE_UNITS
, kMinTextureImageUnits
,
189 &max_texture_image_units_
) ||
191 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
, kMinVertexTextureImageUnits
,
192 &max_vertex_texture_image_units_
)) {
193 LOG(ERROR
) << "ContextGroup::Initialize failed because too few "
198 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2
) {
199 GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS
,
200 &max_fragment_uniform_vectors_
);
201 GetIntegerv(GL_MAX_VARYING_VECTORS
, &max_varying_vectors_
);
202 GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS
, &max_vertex_uniform_vectors_
);
205 GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
, &max_fragment_uniform_vectors_
);
206 max_fragment_uniform_vectors_
/= 4;
207 GetIntegerv(GL_MAX_VARYING_FLOATS
, &max_varying_vectors_
);
208 max_varying_vectors_
/= 4;
209 GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS
, &max_vertex_uniform_vectors_
);
210 max_vertex_uniform_vectors_
/= 4;
213 const GLint kMinFragmentUniformVectors
= 16;
214 const GLint kMinVaryingVectors
= 8;
215 const GLint kMinVertexUniformVectors
= 128;
216 if (!CheckGLFeatureU(
217 kMinFragmentUniformVectors
, &max_fragment_uniform_vectors_
) ||
218 !CheckGLFeatureU(kMinVaryingVectors
, &max_varying_vectors_
) ||
220 kMinVertexUniformVectors
, &max_vertex_uniform_vectors_
)) {
221 LOG(ERROR
) << "ContextGroup::Initialize failed because too few "
222 << "uniforms or varyings supported.";
226 // Some shaders in Skia need more than the min available vertex and
227 // fragment shader uniform vectors in case of OSMesa GL Implementation
228 if (feature_info_
->workarounds().max_fragment_uniform_vectors
) {
229 max_fragment_uniform_vectors_
= std::min(
230 max_fragment_uniform_vectors_
,
232 feature_info_
->workarounds().max_fragment_uniform_vectors
));
234 if (feature_info_
->workarounds().max_varying_vectors
) {
235 max_varying_vectors_
= std::min(
236 max_varying_vectors_
,
237 static_cast<uint32
>(feature_info_
->workarounds().max_varying_vectors
));
239 if (feature_info_
->workarounds().max_vertex_uniform_vectors
) {
240 max_vertex_uniform_vectors_
=
241 std::min(max_vertex_uniform_vectors_
,
243 feature_info_
->workarounds().max_vertex_uniform_vectors
));
246 program_manager_
.reset(new ProgramManager(
247 program_cache_
, max_varying_vectors_
));
249 if (!texture_manager_
->Initialize()) {
250 LOG(ERROR
) << "Context::Group::Initialize failed because texture manager "
251 << "failed to initialize.";
255 decoders_
.push_back(base::AsWeakPtr
<GLES2Decoder
>(decoder
));
261 bool IsNull(const base::WeakPtr
<gles2::GLES2Decoder
>& decoder
) {
262 return !decoder
.get();
265 template <typename T
>
266 class WeakPtrEquals
{
268 explicit WeakPtrEquals(T
* t
) : t_(t
) {}
270 bool operator()(const base::WeakPtr
<T
>& t
) {
271 return t
.get() == t_
;
278 } // namespace anonymous
280 bool ContextGroup::HaveContexts() {
281 decoders_
.erase(std::remove_if(decoders_
.begin(), decoders_
.end(), IsNull
),
283 return !decoders_
.empty();
286 void ContextGroup::Destroy(GLES2Decoder
* decoder
, bool have_context
) {
287 decoders_
.erase(std::remove_if(decoders_
.begin(), decoders_
.end(),
288 WeakPtrEquals
<gles2::GLES2Decoder
>(decoder
)),
290 // If we still have contexts do nothing.
291 if (HaveContexts()) {
295 if (buffer_manager_
!= NULL
) {
296 buffer_manager_
->Destroy(have_context
);
297 buffer_manager_
.reset();
300 if (framebuffer_manager_
!= NULL
) {
301 framebuffer_manager_
->Destroy(have_context
);
302 if (texture_manager_
)
303 texture_manager_
->set_framebuffer_manager(NULL
);
304 framebuffer_manager_
.reset();
307 if (renderbuffer_manager_
!= NULL
) {
308 renderbuffer_manager_
->Destroy(have_context
);
309 renderbuffer_manager_
.reset();
312 if (texture_manager_
!= NULL
) {
313 texture_manager_
->Destroy(have_context
);
314 texture_manager_
.reset();
317 if (program_manager_
!= NULL
) {
318 program_manager_
->Destroy(have_context
);
319 program_manager_
.reset();
322 if (shader_manager_
!= NULL
) {
323 shader_manager_
->Destroy(have_context
);
324 shader_manager_
.reset();
327 memory_tracker_
= NULL
;
330 IdAllocatorInterface
* ContextGroup::GetIdAllocator(unsigned namespace_id
) {
331 if (namespace_id
>= arraysize(id_namespaces_
))
334 return id_namespaces_
[namespace_id
].get();
337 uint32
ContextGroup::GetMemRepresented() const {
339 if (buffer_manager_
.get())
340 total
+= buffer_manager_
->mem_represented();
341 if (renderbuffer_manager_
.get())
342 total
+= renderbuffer_manager_
->mem_represented();
343 if (texture_manager_
.get())
344 total
+= texture_manager_
->mem_represented();
348 void ContextGroup::LoseContexts(GLenum reset_status
) {
349 for (size_t ii
= 0; ii
< decoders_
.size(); ++ii
) {
350 if (decoders_
[ii
].get()) {
351 decoders_
[ii
]->LoseContext(reset_status
);
356 ContextGroup::~ContextGroup() {
357 CHECK(!HaveContexts());
360 bool ContextGroup::CheckGLFeature(GLint min_required
, GLint
* v
) {
362 if (enforce_gl_minimums_
) {
363 value
= std::min(min_required
, value
);
366 return value
>= min_required
;
369 bool ContextGroup::CheckGLFeatureU(GLint min_required
, uint32
* v
) {
371 if (enforce_gl_minimums_
) {
372 value
= std::min(min_required
, value
);
375 return value
>= min_required
;
378 bool ContextGroup::QueryGLFeature(
379 GLenum pname
, GLint min_required
, GLint
* v
) {
381 glGetIntegerv(pname
, &value
);
383 return CheckGLFeature(min_required
, v
);
386 bool ContextGroup::QueryGLFeatureU(
387 GLenum pname
, GLint min_required
, uint32
* v
) {
389 GetIntegerv(pname
, &value
);
390 bool result
= CheckGLFeatureU(min_required
, &value
);