| 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 71963721e523d307ca238045eb1599c89a7663d4..04121aa7346ba275391dc30102909c31d47cf304 100644
|
| --- a/gpu/command_buffer/client/program_info_manager.cc
|
| +++ b/gpu/command_buffer/client/program_info_manager.cc
|
| @@ -44,11 +44,23 @@ ProgramInfoManager::Program::UniformInfo::UniformInfo(
|
| ProgramInfoManager::Program::UniformInfo::~UniformInfo() {
|
| }
|
|
|
| +ProgramInfoManager::Program::UniformBlock::UniformBlock()
|
| + : binding(0),
|
| + data_size(0),
|
| + referenced_by_vertex_shader(false),
|
| + referenced_by_fragment_shader(false) {
|
| +}
|
| +
|
| +ProgramInfoManager::Program::UniformBlock::~UniformBlock() {
|
| +}
|
| +
|
| ProgramInfoManager::Program::Program()
|
| - : cached_(false),
|
| + : cached_es2_(false),
|
| max_attrib_name_length_(0),
|
| max_uniform_name_length_(0),
|
| - link_status_(false) {
|
| + link_status_(false),
|
| + cached_es3_uniform_blocks_(false),
|
| + active_uniform_block_max_name_length_(0) {
|
| }
|
|
|
| ProgramInfoManager::Program::~Program() {
|
| @@ -78,6 +90,11 @@ ProgramInfoManager::Program::GetUniformInfo(GLint index) const {
|
| &uniform_infos_[index] : NULL;
|
| }
|
|
|
| +const ProgramInfoManager::Program::UniformBlock*
|
| +ProgramInfoManager::Program::GetUniformBlock(GLuint index) const {
|
| + return (index < uniform_blocks_.size()) ? &uniform_blocks_[index] : NULL;
|
| +}
|
| +
|
| GLint ProgramInfoManager::Program::GetUniformLocation(
|
| const std::string& name) const {
|
| bool getting_array_location = false;
|
| @@ -125,31 +142,45 @@ bool ProgramInfoManager::Program::GetProgramiv(
|
| GLenum pname, GLint* params) {
|
| switch (pname) {
|
| case GL_LINK_STATUS:
|
| - *params = link_status_;
|
| + *params = static_cast<GLint>(link_status_);
|
| return true;
|
| case GL_ACTIVE_ATTRIBUTES:
|
| - *params = attrib_infos_.size();
|
| + *params = static_cast<GLint>(attrib_infos_.size());
|
| return true;
|
| case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
|
| - *params = max_attrib_name_length_;
|
| + *params = static_cast<GLint>(max_attrib_name_length_);
|
| return true;
|
| case GL_ACTIVE_UNIFORMS:
|
| - *params = uniform_infos_.size();
|
| + *params = static_cast<GLint>(uniform_infos_.size());
|
| return true;
|
| case GL_ACTIVE_UNIFORM_MAX_LENGTH:
|
| - *params = max_uniform_name_length_;
|
| + *params = static_cast<GLint>(max_uniform_name_length_);
|
| + return true;
|
| + case GL_ACTIVE_UNIFORM_BLOCKS:
|
| + *params = static_cast<GLint>(uniform_blocks_.size());
|
| + return true;
|
| + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
|
| + *params = static_cast<GLint>(active_uniform_block_max_name_length_);
|
| return true;
|
| default:
|
| + NOTREACHED();
|
| break;
|
| }
|
| return false;
|
| }
|
|
|
| -void ProgramInfoManager::Program::Update(
|
| - GLES2Implementation* gl,
|
| - GLuint program,
|
| - const std::vector<int8>& result) {
|
| - if (cached_) {
|
| +GLuint ProgramInfoManager::Program::GetUniformBlockIndex(
|
| + const std::string& name) const {
|
| + for (size_t ii = 0; ii < uniform_blocks_.size(); ++ii) {
|
| + if (uniform_blocks_[ii].name == name) {
|
| + return static_cast<GLuint>(ii);
|
| + }
|
| + }
|
| + return GL_INVALID_INDEX;
|
| +}
|
| +
|
| +void ProgramInfoManager::Program::UpdateES2(const std::vector<int8>& result) {
|
| + if (cached_es2_) {
|
| return;
|
| }
|
| if (result.empty()) {
|
| @@ -200,12 +231,93 @@ void ProgramInfoManager::Program::Update(
|
| ++input;
|
| }
|
| DCHECK_EQ(header->num_attribs + header->num_uniforms,
|
| - static_cast<uint32>(input - inputs));
|
| - cached_ = true;
|
| + static_cast<uint32>(input - inputs));
|
| + cached_es2_ = true;
|
| }
|
|
|
| -bool ProgramInfoManager::Program::cached() const {
|
| - return cached_;
|
| +void ProgramInfoManager::Program::UpdateES3UniformBlocks(
|
| + const std::vector<int8>& result) {
|
| + if (cached_es3_uniform_blocks_) {
|
| + return;
|
| + }
|
| + if (result.empty()) {
|
| + // This should only happen on a lost context.
|
| + return;
|
| + }
|
| + uniform_blocks_.clear();
|
| + active_uniform_block_max_name_length_ = 0;
|
| +
|
| + // |result| comes from GPU process. We consider it trusted data. Therefore,
|
| + // no need to check for overflows as the GPU side did the checks already.
|
| + uint32_t header_size = sizeof(UniformBlocksHeader);
|
| + DCHECK_GE(result.size(), header_size);
|
| + const UniformBlocksHeader* header = LocalGetAs<const UniformBlocksHeader*>(
|
| + result, 0, header_size);
|
| + DCHECK(header);
|
| + if (header->num_uniform_blocks == 0) {
|
| + DCHECK_EQ(result.size(), header_size);
|
| + // TODO(zmo): Here we can't tell if no uniform blocks are defined, or
|
| + // the previous link failed.
|
| + return;
|
| + }
|
| + uniform_blocks_.resize(header->num_uniform_blocks);
|
| +
|
| + uint32_t entry_size = sizeof(UniformBlockInfo) * header->num_uniform_blocks;
|
| + DCHECK_GE(result.size(), header_size + entry_size);
|
| + uint32_t data_size = result.size() - header_size - entry_size;
|
| + DCHECK_LT(0u, data_size);
|
| + const UniformBlockInfo* entries = LocalGetAs<const UniformBlockInfo*>(
|
| + result, header_size, entry_size);
|
| + DCHECK(entries);
|
| + const char* data = LocalGetAs<const char*>(
|
| + result, header_size + entry_size, data_size);
|
| + DCHECK(data);
|
| +
|
| + uint32_t size = 0;
|
| + for (uint32_t ii = 0; ii < header->num_uniform_blocks; ++ii) {
|
| + uniform_blocks_[ii].binding = static_cast<GLuint>(entries[ii].binding);
|
| + uniform_blocks_[ii].data_size = static_cast<GLuint>(entries[ii].data_size);
|
| + uniform_blocks_[ii].active_uniform_indices.resize(
|
| + entries[ii].active_uniforms);
|
| + uniform_blocks_[ii].referenced_by_vertex_shader = static_cast<GLboolean>(
|
| + entries[ii].referenced_by_vertex_shader);
|
| + uniform_blocks_[ii].referenced_by_fragment_shader = static_cast<GLboolean>(
|
| + entries[ii].referenced_by_fragment_shader);
|
| + // Uniform block names can't be empty strings.
|
| + DCHECK_LT(1u, entries[ii].name_length);
|
| + if (entries[ii].name_length > active_uniform_block_max_name_length_) {
|
| + active_uniform_block_max_name_length_ = entries[ii].name_length;
|
| + }
|
| + size += entries[ii].name_length;
|
| + DCHECK_GE(data_size, size);
|
| + uniform_blocks_[ii].name = std::string(data, entries[ii].name_length - 1);
|
| + data += entries[ii].name_length;
|
| + size += entries[ii].active_uniforms * sizeof(uint32_t);
|
| + DCHECK_GE(data_size, size);
|
| + const uint32_t* indices = reinterpret_cast<const uint32_t*>(data);
|
| + for (uint32_t uu = 0; uu < entries[ii].active_uniforms; ++uu) {
|
| + uniform_blocks_[ii].active_uniform_indices[uu] =
|
| + static_cast<GLuint>(indices[uu]);
|
| + }
|
| + indices += entries[ii].active_uniforms;
|
| + data = reinterpret_cast<const char*>(indices);
|
| + }
|
| + DCHECK_EQ(data_size, size);
|
| + cached_es3_uniform_blocks_ = true;
|
| +}
|
| +
|
| +bool ProgramInfoManager::Program::IsCached(ProgramInfoType type) const {
|
| + switch (type) {
|
| + case kES2:
|
| + return cached_es2_;
|
| + case kES3UniformBlocks:
|
| + return cached_es3_uniform_blocks_;
|
| + case kNone:
|
| + return true;
|
| + default:
|
| + NOTREACHED();
|
| + return true;
|
| + }
|
| }
|
|
|
|
|
| @@ -216,29 +328,42 @@ ProgramInfoManager::~ProgramInfoManager() {
|
| }
|
|
|
| ProgramInfoManager::Program* ProgramInfoManager::GetProgramInfo(
|
| - GLES2Implementation* gl, GLuint program) {
|
| + GLES2Implementation* gl, GLuint program, ProgramInfoType type) {
|
| lock_.AssertAcquired();
|
| ProgramInfoMap::iterator it = program_infos_.find(program);
|
| if (it == program_infos_.end()) {
|
| return NULL;
|
| }
|
| Program* info = &it->second;
|
| - if (info->cached())
|
| + if (info->IsCached(type))
|
| return info;
|
| - std::vector<int8> result;
|
| - {
|
| - base::AutoUnlock unlock(lock_);
|
| - // lock_ can't be held across IPC call or else it may deadlock in pepper.
|
| - // http://crbug.com/418651
|
| - gl->GetProgramInfoCHROMIUMHelper(program, &result);
|
| - }
|
|
|
| - it = program_infos_.find(program);
|
| - if (it == program_infos_.end()) {
|
| - return NULL;
|
| + std::vector<int8> result;
|
| + switch (type) {
|
| + case kES2:
|
| + {
|
| + base::AutoUnlock unlock(lock_);
|
| + // lock_ can't be held across IPC call or else it may deadlock in
|
| + // pepper. http://crbug.com/418651
|
| + gl->GetProgramInfoCHROMIUMHelper(program, &result);
|
| + }
|
| + info->UpdateES2(result);
|
| + break;
|
| + case kES3UniformBlocks:
|
| + {
|
| + base::AutoUnlock unlock(lock_);
|
| + // lock_ can't be held across IPC call or else it may deadlock in
|
| + // pepper. http://crbug.com/418651
|
| +
|
| + // TODO(zmo): Uncomment the below line once GetUniformBlocksCHROMIUM
|
| + // command is implemented.
|
| + // gl->GetUniformBlocksCHROMIUMHeler(program, &result);
|
| + }
|
| + info->UpdateES3UniformBlocks(result);
|
| + default:
|
| + NOTREACHED();
|
| + return NULL;
|
| }
|
| - info = &it->second;
|
| - info->Update(gl, program, result);
|
| return info;
|
| }
|
|
|
| @@ -259,7 +384,23 @@ void ProgramInfoManager::DeleteInfo(GLuint program) {
|
| bool ProgramInfoManager::GetProgramiv(
|
| GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
|
| base::AutoLock auto_lock(lock_);
|
| - Program* info = GetProgramInfo(gl, program);
|
| + ProgramInfoType type = kNone;
|
| + switch (pname) {
|
| + case GL_ACTIVE_ATTRIBUTES:
|
| + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
|
| + case GL_ACTIVE_UNIFORMS:
|
| + case GL_ACTIVE_UNIFORM_MAX_LENGTH:
|
| + case GL_LINK_STATUS:
|
| + type = kES2;
|
| + break;
|
| + case GL_ACTIVE_UNIFORM_BLOCKS:
|
| + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
|
| + type = kES3UniformBlocks;
|
| + break;
|
| + default:
|
| + return false;
|
| + }
|
| + Program* info = GetProgramInfo(gl, program, type);
|
| if (!info) {
|
| return false;
|
| }
|
| @@ -270,7 +411,7 @@ GLint ProgramInfoManager::GetAttribLocation(
|
| GLES2Implementation* gl, GLuint program, const char* name) {
|
| {
|
| base::AutoLock auto_lock(lock_);
|
| - Program* info = GetProgramInfo(gl, program);
|
| + Program* info = GetProgramInfo(gl, program, kES2);
|
| if (info) {
|
| return info->GetAttribLocation(name);
|
| }
|
| @@ -282,7 +423,7 @@ GLint ProgramInfoManager::GetUniformLocation(
|
| GLES2Implementation* gl, GLuint program, const char* name) {
|
| {
|
| base::AutoLock auto_lock(lock_);
|
| - Program* info = GetProgramInfo(gl, program);
|
| + Program* info = GetProgramInfo(gl, program, kES2);
|
| if (info) {
|
| return info->GetUniformLocation(name);
|
| }
|
| @@ -296,7 +437,7 @@ GLint ProgramInfoManager::GetFragDataLocation(
|
| // fetched altogether from the service side. See crbug.com/452104.
|
| {
|
| base::AutoLock auto_lock(lock_);
|
| - Program* info = GetProgramInfo(gl, program);
|
| + Program* info = GetProgramInfo(gl, program, kNone);
|
| if (info) {
|
| GLint possible_loc = info->GetFragDataLocation(name);
|
| if (possible_loc != -1)
|
| @@ -306,7 +447,7 @@ GLint ProgramInfoManager::GetFragDataLocation(
|
| GLint loc = gl->GetFragDataLocationHelper(program, name);
|
| if (loc != -1) {
|
| base::AutoLock auto_lock(lock_);
|
| - Program* info = GetProgramInfo(gl, program);
|
| + Program* info = GetProgramInfo(gl, program, kNone);
|
| if (info) {
|
| info->CacheFragDataLocation(name, loc);
|
| }
|
| @@ -320,7 +461,7 @@ bool ProgramInfoManager::GetActiveAttrib(
|
| GLint* size, GLenum* type, char* name) {
|
| {
|
| base::AutoLock auto_lock(lock_);
|
| - Program* info = GetProgramInfo(gl, program);
|
| + Program* info = GetProgramInfo(gl, program, kES2);
|
| if (info) {
|
| const Program::VertexAttrib* attrib_info = info->GetAttribInfo(index);
|
| if (attrib_info) {
|
| @@ -356,7 +497,7 @@ bool ProgramInfoManager::GetActiveUniform(
|
| GLint* size, GLenum* type, char* name) {
|
| {
|
| base::AutoLock auto_lock(lock_);
|
| - Program* info = GetProgramInfo(gl, program);
|
| + Program* info = GetProgramInfo(gl, program, kES2);
|
| if (info) {
|
| const Program::UniformInfo* uniform_info = info->GetUniformInfo(index);
|
| if (uniform_info) {
|
| @@ -386,6 +527,119 @@ bool ProgramInfoManager::GetActiveUniform(
|
| program, index, bufsize, length, size, type, name);
|
| }
|
|
|
| +GLuint ProgramInfoManager::GetUniformBlockIndex(
|
| + GLES2Implementation* gl, GLuint program, const char* name) {
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
|
| + if (info) {
|
| + return info->GetUniformBlockIndex(name);
|
| + }
|
| + }
|
| + return gl->GetUniformBlockIndexHelper(program, name);
|
| +}
|
| +
|
| +bool ProgramInfoManager::GetActiveUniformBlockName(
|
| + GLES2Implementation* gl, GLuint program, GLuint index,
|
| + GLsizei buf_size, GLsizei* length, char* name) {
|
| + DCHECK_LE(0, buf_size);
|
| + if (!name) {
|
| + buf_size = 0;
|
| + }
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
|
| + if (info) {
|
| + const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
|
| + if (uniform_block) {
|
| + if (buf_size == 0) {
|
| + if (length) {
|
| + *length = 0;
|
| + }
|
| + } else if (length || name) {
|
| + GLsizei max_size = std::min(
|
| + buf_size - 1, static_cast<GLsizei>(uniform_block->name.size()));
|
| + if (length) {
|
| + *length = max_size;
|
| + }
|
| + if (name) {
|
| + memcpy(name, uniform_block->name.data(), max_size);
|
| + name[max_size] = '\0';
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + return gl->GetActiveUniformBlockNameHelper(
|
| + program, index, buf_size, length, name);
|
| +}
|
| +
|
| +bool ProgramInfoManager::GetActiveUniformBlockiv(
|
| + GLES2Implementation* gl, GLuint program, GLuint index,
|
| + GLenum pname, GLint* params) {
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
|
| + if (info) {
|
| + const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
|
| + bool valid_pname;
|
| + switch (pname) {
|
| + case GL_UNIFORM_BLOCK_BINDING:
|
| + case GL_UNIFORM_BLOCK_DATA_SIZE:
|
| + case GL_UNIFORM_BLOCK_NAME_LENGTH:
|
| + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
|
| + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
|
| + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
|
| + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
|
| + valid_pname = true;
|
| + break;
|
| + default:
|
| + valid_pname = false;
|
| + break;
|
| + }
|
| + if (uniform_block && valid_pname && params) {
|
| + switch (pname) {
|
| + case GL_UNIFORM_BLOCK_BINDING:
|
| + *params = static_cast<GLint>(uniform_block->binding);
|
| + break;
|
| + case GL_UNIFORM_BLOCK_DATA_SIZE:
|
| + *params = static_cast<GLint>(uniform_block->data_size);
|
| + break;
|
| + case GL_UNIFORM_BLOCK_NAME_LENGTH:
|
| + *params = static_cast<GLint>(uniform_block->name.size()) + 1;
|
| + break;
|
| + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
|
| + *params = static_cast<GLint>(
|
| + uniform_block->active_uniform_indices.size());
|
| + break;
|
| + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
|
| + for (size_t ii = 0;
|
| + ii < uniform_block->active_uniform_indices.size(); ++ii) {
|
| + params[ii] = static_cast<GLint>(
|
| + uniform_block->active_uniform_indices[ii]);
|
| + }
|
| + break;
|
| + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
|
| + *params = static_cast<GLint>(
|
| + uniform_block->referenced_by_vertex_shader);
|
| + break;
|
| + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
|
| + *params = static_cast<GLint>(
|
| + uniform_block->referenced_by_fragment_shader);
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| + // TODO(zmo): return gl->GetActiveUniformBlockivHelper(
|
| + // program, index, pname, params);
|
| +}
|
| +
|
| } // namespace gles2
|
| } // namespace gpu
|
|
|
|
|