| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| ===================================================================
|
| --- gpu/command_buffer/service/gles2_cmd_decoder.cc (revision 37873)
|
| +++ gpu/command_buffer/service/gles2_cmd_decoder.cc (working copy)
|
| @@ -35,6 +35,8 @@
|
| GLint_not_same_size_as_uint32);
|
| COMPILE_ASSERT(sizeof(GLsizei) == sizeof(uint32), // NOLINT
|
| GLint_not_same_size_as_uint32);
|
| +COMPILE_ASSERT(sizeof(GLfloat) == sizeof(float), // NOLINT
|
| + GLfloat_not_same_size_as_float);
|
|
|
| namespace {
|
|
|
| @@ -309,6 +311,15 @@
|
| // or if enabled that it points to a valid source.
|
| class ProgramInfo {
|
| public:
|
| + struct UniformInfo {
|
| + GLsizei GetSizeInBytes() const;
|
| +
|
| + GLsizei size;
|
| + GLenum type;
|
| + GLint location;
|
| + };
|
| +
|
| + typedef std::vector<UniformInfo> UniformInfoVector;
|
| typedef std::vector<GLuint> AttribLocationVector;
|
|
|
| ProgramInfo() {
|
| @@ -326,8 +337,34 @@
|
| const AttribLocationVector& GetAttribLocations() const {
|
| return attrib_locations_;
|
| }
|
| +
|
| + void SetNumUniforms(int num_uniforms) {
|
| + uniform_infos_.resize(num_uniforms);
|
| + }
|
| +
|
| + void SetUniformInfo(
|
| + GLint index, GLsizei size, GLenum type, GLint location) {
|
| + UniformInfo& info = uniform_infos_[index];
|
| + info.size = size;
|
| + info.type = type;
|
| + info.location = location;
|
| + }
|
| +
|
| + const UniformInfo* GetUniformInfoByLocation(GLint location) {
|
| + for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
|
| + if (uniform_infos_[ii].location == location) {
|
| + return &uniform_infos_[ii];
|
| + }
|
| + }
|
| + return NULL;
|
| + }
|
| +
|
| +
|
| private:
|
| AttribLocationVector attrib_locations_;
|
| +
|
| + // Uniform info by info.
|
| + UniformInfoVector uniform_infos_;
|
| };
|
|
|
| ProgramInfo* GetProgramInfo(GLuint program);
|
| @@ -345,6 +382,10 @@
|
| ProgramInfoMap program_infos_;
|
| };
|
|
|
| +GLsizei ProgramManager::ProgramInfo::UniformInfo::GetSizeInBytes() const {
|
| + return GLES2Util::GetGLDataTypeSize(type) * size;
|
| +}
|
| +
|
| ProgramManager::ProgramInfo* ProgramManager::GetProgramInfo(GLuint program) {
|
| ProgramInfoMap::iterator it = program_infos_.find(program);
|
| return it != program_infos_.end() ? &it->second : NULL;
|
| @@ -364,17 +405,32 @@
|
| info->SetNumAttributes(num_attribs);
|
| glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
|
| // TODO(gman): Should we check for error?
|
| - scoped_array<char> name_buffer(new char[max_len + 1]);
|
| + scoped_array<char> name_buffer(new char[max_len]);
|
| for (GLint ii = 0; ii < num_attribs; ++ii) {
|
| GLsizei length;
|
| GLsizei size;
|
| GLenum type;
|
| glGetActiveAttrib(
|
| - program, ii, max_len + 1, &length, &size, &type, name_buffer.get());
|
| + program, ii, max_len, &length, &size, &type, name_buffer.get());
|
| // TODO(gman): Should we check for error?
|
| GLint location = glGetAttribLocation(program, name_buffer.get());
|
| info->SetAttributeLocation(ii, location);
|
| }
|
| + GLint num_uniforms;
|
| + glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &num_uniforms);
|
| + info->SetNumUniforms(num_uniforms);
|
| + glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len);
|
| + name_buffer.reset(new char[max_len]);
|
| + for (GLint ii = 0; ii < num_uniforms; ++ii) {
|
| + GLsizei length;
|
| + GLsizei size;
|
| + GLenum type;
|
| + glGetActiveUniform(
|
| + program, ii, max_len, &length, &size, &type, name_buffer.get());
|
| + // TODO(gman): Should we check for error?
|
| + GLint location = glGetUniformLocation(program, name_buffer.get());
|
| + info->SetUniformInfo(ii, size, type, location);
|
| + }
|
| }
|
|
|
| void ProgramManager::RemoveProgramInfo(GLuint program) {
|
| @@ -613,6 +669,14 @@
|
| bound_element_array_buffer_;
|
| }
|
|
|
| + // Validates the program and location for a glGetUniform call and returns
|
| + // a SizeResult setup to receive the result. Returns true if glGetUniform
|
| + // should be called.
|
| + bool GetUniformSetup(
|
| + GLuint program, GLint location,
|
| + uint32 shm_id, uint32 shm_offset,
|
| + error::Error* error, GLuint* service_id, SizedResult** result);
|
| +
|
| // Generate a member function prototype for each command in an automated and
|
| // typesafe way.
|
| #define GLES2_CMD_OP(name) \
|
| @@ -1863,18 +1927,80 @@
|
| return error::kNoError;
|
| }
|
|
|
| +bool GLES2DecoderImpl::GetUniformSetup(
|
| + GLuint program, GLint location,
|
| + uint32 shm_id, uint32 shm_offset,
|
| + error::Error* error, GLuint* service_id, SizedResult** result) {
|
| + *error = error::kNoError;
|
| + // Make sure we have enough room for the result on failure.
|
| + *result = GetSharedMemoryAs<SizedResult*>(
|
| + shm_id, shm_offset, SizedResult::GetSize(0));
|
| + if (!*result) {
|
| + *error = error::kOutOfBounds;
|
| + return false;
|
| + }
|
| + // Set the result size to 0 so the client does not have to check for success.
|
| + (*result)->size = 0;
|
| + if (!id_manager_->GetServiceId(program, service_id)) {
|
| + SetGLError(GL_INVALID_VALUE);
|
| + return error::kNoError;
|
| + }
|
| + ProgramManager::ProgramInfo* info = GetProgramInfo(*service_id);
|
| + if (!info) {
|
| + // Program was not linked successfully. (ie, glLinkProgram)
|
| + SetGLError(GL_INVALID_OPERATION);
|
| + return false;
|
| + }
|
| + const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
|
| + info->GetUniformInfoByLocation(location);
|
| + if (!uniform_info) {
|
| + // No such location.
|
| + SetGLError(GL_INVALID_OPERATION);
|
| + return false;
|
| + }
|
| + GLsizei size = uniform_info->GetSizeInBytes();
|
| + if (size == 0) {
|
| + SetGLError(GL_INVALID_OPERATION);
|
| + return false;
|
| + }
|
| + *result = GetSharedMemoryAs<SizedResult*>(
|
| + shm_id, shm_offset, SizedResult::GetSize(size));
|
| + if (!*result) {
|
| + *error = error::kOutOfBounds;
|
| + return false;
|
| + }
|
| + (*result)->size = size;
|
| + return true;
|
| +}
|
| +
|
| error::Error GLES2DecoderImpl::HandleGetUniformiv(
|
| uint32 immediate_data_size, const gles2::GetUniformiv& c) {
|
| - // TODO(gman): Implement.
|
| - NOTREACHED();
|
| - return error::kNoError;
|
| + GLuint program = c.program;
|
| + GLint location = c.location;
|
| + GLuint service_id;
|
| + Error error;
|
| + SizedResult* result;
|
| + if (GetUniformSetup(
|
| + program, location, c.params_shm_id, c.params_shm_offset,
|
| + &error, &service_id, &result)) {
|
| + glGetUniformiv(service_id, location, result->GetDataAs<GLint*>());
|
| + }
|
| + return error;
|
| }
|
|
|
| error::Error GLES2DecoderImpl::HandleGetUniformfv(
|
| uint32 immediate_data_size, const gles2::GetUniformfv& c) {
|
| - // TODO(gman): Implement.
|
| - NOTREACHED();
|
| - return error::kNoError;
|
| + GLuint program = c.program;
|
| + GLint location = c.location;
|
| + GLuint service_id;
|
| + Error error;
|
| + SizedResult* result;
|
| + if (GetUniformSetup(
|
| + program, location, c.params_shm_id, c.params_shm_offset,
|
| + &error, &service_id, &result)) {
|
| + glGetUniformfv(service_id, location, result->GetDataAs<GLfloat*>());
|
| + }
|
| + return error;
|
| }
|
|
|
| error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
|
|
|