Home | History | Annotate | Download | only in service
      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/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"
     27 
     28 namespace gpu {
     29 namespace gles2 {
     30 
     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),
     54       program_cache_(NULL),
     55       feature_info_(feature_info ? feature_info : new FeatureInfo),
     56       draw_buffer_(GL_BACK) {
     57   {
     58     TransferBufferManager* manager = new TransferBufferManager();
     59     transfer_buffer_manager_.reset(manager);
     60     manager->Initialize();
     61   }
     62 
     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);
     71 }
     72 
     73 static void GetIntegerv(GLenum pname, uint32* var) {
     74   GLint value = 0;
     75   glGetIntegerv(pname, &value);
     76   *var = value;
     77 }
     78 
     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;
     86   }
     87 
     88   if (!feature_info_->Initialize(disallowed_features)) {
     89     LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
     90                << "initialization failed.";
     91     return false;
     92   }
     93 
     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.";
    101     return false;
    102   }
    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);
    109     } else {
    110       glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
    111     }
    112   }
    113 
    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;
    122   }
    123 
    124   const bool depth24_supported = feature_info_->feature_flags().oes_depth24;
    125 
    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,
    132       depth24_supported));
    133   shader_manager_.reset(new ShaderManager());
    134 
    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.";
    142     return false;
    143   }
    144 
    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.";
    151     return false;
    152   }
    153 
    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!?!?
    158   if (!QueryGLFeature(
    159       GL_MAX_TEXTURE_SIZE, kMinTextureSize, &max_texture_size) ||
    160       !QueryGLFeature(
    161       GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize,
    162       &max_cube_map_texture_size)) {
    163     LOG(ERROR) << "ContextGroup::Initialize failed because maximum texture size"
    164                << "is too small.";
    165     return false;
    166   }
    167 
    168   if (feature_info_->workarounds().max_texture_size) {
    169     max_texture_size = std::min(
    170         max_texture_size, feature_info_->workarounds().max_texture_size);
    171   }
    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);
    176   }
    177 
    178   texture_manager_.reset(new TextureManager(memory_tracker_.get(),
    179                                             feature_info_.get(),
    180                                             max_texture_size,
    181                                             max_cube_map_texture_size,
    182                                             bind_generates_resource_));
    183   texture_manager_->set_framebuffer_manager(framebuffer_manager_.get());
    184 
    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_) ||
    190       !QueryGLFeatureU(
    191       GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits,
    192       &max_vertex_texture_image_units_)) {
    193     LOG(ERROR) << "ContextGroup::Initialize failed because too few "
    194                << "texture units.";
    195     return false;
    196   }
    197 
    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_);
    203   } else {
    204     GetIntegerv(
    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;
    211   }
    212 
    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_) ||
    219       !CheckGLFeatureU(
    220       kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) {
    221     LOG(ERROR) << "ContextGroup::Initialize failed because too few "
    222                << "uniforms or varyings supported.";
    223     return false;
    224   }
    225 
    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_,
    231         static_cast<uint32>(
    232             feature_info_->workarounds().max_fragment_uniform_vectors));
    233   }
    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));
    238   }
    239   if (feature_info_->workarounds().max_vertex_uniform_vectors) {
    240     max_vertex_uniform_vectors_ =
    241         std::min(max_vertex_uniform_vectors_,
    242                  static_cast<uint32>(
    243                      feature_info_->workarounds().max_vertex_uniform_vectors));
    244   }
    245 
    246   program_manager_.reset(new ProgramManager(
    247       program_cache_, max_varying_vectors_));
    248 
    249   if (!texture_manager_->Initialize()) {
    250     LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
    251                << "failed to initialize.";
    252     return false;
    253   }
    254 
    255   decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
    256   return true;
    257 }
    258 
    259 namespace {
    260 
    261 bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) {
    262   return !decoder.get();
    263 }
    264 
    265 template <typename T>
    266 class WeakPtrEquals {
    267  public:
    268   explicit WeakPtrEquals(T* t) : t_(t) {}
    269 
    270   bool operator()(const base::WeakPtr<T>& t) {
    271     return t.get() == t_;
    272   }
    273 
    274  private:
    275   T* const t_;
    276 };
    277 
    278 }  // namespace anonymous
    279 
    280 bool ContextGroup::HaveContexts() {
    281   decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull),
    282                   decoders_.end());
    283   return !decoders_.empty();
    284 }
    285 
    286 void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) {
    287   decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(),
    288                                  WeakPtrEquals<gles2::GLES2Decoder>(decoder)),
    289                   decoders_.end());
    290   // If we still have contexts do nothing.
    291   if (HaveContexts()) {
    292     return;
    293   }
    294 
    295   if (buffer_manager_ != NULL) {
    296     buffer_manager_->Destroy(have_context);
    297     buffer_manager_.reset();
    298   }
    299 
    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();
    305   }
    306 
    307   if (renderbuffer_manager_ != NULL) {
    308     renderbuffer_manager_->Destroy(have_context);
    309     renderbuffer_manager_.reset();
    310   }
    311 
    312   if (texture_manager_ != NULL) {
    313     texture_manager_->Destroy(have_context);
    314     texture_manager_.reset();
    315   }
    316 
    317   if (program_manager_ != NULL) {
    318     program_manager_->Destroy(have_context);
    319     program_manager_.reset();
    320   }
    321 
    322   if (shader_manager_ != NULL) {
    323     shader_manager_->Destroy(have_context);
    324     shader_manager_.reset();
    325   }
    326 
    327   memory_tracker_ = NULL;
    328 }
    329 
    330 IdAllocatorInterface* ContextGroup::GetIdAllocator(unsigned namespace_id) {
    331   if (namespace_id >= arraysize(id_namespaces_))
    332     return NULL;
    333 
    334   return id_namespaces_[namespace_id].get();
    335 }
    336 
    337 uint32 ContextGroup::GetMemRepresented() const {
    338   uint32 total = 0;
    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();
    345   return total;
    346 }
    347 
    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);
    352     }
    353   }
    354 }
    355 
    356 ContextGroup::~ContextGroup() {
    357   CHECK(!HaveContexts());
    358 }
    359 
    360 bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) {
    361   GLint value = *v;
    362   if (enforce_gl_minimums_) {
    363     value = std::min(min_required, value);
    364   }
    365   *v = value;
    366   return value >= min_required;
    367 }
    368 
    369 bool ContextGroup::CheckGLFeatureU(GLint min_required, uint32* v) {
    370   GLint value = *v;
    371   if (enforce_gl_minimums_) {
    372     value = std::min(min_required, value);
    373   }
    374   *v = value;
    375   return value >= min_required;
    376 }
    377 
    378 bool ContextGroup::QueryGLFeature(
    379     GLenum pname, GLint min_required, GLint* v) {
    380   GLint value = 0;
    381   glGetIntegerv(pname, &value);
    382   *v = value;
    383   return CheckGLFeature(min_required, v);
    384 }
    385 
    386 bool ContextGroup::QueryGLFeatureU(
    387     GLenum pname, GLint min_required, uint32* v) {
    388   uint32 value = 0;
    389   GetIntegerv(pname, &value);
    390   bool result = CheckGLFeatureU(min_required, &value);
    391   *v = value;
    392   return result;
    393 }
    394 
    395 }  // namespace gles2
    396 }  // namespace gpu
    397