context_group.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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. 4 5#include "gpu/command_buffer/service/context_group.h" 6 7#include <algorithm> 8#include <string> 9 10#include "base/command_line.h" 11#include "base/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" 27 28namespace gpu { 29namespace gles2 { 30 31ContextGroup::ContextGroup( 32 MailboxManager* mailbox_manager, 33 ImageManager* image_manager, 34 MemoryTracker* memory_tracker, 35 bool bind_generates_resource) 36 : mailbox_manager_(mailbox_manager ? mailbox_manager : new MailboxManager), 37 image_manager_(image_manager ? image_manager : new ImageManager), 38 memory_tracker_(memory_tracker), 39 enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch( 40 switches::kEnforceGLMinimums)), 41 bind_generates_resource_(bind_generates_resource), 42 max_vertex_attribs_(0u), 43 max_texture_units_(0u), 44 max_texture_image_units_(0u), 45 max_vertex_texture_image_units_(0u), 46 max_fragment_uniform_vectors_(0u), 47 max_varying_vectors_(0u), 48 max_vertex_uniform_vectors_(0u), 49 max_color_attachments_(1u), 50 max_draw_buffers_(1u), 51 program_cache_(NULL), 52 feature_info_(new FeatureInfo()), 53 draw_buffer_(GL_BACK) { 54 { 55 TransferBufferManager* manager = new TransferBufferManager(); 56 transfer_buffer_manager_.reset(manager); 57 manager->Initialize(); 58 } 59 60 id_namespaces_[id_namespaces::kBuffers].reset(new IdAllocator); 61 id_namespaces_[id_namespaces::kFramebuffers].reset(new IdAllocator); 62 id_namespaces_[id_namespaces::kProgramsAndShaders].reset( 63 new NonReusedIdAllocator); 64 id_namespaces_[id_namespaces::kRenderbuffers].reset(new IdAllocator); 65 id_namespaces_[id_namespaces::kTextures].reset(new IdAllocator); 66 id_namespaces_[id_namespaces::kQueries].reset(new IdAllocator); 67 id_namespaces_[id_namespaces::kVertexArrays].reset(new IdAllocator); 68} 69 70static void GetIntegerv(GLenum pname, uint32* var) { 71 GLint value = 0; 72 glGetIntegerv(pname, &value); 73 *var = value; 74} 75 76bool ContextGroup::Initialize( 77 GLES2Decoder* decoder, 78 const DisallowedFeatures& disallowed_features, 79 const char* allowed_features) { 80 // If we've already initialized the group just add the context. 81 if (HaveContexts()) { 82 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder)); 83 return true; 84 } 85 86 if (!feature_info_->Initialize(disallowed_features, allowed_features)) { 87 LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo " 88 << "initialization failed."; 89 return false; 90 } 91 92 const GLint kMinRenderbufferSize = 512; // GL says 1 pixel! 93 GLint max_renderbuffer_size = 0; 94 if (!QueryGLFeature( 95 GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize, 96 &max_renderbuffer_size)) { 97 LOG(ERROR) << "ContextGroup::Initialize failed because maximum " 98 << "renderbuffer size too small."; 99 return false; 100 } 101 GLint max_samples = 0; 102 if (feature_info_->feature_flags().chromium_framebuffer_multisample) { 103 glGetIntegerv(GL_MAX_SAMPLES, &max_samples); 104 } 105 106 if (feature_info_->feature_flags().ext_draw_buffers) { 107 GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments_); 108 if (max_color_attachments_ < 1) 109 max_color_attachments_ = 1; 110 GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers_); 111 if (max_draw_buffers_ < 1) 112 max_draw_buffers_ = 1; 113 draw_buffer_ = GL_BACK; 114 } 115 116 buffer_manager_.reset(new BufferManager( 117 memory_tracker_, feature_info_.get())); 118 framebuffer_manager_.reset( 119 new FramebufferManager(max_draw_buffers_, max_color_attachments_)); 120 renderbuffer_manager_.reset(new RenderbufferManager(memory_tracker_, 121 max_renderbuffer_size, 122 max_samples)); 123 shader_manager_.reset(new ShaderManager()); 124 program_manager_.reset(new ProgramManager(program_cache_)); 125 126 // Lookup GL things we need to know. 127 const GLint kGLES2RequiredMinimumVertexAttribs = 8u; 128 if (!QueryGLFeatureU( 129 GL_MAX_VERTEX_ATTRIBS, kGLES2RequiredMinimumVertexAttribs, 130 &max_vertex_attribs_)) { 131 LOG(ERROR) << "ContextGroup::Initialize failed because too few " 132 << "vertex attributes supported."; 133 return false; 134 } 135 136 const GLuint kGLES2RequiredMinimumTextureUnits = 8u; 137 if (!QueryGLFeatureU( 138 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kGLES2RequiredMinimumTextureUnits, 139 &max_texture_units_)) { 140 LOG(ERROR) << "ContextGroup::Initialize failed because too few " 141 << "texture units supported."; 142 return false; 143 } 144 145 GLint max_texture_size = 0; 146 GLint max_cube_map_texture_size = 0; 147 const GLint kMinTextureSize = 2048; // GL actually says 64!?!? 148 const GLint kMinCubeMapSize = 256; // GL actually says 16!?!? 149 if (!QueryGLFeature( 150 GL_MAX_TEXTURE_SIZE, kMinTextureSize, &max_texture_size) || 151 !QueryGLFeature( 152 GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize, 153 &max_cube_map_texture_size)) { 154 LOG(ERROR) << "ContextGroup::Initialize failed because maximum texture size" 155 << "is too small."; 156 return false; 157 } 158 159 if (feature_info_->workarounds().max_texture_size) { 160 max_texture_size = std::min( 161 max_texture_size, feature_info_->workarounds().max_texture_size); 162 } 163 if (feature_info_->workarounds().max_cube_map_texture_size) { 164 max_cube_map_texture_size = std::min( 165 max_cube_map_texture_size, 166 feature_info_->workarounds().max_cube_map_texture_size); 167 } 168 169 texture_manager_.reset(new TextureManager(memory_tracker_, 170 feature_info_.get(), 171 max_texture_size, 172 max_cube_map_texture_size)); 173 texture_manager_->set_framebuffer_manager(framebuffer_manager_.get()); 174 175 const GLint kMinTextureImageUnits = 8; 176 const GLint kMinVertexTextureImageUnits = 0; 177 if (!QueryGLFeatureU( 178 GL_MAX_TEXTURE_IMAGE_UNITS, kMinTextureImageUnits, 179 &max_texture_image_units_) || 180 !QueryGLFeatureU( 181 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits, 182 &max_vertex_texture_image_units_)) { 183 LOG(ERROR) << "ContextGroup::Initialize failed because too few " 184 << "texture units."; 185 return false; 186 } 187 188 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { 189 GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, 190 &max_fragment_uniform_vectors_); 191 GetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors_); 192 GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &max_vertex_uniform_vectors_); 193 } else { 194 GetIntegerv( 195 GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max_fragment_uniform_vectors_); 196 max_fragment_uniform_vectors_ /= 4; 197 GetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_vectors_); 198 max_varying_vectors_ /= 4; 199 GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_vertex_uniform_vectors_); 200 max_vertex_uniform_vectors_ /= 4; 201 } 202 203 const GLint kMinFragmentUniformVectors = 16; 204 const GLint kMinVaryingVectors = 8; 205 const GLint kMinVertexUniformVectors = 128; 206 if (!CheckGLFeatureU( 207 kMinFragmentUniformVectors, &max_fragment_uniform_vectors_) || 208 !CheckGLFeatureU(kMinVaryingVectors, &max_varying_vectors_) || 209 !CheckGLFeatureU( 210 kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) { 211 LOG(ERROR) << "ContextGroup::Initialize failed because too few " 212 << "uniforms or varyings supported."; 213 return false; 214 } 215 216 // TODO(gman): Use workarounds similar to max_texture_size above to implement. 217 if (gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL) { 218 // Some shaders in Skia needed more than the min. 219 max_fragment_uniform_vectors_ = 220 std::min(static_cast<uint32>(kMinFragmentUniformVectors * 2), 221 max_fragment_uniform_vectors_); 222 max_varying_vectors_ = 223 std::min(static_cast<uint32>(kMinVaryingVectors * 2), 224 max_varying_vectors_); 225 max_vertex_uniform_vectors_ = 226 std::min(static_cast<uint32>(kMinVertexUniformVectors * 2), 227 max_vertex_uniform_vectors_); 228 } 229 230 if (!texture_manager_->Initialize()) { 231 LOG(ERROR) << "Context::Group::Initialize failed because texture manager " 232 << "failed to initialize."; 233 return false; 234 } 235 236 decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder)); 237 return true; 238} 239 240namespace { 241 242bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) { 243 return !decoder; 244} 245 246} // namespace anonymous 247 248bool ContextGroup::HaveContexts() { 249 decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull), 250 decoders_.end()); 251 return !decoders_.empty(); 252} 253 254void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) { 255 decoders_.erase(std::remove(decoders_.begin(), decoders_.end(), decoder), 256 decoders_.end()); 257 // If we still have contexts do nothing. 258 if (HaveContexts()) { 259 return; 260 } 261 262 if (buffer_manager_ != NULL) { 263 buffer_manager_->Destroy(have_context); 264 buffer_manager_.reset(); 265 } 266 267 if (framebuffer_manager_ != NULL) { 268 framebuffer_manager_->Destroy(have_context); 269 if (texture_manager_) 270 texture_manager_->set_framebuffer_manager(NULL); 271 framebuffer_manager_.reset(); 272 } 273 274 if (renderbuffer_manager_ != NULL) { 275 renderbuffer_manager_->Destroy(have_context); 276 renderbuffer_manager_.reset(); 277 } 278 279 if (texture_manager_ != NULL) { 280 mailbox_manager_->DestroyOwnedTextures(texture_manager_.get(), 281 have_context); 282 texture_manager_->Destroy(have_context); 283 texture_manager_.reset(); 284 } 285 286 if (program_manager_ != NULL) { 287 program_manager_->Destroy(have_context); 288 program_manager_.reset(); 289 } 290 291 if (shader_manager_ != NULL) { 292 shader_manager_->Destroy(have_context); 293 shader_manager_.reset(); 294 } 295 296 memory_tracker_ = NULL; 297} 298 299IdAllocatorInterface* ContextGroup::GetIdAllocator(unsigned namespace_id) { 300 if (namespace_id >= arraysize(id_namespaces_)) 301 return NULL; 302 303 return id_namespaces_[namespace_id].get(); 304} 305 306uint32 ContextGroup::GetMemRepresented() const { 307 uint32 total = 0; 308 if (buffer_manager_.get()) 309 total += buffer_manager_->mem_represented(); 310 if (renderbuffer_manager_.get()) 311 total += renderbuffer_manager_->mem_represented(); 312 if (texture_manager_.get()) 313 total += texture_manager_->mem_represented(); 314 return total; 315} 316 317void ContextGroup::LoseContexts(GLenum reset_status) { 318 for (size_t ii = 0; ii < decoders_.size(); ++ii) { 319 if (decoders_[ii]) { 320 decoders_[ii]->LoseContext(reset_status); 321 } 322 } 323} 324 325ContextGroup::~ContextGroup() { 326 CHECK(!HaveContexts()); 327} 328 329bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) { 330 GLint value = *v; 331 if (enforce_gl_minimums_) { 332 value = std::min(min_required, value); 333 } 334 *v = value; 335 return value >= min_required; 336} 337 338bool ContextGroup::CheckGLFeatureU(GLint min_required, uint32* v) { 339 GLint value = *v; 340 if (enforce_gl_minimums_) { 341 value = std::min(min_required, value); 342 } 343 *v = value; 344 return value >= min_required; 345} 346 347bool ContextGroup::QueryGLFeature( 348 GLenum pname, GLint min_required, GLint* v) { 349 GLint value = 0; 350 glGetIntegerv(pname, &value); 351 *v = value; 352 return CheckGLFeature(min_required, v); 353} 354 355bool ContextGroup::QueryGLFeatureU( 356 GLenum pname, GLint min_required, uint32* v) { 357 uint32 value = 0; 358 GetIntegerv(pname, &value); 359 bool result = CheckGLFeatureU(min_required, &value); 360 *v = value; 361 return result; 362} 363 364} // namespace gles2 365} // namespace gpu 366