15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/context_group.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_info.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/id_allocator.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/buffer_manager.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/framebuffer_manager.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/gpu_switches.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/image_manager.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/mailbox_manager.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/memory_tracking.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/program_manager.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/renderbuffer_manager.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/shader_manager.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/texture_manager.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/transfer_buffer_manager.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_implementation.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gles2 {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContextGroup::ContextGroup(
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MailboxManager* mailbox_manager,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImageManager* image_manager,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MemoryTracker* memory_tracker,
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    StreamTextureManager* stream_texture_manager,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool bind_generates_resource)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : mailbox_manager_(mailbox_manager ? mailbox_manager : new MailboxManager),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image_manager_(image_manager ? image_manager : new ImageManager),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memory_tracker_(memory_tracker),
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream_texture_manager_(stream_texture_manager),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enforce_gl_minimums_(CommandLine::ForCurrentProcess()->HasSwitch(
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          switches::kEnforceGLMinimums)),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bind_generates_resource_(bind_generates_resource),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_vertex_attribs_(0u),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_texture_units_(0u),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_texture_image_units_(0u),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_vertex_texture_image_units_(0u),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_fragment_uniform_vectors_(0u),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_varying_vectors_(0u),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_vertex_uniform_vectors_(0u),
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_color_attachments_(1u),
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_draw_buffers_(1u),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      program_cache_(NULL),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      feature_info_(new FeatureInfo()),
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      draw_buffer_(GL_BACK) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransferBufferManager* manager = new TransferBufferManager();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transfer_buffer_manager_.reset(manager);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager->Initialize();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_namespaces_[id_namespaces::kBuffers].reset(new IdAllocator);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_namespaces_[id_namespaces::kFramebuffers].reset(new IdAllocator);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_namespaces_[id_namespaces::kProgramsAndShaders].reset(
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new NonReusedIdAllocator);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_namespaces_[id_namespaces::kRenderbuffers].reset(new IdAllocator);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_namespaces_[id_namespaces::kTextures].reset(new IdAllocator);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_namespaces_[id_namespaces::kQueries].reset(new IdAllocator);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  id_namespaces_[id_namespaces::kVertexArrays].reset(new IdAllocator);
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  id_namespaces_[id_namespaces::kImages].reset(new IdAllocator);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void GetIntegerv(GLenum pname, uint32* var) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint value = 0;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glGetIntegerv(pname, &value);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *var = value;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ContextGroup::Initialize(
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GLES2Decoder* decoder,
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const DisallowedFeatures& disallowed_features,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* allowed_features) {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we've already initialized the group just add the context.
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (HaveContexts()) {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!feature_info_->Initialize(disallowed_features, allowed_features)) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "initialization failed.";
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLint kMinRenderbufferSize = 512;  // GL says 1 pixel!
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint max_renderbuffer_size = 0;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!QueryGLFeature(
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &max_renderbuffer_size)) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ContextGroup::Initialize failed because maximum "
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "renderbuffer size too small.";
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint max_samples = 0;
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (feature_info_->feature_flags().chromium_framebuffer_multisample ||
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      feature_info_->feature_flags().multisampled_render_to_texture) {
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (feature_info_->feature_flags(
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            ).use_img_for_multisampled_render_to_texture) {
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples);
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (feature_info_->feature_flags().ext_draw_buffers) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &max_color_attachments_);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (max_color_attachments_ < 1)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_color_attachments_ = 1;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &max_draw_buffers_);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (max_draw_buffers_ < 1)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_draw_buffers_ = 1;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    draw_buffer_ = GL_BACK;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  buffer_manager_.reset(
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new BufferManager(memory_tracker_.get(), feature_info_.get()));
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  framebuffer_manager_.reset(
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new FramebufferManager(max_draw_buffers_, max_color_attachments_));
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  renderbuffer_manager_.reset(new RenderbufferManager(
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      memory_tracker_.get(), max_renderbuffer_size, max_samples));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shader_manager_.reset(new ShaderManager());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  program_manager_.reset(new ProgramManager(program_cache_));
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Lookup GL things we need to know.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLint kGLES2RequiredMinimumVertexAttribs = 8u;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!QueryGLFeatureU(
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_MAX_VERTEX_ATTRIBS, kGLES2RequiredMinimumVertexAttribs,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &max_vertex_attribs_)) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ContextGroup::Initialize failed because too few "
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "vertex attributes supported.";
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLuint kGLES2RequiredMinimumTextureUnits = 8u;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!QueryGLFeatureU(
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kGLES2RequiredMinimumTextureUnits,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &max_texture_units_)) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ContextGroup::Initialize failed because too few "
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "texture units supported.";
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint max_texture_size = 0;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint max_cube_map_texture_size = 0;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLint kMinTextureSize = 2048;  // GL actually says 64!?!?
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLint kMinCubeMapSize = 256;  // GL actually says 16!?!?
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!QueryGLFeature(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_MAX_TEXTURE_SIZE, kMinTextureSize, &max_texture_size) ||
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !QueryGLFeature(
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMinCubeMapSize,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &max_cube_map_texture_size)) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ContextGroup::Initialize failed because maximum texture size"
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "is too small.";
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (feature_info_->workarounds().max_texture_size) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_texture_size = std::min(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        max_texture_size, feature_info_->workarounds().max_texture_size);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (feature_info_->workarounds().max_cube_map_texture_size) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_cube_map_texture_size = std::min(
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        max_cube_map_texture_size,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        feature_info_->workarounds().max_cube_map_texture_size);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  texture_manager_.reset(new TextureManager(memory_tracker_.get(),
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            feature_info_.get(),
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            max_texture_size,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            max_cube_map_texture_size));
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  texture_manager_->set_framebuffer_manager(framebuffer_manager_.get());
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  texture_manager_->set_stream_texture_manager(stream_texture_manager_);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLint kMinTextureImageUnits = 8;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLint kMinVertexTextureImageUnits = 0;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!QueryGLFeatureU(
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_MAX_TEXTURE_IMAGE_UNITS, kMinTextureImageUnits,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &max_texture_image_units_) ||
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !QueryGLFeatureU(
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMinVertexTextureImageUnits,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &max_vertex_texture_image_units_)) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ContextGroup::Initialize failed because too few "
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "texture units.";
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &max_fragment_uniform_vectors_);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors_);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &max_vertex_uniform_vectors_);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetIntegerv(
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &max_fragment_uniform_vectors_);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_fragment_uniform_vectors_ /= 4;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetIntegerv(GL_MAX_VARYING_FLOATS, &max_varying_vectors_);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_varying_vectors_ /= 4;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_vertex_uniform_vectors_);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    max_vertex_uniform_vectors_ /= 4;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLint kMinFragmentUniformVectors = 16;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLint kMinVaryingVectors = 8;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GLint kMinVertexUniformVectors = 128;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CheckGLFeatureU(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kMinFragmentUniformVectors, &max_fragment_uniform_vectors_) ||
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !CheckGLFeatureU(kMinVaryingVectors, &max_varying_vectors_) ||
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !CheckGLFeatureU(
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kMinVertexUniformVectors, &max_vertex_uniform_vectors_)) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "ContextGroup::Initialize failed because too few "
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "uniforms or varyings supported.";
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(gman): Use workarounds similar to max_texture_size above to implement.
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL) {
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Some shaders in Skia needed more than the min.
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    max_fragment_uniform_vectors_ =
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       std::min(static_cast<uint32>(kMinFragmentUniformVectors * 2),
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                max_fragment_uniform_vectors_);
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    max_varying_vectors_ =
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       std::min(static_cast<uint32>(kMinVaryingVectors * 2),
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                max_varying_vectors_);
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    max_vertex_uniform_vectors_ =
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       std::min(static_cast<uint32>(kMinVertexUniformVectors * 2),
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                max_vertex_uniform_vectors_);
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!texture_manager_->Initialize()) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Context::Group::Initialize failed because texture manager "
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "failed to initialize.";
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decoders_.push_back(base::AsWeakPtr<GLES2Decoder>(decoder));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsNull(const base::WeakPtr<gles2::GLES2Decoder>& decoder) {
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return !decoder.get();
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template <typename T>
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class WeakPtrEquals {
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  explicit WeakPtrEquals(T* t) : t_(t) {}
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool operator()(const base::WeakPtr<T>& t) {
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return t.get() == t_;
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  T* const t_;
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace anonymous
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ContextGroup::HaveContexts() {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(), IsNull),
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  decoders_.end());
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return !decoders_.empty();
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ContextGroup::Destroy(GLES2Decoder* decoder, bool have_context) {
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  decoders_.erase(std::remove_if(decoders_.begin(), decoders_.end(),
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 WeakPtrEquals<gles2::GLES2Decoder>(decoder)),
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  decoders_.end());
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we still have contexts do nothing.
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (HaveContexts()) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_manager_ != NULL) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_manager_->Destroy(have_context);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer_manager_.reset();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (framebuffer_manager_ != NULL) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    framebuffer_manager_->Destroy(have_context);
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (texture_manager_)
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      texture_manager_->set_framebuffer_manager(NULL);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    framebuffer_manager_.reset();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (renderbuffer_manager_ != NULL) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    renderbuffer_manager_->Destroy(have_context);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    renderbuffer_manager_.reset();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (texture_manager_ != NULL) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    texture_manager_->Destroy(have_context);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    texture_manager_.reset();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (program_manager_ != NULL) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    program_manager_->Destroy(have_context);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    program_manager_.reset();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (shader_manager_ != NULL) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shader_manager_->Destroy(have_context);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shader_manager_.reset();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memory_tracker_ = NULL;
318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream_texture_manager_ = NULL;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IdAllocatorInterface* ContextGroup::GetIdAllocator(unsigned namespace_id) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (namespace_id >= arraysize(id_namespaces_))
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return id_namespaces_[namespace_id].get();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 ContextGroup::GetMemRepresented() const {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 total = 0;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_manager_.get())
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total += buffer_manager_->mem_represented();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (renderbuffer_manager_.get())
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total += renderbuffer_manager_->mem_represented();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (texture_manager_.get())
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total += texture_manager_->mem_represented();
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return total;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ContextGroup::LoseContexts(GLenum reset_status) {
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t ii = 0; ii < decoders_.size(); ++ii) {
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (decoders_[ii].get()) {
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      decoders_[ii]->LoseContext(reset_status);
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ContextGroup::~ContextGroup() {
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(!HaveContexts());
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ContextGroup::CheckGLFeature(GLint min_required, GLint* v) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint value = *v;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enforce_gl_minimums_) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value = std::min(min_required, value);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *v = value;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value >= min_required;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ContextGroup::CheckGLFeatureU(GLint min_required, uint32* v) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint value = *v;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enforce_gl_minimums_) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value = std::min(min_required, value);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *v = value;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value >= min_required;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ContextGroup::QueryGLFeature(
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLenum pname, GLint min_required, GLint* v) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLint value = 0;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  glGetIntegerv(pname, &value);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *v = value;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CheckGLFeature(min_required, v);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ContextGroup::QueryGLFeatureU(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLenum pname, GLint min_required, uint32* v) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 value = 0;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetIntegerv(pname, &value);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = CheckGLFeatureU(min_required, &value);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *v = value;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gles2
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gpu
388