| Index: gpu/command_buffer/client/program_info_manager.cc
|
| diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc
|
| index 8b137891791fe96927ad78e64b0aad7bded08bdc..57a037d3256f4420196bb939fc8d196adac03407 100644
|
| --- a/gpu/command_buffer/client/program_info_manager.cc
|
| +++ b/gpu/command_buffer/client/program_info_manager.cc
|
| @@ -1 +1,496 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "../client/program_info_manager.h"
|
| +#include "../client/gles2_implementation.h"
|
| +
|
| +#include <map>
|
| +
|
| +namespace gpu {
|
| +namespace gles2 {
|
| +
|
| +class NonCachedProgramInfoManager : public ProgramInfoManager {
|
| + public:
|
| + NonCachedProgramInfoManager();
|
| + virtual ~NonCachedProgramInfoManager();
|
| +
|
| + virtual void CreateInfo(GLuint program);
|
| +
|
| + virtual void DeleteInfo(GLuint program);
|
| +
|
| + virtual bool GetProgramiv(
|
| + GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params);
|
| +
|
| + virtual GLint GetAttribLocation(
|
| + GLES2Implementation* gl, GLuint program, const char* name);
|
| +
|
| + virtual GLint GetUniformLocation(
|
| + GLES2Implementation* gl, GLuint program, const char* name);
|
| +
|
| + virtual bool GetActiveAttrib(
|
| + GLES2Implementation* gl,
|
| + GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
|
| + GLint* size, GLenum* type, char* name);
|
| +
|
| + virtual bool GetActiveUniform(
|
| + GLES2Implementation* gl,
|
| + GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
|
| + GLint* size, GLenum* type, char* name);
|
| +
|
| +};
|
| +
|
| +NonCachedProgramInfoManager::NonCachedProgramInfoManager() {
|
| +}
|
| +
|
| +NonCachedProgramInfoManager::~NonCachedProgramInfoManager() {
|
| +}
|
| +
|
| +void NonCachedProgramInfoManager::CreateInfo(GLuint /* program */) {
|
| +}
|
| +
|
| +void NonCachedProgramInfoManager::DeleteInfo(GLuint /* program */) {
|
| +}
|
| +
|
| +bool NonCachedProgramInfoManager::GetProgramiv(
|
| + GLES2Implementation* /* gl */,
|
| + GLuint /* program */,
|
| + GLenum /* pname */,
|
| + GLint* /* params */) {
|
| + return false;
|
| +}
|
| +
|
| +GLint NonCachedProgramInfoManager::GetAttribLocation(
|
| + GLES2Implementation* gl, GLuint program, const char* name) {
|
| + return gl->GetAttribLocationHelper(program, name);
|
| +}
|
| +
|
| +GLint NonCachedProgramInfoManager::GetUniformLocation(
|
| + GLES2Implementation* gl, GLuint program, const char* name) {
|
| + return gl->GetUniformLocationHelper(program, name);
|
| +}
|
| +
|
| +bool NonCachedProgramInfoManager::GetActiveAttrib(
|
| + GLES2Implementation* gl,
|
| + GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
|
| + GLint* size, GLenum* type, char* name) {
|
| + return gl->GetActiveAttribHelper(
|
| + program, index, bufsize, length, size, type, name);
|
| +}
|
| +
|
| +bool NonCachedProgramInfoManager::GetActiveUniform(
|
| + GLES2Implementation* gl,
|
| + GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
|
| + GLint* size, GLenum* type, char* name) {
|
| + return gl->GetActiveUniformHelper(
|
| + program, index, bufsize, length, size, type, name);
|
| +}
|
| +
|
| +class CachedProgramInfoManager : public ProgramInfoManager {
|
| + public:
|
| + CachedProgramInfoManager();
|
| + virtual ~CachedProgramInfoManager();
|
| +
|
| + virtual void CreateInfo(GLuint program);
|
| +
|
| + virtual void DeleteInfo(GLuint program);
|
| +
|
| + virtual bool GetProgramiv(
|
| + GLES2Implementation* gl,
|
| + GLuint program, GLenum pname, GLint* params);
|
| +
|
| + virtual GLint GetAttribLocation(
|
| + GLES2Implementation* gl, GLuint program, const char* name);
|
| +
|
| + virtual GLint GetUniformLocation(
|
| + GLES2Implementation* gl, GLuint program, const char* name);
|
| +
|
| + virtual bool GetActiveAttrib(
|
| + GLES2Implementation* gl,
|
| + GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
|
| + GLint* size, GLenum* type, char* name);
|
| +
|
| + virtual bool GetActiveUniform(
|
| + GLES2Implementation* gl,
|
| + GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
|
| + GLint* size, GLenum* type, char* name);
|
| +
|
| + private:
|
| + class ProgramInfo {
|
| + public:
|
| + struct UniformInfo {
|
| + UniformInfo(GLsizei _size, GLenum _type, const std::string& _name);
|
| +
|
| + GLsizei size;
|
| + GLenum type;
|
| + bool is_array;
|
| + std::string name;
|
| + std::vector<GLint> element_locations;
|
| + };
|
| + struct VertexAttribInfo {
|
| + VertexAttribInfo(GLsizei _size, GLenum _type, const std::string& _name,
|
| + GLint _location)
|
| + : size(_size),
|
| + type(_type),
|
| + location(_location),
|
| + name(_name) {
|
| + }
|
| + GLsizei size;
|
| + GLenum type;
|
| + GLint location;
|
| + std::string name;
|
| + };
|
| +
|
| + typedef std::vector<UniformInfo> UniformInfoVector;
|
| + typedef std::vector<VertexAttribInfo> AttribInfoVector;
|
| +
|
| + ProgramInfo();
|
| +
|
| + const AttribInfoVector& GetAttribInfos() const {
|
| + return attrib_infos_;
|
| + }
|
| +
|
| + const VertexAttribInfo* GetAttribInfo(GLint index) const {
|
| + return (static_cast<size_t>(index) < attrib_infos_.size()) ?
|
| + &attrib_infos_[index] : NULL;
|
| + }
|
| +
|
| + GLint GetAttribLocation(const std::string& name) const;
|
| +
|
| + const UniformInfo* GetUniformInfo(GLint index) const {
|
| + return (static_cast<size_t>(index) < uniform_infos_.size()) ?
|
| + &uniform_infos_[index] : NULL;
|
| + }
|
| +
|
| + // Gets the location of a uniform by name.
|
| + GLint GetUniformLocation(const std::string& name) const;
|
| +
|
| + bool GetProgramiv(GLenum pname, GLint* params);
|
| +
|
| + // Updates the program info after a successful link.
|
| + void Update(GLES2Implementation* gl, GLuint program);
|
| +
|
| + private:
|
| + bool cached_;
|
| +
|
| + GLsizei max_attrib_name_length_;
|
| +
|
| + // Attrib by index.
|
| + AttribInfoVector attrib_infos_;
|
| +
|
| + GLsizei max_uniform_name_length_;
|
| +
|
| + // Uniform info by index.
|
| + UniformInfoVector uniform_infos_;
|
| +
|
| + // This is true if glLinkProgram was successful last time it was called.
|
| + bool link_status_;
|
| + };
|
| +
|
| + ProgramInfo* GetProgramInfo(GLES2Implementation* gl, GLuint program);
|
| +
|
| + // TODO(gman): Switch to a faster container.
|
| + typedef std::map<GLuint, ProgramInfo> ProgramInfoMap;
|
| +
|
| + ProgramInfoMap program_infos_;
|
| +};
|
| +
|
| +CachedProgramInfoManager::ProgramInfo::UniformInfo::UniformInfo(
|
| + GLsizei _size, GLenum _type, const std::string& _name)
|
| + : size(_size),
|
| + type(_type),
|
| + name(_name) {
|
| + is_array = (!name.empty() && name[name.size() - 1] == ']');
|
| + GPU_DCHECK(!(size > 1 && !is_array));
|
| +}
|
| +
|
| +CachedProgramInfoManager::ProgramInfo::ProgramInfo()
|
| + : cached_(false),
|
| + max_attrib_name_length_(0),
|
| + max_uniform_name_length_(0),
|
| + link_status_(false) {
|
| +}
|
| +
|
| +// TODO(gman): Add a faster lookup.
|
| +GLint CachedProgramInfoManager::ProgramInfo::GetAttribLocation(
|
| + const std::string& name) const {
|
| + for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
|
| + const VertexAttribInfo& info = attrib_infos_[ii];
|
| + if (info.name == name) {
|
| + return info.location;
|
| + }
|
| + }
|
| + return -1;
|
| +}
|
| +
|
| +// TODO(gman): Add a faster lookup.
|
| +GLint CachedProgramInfoManager::ProgramInfo::GetUniformLocation(
|
| + const std::string& name) const {
|
| + for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
|
| + const UniformInfo& info = uniform_infos_[ii];
|
| + if (info.name == name ||
|
| + (info.is_array &&
|
| + info.name.compare(0, info.name.size() - 3, name) == 0)) {
|
| + return info.element_locations[0];
|
| + } else if (info.is_array &&
|
| + name.size() >= 3 && name[name.size() - 1] == ']') {
|
| + // Look for an array specification.
|
| + size_t open_pos = name.find_last_of('[');
|
| + if (open_pos != std::string::npos &&
|
| + open_pos < name.size() - 2 &&
|
| + info.name.size() > open_pos &&
|
| + name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
|
| + GLint index = 0;
|
| + size_t last = name.size() - 1;
|
| + bool bad = false;
|
| + for (size_t pos = open_pos + 1; pos < last; ++pos) {
|
| + int8 digit = name[pos] - '0';
|
| + if (digit < 0 || digit > 9) {
|
| + bad = true;
|
| + break;
|
| + }
|
| + index = index * 10 + digit;
|
| + }
|
| + if (!bad && index >= 0 && index < info.size) {
|
| + return info.element_locations[index];
|
| + }
|
| + }
|
| + }
|
| + }
|
| + return -1;
|
| +}
|
| +
|
| +bool CachedProgramInfoManager::ProgramInfo::GetProgramiv(
|
| + GLenum pname, GLint* params) {
|
| + switch (pname) {
|
| + case GL_LINK_STATUS:
|
| + *params = link_status_;
|
| + return true;
|
| + case GL_ACTIVE_ATTRIBUTES:
|
| + *params = attrib_infos_.size();
|
| + return true;
|
| + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
|
| + *params = max_attrib_name_length_;
|
| + return true;
|
| + case GL_ACTIVE_UNIFORMS:
|
| + *params = uniform_infos_.size();
|
| + return true;
|
| + case GL_ACTIVE_UNIFORM_MAX_LENGTH:
|
| + *params = max_uniform_name_length_;
|
| + return true;
|
| + default:
|
| + break;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +template<typename T> static T LocalGetAs(
|
| + const std::vector<int8>& data, uint32 offset, size_t size) {
|
| + const int8* p = &data[0] + offset;
|
| + if (offset + size > data.size()) {
|
| + GPU_NOTREACHED();
|
| + return NULL;
|
| + }
|
| + return static_cast<T>(static_cast<const void*>(p));
|
| +}
|
| +
|
| +void CachedProgramInfoManager::ProgramInfo::Update(
|
| + GLES2Implementation* gl, GLuint program) {
|
| + if (cached_) {
|
| + return;
|
| + }
|
| + std::vector<int8> result;
|
| + gl->GetProgramInfoCHROMIUMHelper(program, &result);
|
| + if (result.empty()) {
|
| + // This should only happen on a lost context.
|
| + return;
|
| + }
|
| + GPU_DCHECK_GE(result.size(), sizeof(ProgramInfoHeader));
|
| + const ProgramInfoHeader* header = LocalGetAs<const ProgramInfoHeader*>(
|
| + result, 0, sizeof(header));
|
| + link_status_ = header->link_status != 0;
|
| + if (!link_status_) {
|
| + return;
|
| + }
|
| + attrib_infos_.clear();
|
| + uniform_infos_.clear();
|
| + max_attrib_name_length_ = 0;
|
| + max_uniform_name_length_ = 0;
|
| + const ProgramInput* inputs = LocalGetAs<const ProgramInput*>(
|
| + result, sizeof(*header),
|
| + sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms));
|
| + const ProgramInput* input = inputs;
|
| + for (uint32 ii = 0; ii < header->num_attribs; ++ii) {
|
| + const int32* location = LocalGetAs<const int32*>(
|
| + result, input->location_offset, sizeof(int32));
|
| + const char* name_buf = LocalGetAs<const char*>(
|
| + result, input->name_offset, input->name_length);
|
| + std::string name(name_buf, input->name_length);
|
| + attrib_infos_.push_back(
|
| + VertexAttribInfo(input->size, input->type, name, *location));
|
| + max_attrib_name_length_ = std::max(
|
| + static_cast<GLsizei>(name.size() + 1), max_attrib_name_length_);
|
| + ++input;
|
| + }
|
| + for (uint32 ii = 0; ii < header->num_uniforms; ++ii) {
|
| + const int32* locations = LocalGetAs<const int32*>(
|
| + result, input->location_offset, sizeof(int32) * input->size);
|
| + const char* name_buf = LocalGetAs<const char*>(
|
| + result, input->name_offset, input->name_length);
|
| + std::string name(name_buf, input->name_length);
|
| + UniformInfo info(input->size, input->type, name);
|
| + max_uniform_name_length_ = std::max(
|
| + static_cast<GLsizei>(name.size() + 1), max_uniform_name_length_);
|
| + for (int32 jj = 0; jj < input->size; ++jj) {
|
| + info.element_locations.push_back(locations[jj]);
|
| + }
|
| + uniform_infos_.push_back(info);
|
| + ++input;
|
| + }
|
| + GPU_DCHECK_EQ(header->num_attribs + header->num_uniforms,
|
| + static_cast<uint32>(input - inputs));
|
| + cached_ = true;
|
| +}
|
| +
|
| +CachedProgramInfoManager::CachedProgramInfoManager() {
|
| +}
|
| +
|
| +CachedProgramInfoManager::~CachedProgramInfoManager() {
|
| +
|
| +}
|
| +
|
| +CachedProgramInfoManager::ProgramInfo*
|
| + CachedProgramInfoManager::GetProgramInfo(
|
| + GLES2Implementation* gl, GLuint program) {
|
| + ProgramInfoMap::iterator it = program_infos_.find(program);
|
| + if (it == program_infos_.end()) {
|
| + return NULL;
|
| + }
|
| + ProgramInfo* info = &it->second;
|
| + info->Update(gl, program);
|
| + return info;
|
| +}
|
| +
|
| +void CachedProgramInfoManager::CreateInfo(GLuint program) {
|
| + DeleteInfo(program);
|
| + std::pair<ProgramInfoMap::iterator, bool> result =
|
| + program_infos_.insert(std::make_pair(program, ProgramInfo()));
|
| +
|
| + GPU_DCHECK(result.second);
|
| +}
|
| +
|
| +void CachedProgramInfoManager::DeleteInfo(GLuint program) {
|
| + program_infos_.erase(program);
|
| +}
|
| +
|
| +bool CachedProgramInfoManager::GetProgramiv(
|
| + GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
|
| + ProgramInfo* info = GetProgramInfo(gl, program);
|
| + if (!info) {
|
| + return false;
|
| + }
|
| + return info->GetProgramiv(pname, params);
|
| +}
|
| +
|
| +GLint CachedProgramInfoManager::GetAttribLocation(
|
| + GLES2Implementation* gl, GLuint program, const char* name) {
|
| + ProgramInfo* info = GetProgramInfo(gl, program);
|
| + if (info) {
|
| + return info->GetAttribLocation(name);
|
| + }
|
| + return gl->GetAttribLocationHelper(program, name);
|
| +}
|
| +
|
| +GLint CachedProgramInfoManager::GetUniformLocation(
|
| + GLES2Implementation* gl, GLuint program, const char* name) {
|
| + ProgramInfo* info = GetProgramInfo(gl, program);
|
| + if (info) {
|
| + return info->GetUniformLocation(name);
|
| + }
|
| + return gl->GetUniformLocationHelper(program, name);
|
| +}
|
| +
|
| +bool CachedProgramInfoManager::GetActiveAttrib(
|
| + GLES2Implementation* gl,
|
| + GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
|
| + GLint* size, GLenum* type, char* name) {
|
| + ProgramInfo* info = GetProgramInfo(gl, program);
|
| + if (info) {
|
| + const ProgramInfo::VertexAttribInfo* attrib_info =
|
| + info->GetAttribInfo(index);
|
| + if (attrib_info) {
|
| + if (size) {
|
| + *size = attrib_info->size;
|
| + }
|
| + if (type) {
|
| + *type = attrib_info->type;
|
| + }
|
| + if (length || name) {
|
| + GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
|
| + std::max(static_cast<size_t>(0),
|
| + attrib_info->name.size()));
|
| + if (length) {
|
| + *length = max_size;
|
| + }
|
| + if (name && bufsize > 0) {
|
| + memcpy(name, attrib_info->name.c_str(), max_size);
|
| + name[max_size] = '\0';
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| + }
|
| + return gl->GetActiveAttribHelper(
|
| + program, index, bufsize, length, size, type, name);
|
| +}
|
| +
|
| +bool CachedProgramInfoManager::GetActiveUniform(
|
| + GLES2Implementation* gl,
|
| + GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
|
| + GLint* size, GLenum* type, char* name) {
|
| + ProgramInfo* info = GetProgramInfo(gl, program);
|
| + if (info) {
|
| + const ProgramInfo::UniformInfo* uniform_info = info->GetUniformInfo(index);
|
| + if (uniform_info) {
|
| + if (size) {
|
| + *size = uniform_info->size;
|
| + }
|
| + if (type) {
|
| + *type = uniform_info->type;
|
| + }
|
| + if (length || name) {
|
| + GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
|
| + std::max(static_cast<size_t>(0),
|
| + uniform_info->name.size()));
|
| + if (length) {
|
| + *length = max_size;
|
| + }
|
| + if (name && bufsize > 0) {
|
| + memcpy(name, uniform_info->name.c_str(), max_size);
|
| + name[max_size] = '\0';
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| + }
|
| + return gl->GetActiveUniformHelper(
|
| + program, index, bufsize, length, size, type, name);
|
| +}
|
| +
|
| +ProgramInfoManager::ProgramInfoManager() {
|
| +}
|
| +
|
| +ProgramInfoManager::~ProgramInfoManager() {
|
| +}
|
| +
|
| +ProgramInfoManager* ProgramInfoManager::Create(bool shared_resources) {
|
| + if (shared_resources) {
|
| + return new NonCachedProgramInfoManager();
|
| + } else {
|
| + return new CachedProgramInfoManager();
|
| + }
|
| +}
|
| +
|
| +} // namespace gles2
|
| +} // namespace gpu
|
|
|
|
|