diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-05 23:02:25 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-05 23:02:25 +0000 |
commit | 0bfd9882d39c63727676616ef1401d7618fdd26c (patch) | |
tree | f81bccc6d5a6f652cb600d5b61fa95b72181a513 /gpu/command_buffer/service | |
parent | ed0cf569f40ba5e11402c691c6bef6304d3d45c6 (diff) | |
download | chromium_src-0bfd9882d39c63727676616ef1401d7618fdd26c.zip chromium_src-0bfd9882d39c63727676616ef1401d7618fdd26c.tar.gz chromium_src-0bfd9882d39c63727676616ef1401d7618fdd26c.tar.bz2 |
Adds
glGetActiveAttrib
glGetActiveUniform
glGetAttachedShaders
glGetShaderPrecision
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/577017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38270 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer/service')
-rw-r--r-- | gpu/command_buffer/service/common_decoder.cc | 21 | ||||
-rw-r--r-- | gpu/command_buffer/service/common_decoder.h | 13 | ||||
-rw-r--r-- | gpu/command_buffer/service/gl_utils.h | 16 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 437 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc | 571 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_validation_autogen.h | 2 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h | 8 |
7 files changed, 835 insertions, 233 deletions
diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc index 6b2d116..3dbe967 100644 --- a/gpu/command_buffer/service/common_decoder.cc +++ b/gpu/command_buffer/service/common_decoder.cc @@ -32,6 +32,11 @@ bool CommonDecoder::Bucket::SetData( return false; } +void CommonDecoder::Bucket::SetFromString(const std::string& str) { + SetSize(str.size()); + SetData(str.c_str(), 0, str.size()); +} + void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id, unsigned int offset, unsigned int size) { @@ -66,6 +71,15 @@ CommonDecoder::Bucket* CommonDecoder::GetBucket(uint32 bucket_id) const { return iter != buckets_.end() ? &(*iter->second) : NULL; } +CommonDecoder::Bucket* CommonDecoder::CreateBucket(uint32 bucket_id) { + Bucket* bucket = GetBucket(bucket_id); + if (!bucket) { + bucket = new Bucket(); + buckets_[bucket_id] = linked_ptr<Bucket>(bucket); + } + return bucket; +} + namespace { // Returns the address of the first byte after a struct. @@ -202,12 +216,7 @@ error::Error CommonDecoder::HandleSetBucketSize( uint32 bucket_id = args.bucket_id; uint32 size = args.size; - Bucket* bucket = GetBucket(bucket_id); - if (!bucket) { - bucket = new Bucket(); - buckets_[bucket_id] = linked_ptr<Bucket>(bucket); - } - + Bucket* bucket = CreateBucket(bucket_id); bucket->SetSize(size); return error::kNoError; } diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h index f4c0e67..2300e5a 100644 --- a/gpu/command_buffer/service/common_decoder.h +++ b/gpu/command_buffer/service/common_decoder.h @@ -7,6 +7,7 @@ #include <map> #include <stack> +#include <string> #include "base/linked_ptr.h" #include "base/scoped_ptr.h" #include "gpu/command_buffer/service/cmd_parser.h" @@ -70,6 +71,9 @@ class CommonDecoder : public AsyncAPIInterface { // Returns false if offset or size is out of range. bool SetData(const void* src, size_t offset, size_t size); + // Sets the bucket data from a string. + void SetFromString(const std::string& str); + private: bool OffsetSizeValid(size_t offset, size_t size) const { size_t temp = offset + size; @@ -93,6 +97,9 @@ class CommonDecoder : public AsyncAPIInterface { engine_ = engine; } + // Gets a bucket. Returns NULL if the bucket does not exist. + Bucket* GetBucket(uint32 bucket_id) const; + protected: // Executes a common command. // Parameters: @@ -131,14 +138,14 @@ class CommonDecoder : public AsyncAPIInterface { // Gets an name for a common command. const char* GetCommonCommandName(cmd::CommandId command_id) const; - // Gets a bucket. Returns NULL if the bucket does not exist. - Bucket* GetBucket(uint32 bucket_id) const; + // Creates a bucket. If the bucket already exists returns that bucket. + Bucket* CreateBucket(uint32 bucket_id); private: // Generate a member function prototype for each command in an automated and // typesafe way. #define COMMON_COMMAND_BUFFER_CMD_OP(name) \ - error::Error Handle ## name( \ + error::Error Handle##name( \ uint32 immediate_data_size, \ const cmd::name& args); \ diff --git a/gpu/command_buffer/service/gl_utils.h b/gpu/command_buffer/service/gl_utils.h index 65df9f5..6edc287 100644 --- a/gpu/command_buffer/service/gl_utils.h +++ b/gpu/command_buffer/service/gl_utils.h @@ -13,12 +13,22 @@ #if defined(UNIT_TEST) #include "gpu/command_buffer/service/gl_mock.h" #else -#include <GL/glew.h> +#include <GL/glew.h> // NOLINT #if defined(OS_WIN) -#include <GL/wglew.h> +#include <GL/wglew.h> // NOLINT #elif defined(OS_LINUX) -#include <GL/glxew.h> +#include <GL/glxew.h> // NOLINT #endif // OS_WIN + +// GLES2 defines not part of Desktop GL +// Shader Precision-Specified Types +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 + #endif // UNIT_TEST #define GL_GLEXT_PROTOTYPES 1 diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 684e579..adfea53 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -9,8 +9,9 @@ #include <vector> #include <string> #include <map> -#include <build/build_config.h> +#include <build/build_config.h> // NOLINT #include "base/scoped_ptr.h" +#include "base/string_util.h" #define GLES2_GPU_SERVICE 1 #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -68,6 +69,12 @@ static size_t GetGLTypeSize(GLenum type) { } } +bool IsInvalidPrefix(const char* name, size_t length) { + static const char kInvalidPrefix[] = { 'g', 'l', '_' }; + return (length >= sizeof(kInvalidPrefix) && + memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0); +} + // Returns the address of the first byte after a struct. template <typename T> const void* AddressAfterStruct(const T& pod) { @@ -323,30 +330,142 @@ class ProgramManager { class ProgramInfo { public: struct UniformInfo { - GLsizei GetSizeInBytes() const; - + GLsizei size; + GLenum type; + std::string name; + std::vector<GLint> element_locations; + }; + struct VertexAttribInfo { GLsizei size; GLenum type; GLint location; + std::string name; }; typedef std::vector<UniformInfo> UniformInfoVector; - typedef std::vector<GLuint> AttribLocationVector; + typedef std::vector<VertexAttribInfo> AttribInfoVector; - ProgramInfo() { + explicit ProgramInfo(GLuint program) + : program_(program) { } - void SetNumAttributes(int num_attribs) { - attrib_locations_.resize(num_attribs); + void Update() { + GLint num_attribs = 0; + GLint max_len = 0; + glGetProgramiv(program_, GL_ACTIVE_ATTRIBUTES, &num_attribs); + 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]); + for (GLint ii = 0; ii < num_attribs; ++ii) { + GLsizei length; + GLsizei size; + GLenum type; + glGetActiveAttrib( + program_, ii, max_len, &length, &size, &type, name_buffer.get()); + // TODO(gman): Should we check for error? + GLint location = IsInvalidPrefix(name_buffer.get(), length) ? -1 : + glGetAttribLocation(program_, name_buffer.get()); + SetAttributeInfo(ii, size, type, location, name_buffer.get()); + } + GLint num_uniforms; + glGetProgramiv(program_, GL_ACTIVE_UNIFORMS, &num_uniforms); + 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 = IsInvalidPrefix(name_buffer.get(), length) ? -1 : + glGetUniformLocation(program_, name_buffer.get()); + SetUniformInfo(ii, size, type, location, name_buffer.get()); + } } - void SetAttributeLocation(GLuint index, int location) { - DCHECK(index < attrib_locations_.size()); - attrib_locations_[index] = location; + 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) { + for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { + const VertexAttribInfo& info = attrib_infos_[ii]; + if (info.name == name) { + return info.location; + } + } + return -1; + } + + const UniformInfo* GetUniformInfo(GLint index) const { + return (static_cast<size_t>(index) < uniform_infos_.size()) ? + &uniform_infos_[index] : NULL; + } + + GLint GetUniformLocation(const std::string& name) { + for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { + const UniformInfo& info = uniform_infos_[ii]; + if (info.name == name) { + return info.element_locations[0]; + } else if (name.size() >= 3 && name[name.size() - 1] == ']') { + // Look for an array specfication. + size_t open_pos = name.find_last_of('['); + if (open_pos != std::string::npos && open_pos < name.size() - 2) { + GLuint 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) { + return index; + } + } + } + } + return -1; + } + + bool GetUniformTypeByLocation(GLint location, GLenum* type) const { + for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { + const UniformInfo& info = uniform_infos_[ii]; + for (GLsizei jj = 0; jj < info.size; ++jj) { + if (info.element_locations[jj] == location) { + *type = info.type; + return true; + } + } + } + return false; + } + + private: + void SetNumAttributes(int num_attribs) { + attrib_infos_.resize(num_attribs); } - const AttribLocationVector& GetAttribLocations() const { - return attrib_locations_; + void SetAttributeInfo( + GLint index, GLsizei size, GLenum type, GLint location, + const std::string& name) { + DCHECK(static_cast<unsigned>(index) < attrib_infos_.size()); + VertexAttribInfo& info = attrib_infos_[index]; + info.size = size; + info.type = type; + info.name = name; + info.location = location; } void SetNumUniforms(int num_uniforms) { @@ -354,28 +473,34 @@ class ProgramManager { } void SetUniformInfo( - GLint index, GLsizei size, GLenum type, GLint location) { + GLint index, GLsizei size, GLenum type, GLint location, + const std::string& name) { + DCHECK(static_cast<unsigned>(index) < uniform_infos_.size()); 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]; + info.name = name; + info.element_locations.resize(size); + info.element_locations[0] = location; + // Go through the array element locations looking for a match. + // We can skip the first element because it's the same as the + // the location without the array operators. + if (size > 1) { + for (GLsizei ii = 1; ii < info.size; ++ii) { + std::string element_name(name + "[" + IntToString(ii) + "]"); + info.element_locations[ii] = + glGetUniformLocation(program_, element_name.c_str()); } } - return NULL; } - - private: - AttribLocationVector attrib_locations_; + AttribInfoVector attrib_infos_; // Uniform info by info. UniformInfoVector uniform_infos_; + + // The program this ProgramInfo is tracking. + GLuint program_; }; ProgramInfo* GetProgramInfo(GLuint program); @@ -393,10 +518,6 @@ class ProgramManager { 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; @@ -406,42 +527,11 @@ void ProgramManager::UpdateProgramInfo(GLuint program) { ProgramInfo* info = GetProgramInfo(program); if (!info) { std::pair<ProgramInfoMap::iterator, bool> result = - program_infos_.insert(std::make_pair(program, ProgramInfo())); + program_infos_.insert(std::make_pair(program, ProgramInfo(program))); DCHECK(result.second); info = &result.first->second; } - GLint num_attribs = 0; - GLint max_len = 0; - glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &num_attribs); - 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]); - for (GLint ii = 0; ii < num_attribs; ++ii) { - GLsizei length; - GLsizei size; - GLenum type; - glGetActiveAttrib( - 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); - } + info->Update(); } void ProgramManager::RemoveProgramInfo(GLuint program) { @@ -693,7 +783,7 @@ class GLES2DecoderImpl : public GLES2Decoder { bool GetUniformSetup( GLuint program, GLint location, uint32 shm_id, uint32 shm_offset, - error::Error* error, GLuint* service_id, SizedResult** result); + error::Error* error, GLuint* service_id, void** result); // Generate a member function prototype for each command in an automated and // typesafe way. @@ -1647,11 +1737,14 @@ bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) { return false; } // Validate that all attribs current program needs are setup correctly. - const ProgramManager::ProgramInfo::AttribLocationVector& locations = - info->GetAttribLocations(); - for (size_t ii = 0; ii < locations.size(); ++ii) { - GLuint location = locations[ii]; - DCHECK_LT(location, max_vertex_attribs_); + const ProgramManager::ProgramInfo::AttribInfoVector& infos = + info->GetAttribInfos(); + for (size_t ii = 0; ii < infos.size(); ++ii) { + GLint location = infos[ii].location; + if (location < 0) { + return false; + } + DCHECK_LT(static_cast<GLuint>(location), max_vertex_attribs_); if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) { SetGLError(GL_INVALID_OPERATION); return false; @@ -1875,6 +1968,12 @@ error::Error GLES2DecoderImpl::HandleGetAttribLocation( SetGLError(GL_INVALID_VALUE); return error::kNoError; } + ProgramManager::ProgramInfo* info = GetProgramInfo(program); + if (!info) { + // Program was not linked successfully. (ie, glLinkProgram) + SetGLError(GL_INVALID_OPERATION); + return error::kNoError; + } uint32 name_size = c.data_size; const char* name = GetSharedMemoryAs<const char*>( c.name_shm_id, c.name_shm_offset, name_size); @@ -1884,7 +1983,7 @@ error::Error GLES2DecoderImpl::HandleGetAttribLocation( return error::kOutOfBounds; } String name_str(name, name_size); - *location = glGetAttribLocation(program, name_str.c_str()); + *location = info->GetAttribLocation(name_str); return error::kNoError; } @@ -1895,6 +1994,12 @@ error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate( SetGLError(GL_INVALID_VALUE); return error::kNoError; } + ProgramManager::ProgramInfo* info = GetProgramInfo(program); + if (!info) { + // Program was not linked successfully. (ie, glLinkProgram) + SetGLError(GL_INVALID_OPERATION); + return error::kNoError; + } uint32 name_size = c.data_size; const char* name = GetImmediateDataAs<const char*>( c, name_size, immediate_data_size); @@ -1904,7 +2009,7 @@ error::Error GLES2DecoderImpl::HandleGetAttribLocationImmediate( return error::kOutOfBounds; } String name_str(name, name_size); - *location = glGetAttribLocation(program, name_str.c_str()); + *location = info->GetAttribLocation(name_str); return error::kNoError; } @@ -1915,6 +2020,12 @@ error::Error GLES2DecoderImpl::HandleGetUniformLocation( SetGLError(GL_INVALID_VALUE); return error::kNoError; } + ProgramManager::ProgramInfo* info = GetProgramInfo(program); + if (!info) { + // Program was not linked successfully. (ie, glLinkProgram) + SetGLError(GL_INVALID_OPERATION); + return error::kNoError; + } uint32 name_size = c.data_size; const char* name = GetSharedMemoryAs<const char*>( c.name_shm_id, c.name_shm_offset, name_size); @@ -1924,7 +2035,7 @@ error::Error GLES2DecoderImpl::HandleGetUniformLocation( return error::kOutOfBounds; } String name_str(name, name_size); - *location = glGetUniformLocation(program, name_str.c_str()); + *location = info->GetUniformLocation(name_str); return error::kNoError; } @@ -1935,6 +2046,12 @@ error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate( SetGLError(GL_INVALID_VALUE); return error::kNoError; } + ProgramManager::ProgramInfo* info = GetProgramInfo(program); + if (!info) { + // Program was not linked successfully. (ie, glLinkProgram) + SetGLError(GL_INVALID_OPERATION); + return error::kNoError; + } uint32 name_size = c.data_size; const char* name = GetImmediateDataAs<const char*>( c, name_size, immediate_data_size); @@ -1944,7 +2061,7 @@ error::Error GLES2DecoderImpl::HandleGetUniformLocationImmediate( return error::kOutOfBounds; } String name_str(name, name_size); - *location = glGetUniformLocation(program, name_str.c_str()); + *location = info->GetUniformLocation(name_str); return error::kNoError; } @@ -2145,8 +2262,9 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv( uint32 immediate_data_size, const gles2::GetVertexAttribPointerv& c) { GLuint index = static_cast<GLuint>(c.index); GLenum pname = static_cast<GLenum>(c.pname); - SizedResult* result = GetSharedMemoryAs<SizedResult*>( - c.pointer_shm_id, c.pointer_shm_offset, sizeof(SizedResult)); + typedef gles2::GetVertexAttribPointerv::Result Result; + Result* result = GetSharedMemoryAs<Result*>( + c.pointer_shm_id, c.pointer_shm_offset, Result::ComputeSize(1)); if (!result) { return error::kOutOfBounds; } @@ -2159,25 +2277,27 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv( SetGLError(GL_INVALID_VALUE); return error::kNoError; } - result->size = sizeof(GLuint); - *result->GetDataAs<GLuint*>() = vertex_attrib_infos_[index].offset(); + result->SetNumResults(1); + *result->GetData() = vertex_attrib_infos_[index].offset(); 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* error, GLuint* service_id, void** result_pointer) { *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) { + SizedResult<GLint>* result; + result = GetSharedMemoryAs<SizedResult<GLint>*>( + shm_id, shm_offset, SizedResult<GLint>::ComputeSize(0)); + if (!result) { *error = error::kOutOfBounds; return false; } + *result_pointer = result; // Set the result size to 0 so the client does not have to check for success. - (*result)->size = 0; + result->SetNumResults(0); if (!id_manager_->GetServiceId(program, service_id)) { SetGLError(GL_INVALID_VALUE); return error::kNoError; @@ -2188,25 +2308,24 @@ bool GLES2DecoderImpl::GetUniformSetup( SetGLError(GL_INVALID_OPERATION); return false; } - const ProgramManager::ProgramInfo::UniformInfo* uniform_info = - info->GetUniformInfoByLocation(location); - if (!uniform_info) { + GLenum type; + if (!info->GetUniformTypeByLocation(location, &type)) { // No such location. SetGLError(GL_INVALID_OPERATION); return false; } - GLsizei size = uniform_info->GetSizeInBytes(); + GLsizei size = GLES2Util::GetGLDataTypeSize(type); if (size == 0) { SetGLError(GL_INVALID_OPERATION); return false; } - *result = GetSharedMemoryAs<SizedResult*>( - shm_id, shm_offset, SizedResult::GetSize(size)); - if (!*result) { + result = GetSharedMemoryAs<SizedResult<GLint>*>( + shm_id, shm_offset, SizedResult<GLint>::ComputeSizeFromBytes(size)); + if (!result) { *error = error::kOutOfBounds; return false; } - (*result)->size = size; + result->size = size; return true; } @@ -2216,11 +2335,13 @@ error::Error GLES2DecoderImpl::HandleGetUniformiv( GLint location = c.location; GLuint service_id; Error error; - SizedResult* result; + void* result; if (GetUniformSetup( program, location, c.params_shm_id, c.params_shm_offset, &error, &service_id, &result)) { - glGetUniformiv(service_id, location, result->GetDataAs<GLint*>()); + glGetUniformiv( + service_id, location, + static_cast<gles2::GetUniformiv::Result*>(result)->GetData()); } return error; } @@ -2231,40 +2352,156 @@ error::Error GLES2DecoderImpl::HandleGetUniformfv( GLint location = c.location; GLuint service_id; Error error; - SizedResult* result; + void* result; + typedef gles2::GetUniformfv::Result Result; if (GetUniformSetup( program, location, c.params_shm_id, c.params_shm_offset, &error, &service_id, &result)) { - glGetUniformfv(service_id, location, result->GetDataAs<GLfloat*>()); + glGetUniformfv( + service_id, + location, + static_cast<gles2::GetUniformfv::Result*>(result)->GetData()); } return error; } error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat( uint32 immediate_data_size, const gles2::GetShaderPrecisionFormat& c) { - // TODO(gman): Implement. - NOTREACHED(); + GLenum shader_type = static_cast<GLenum>(c.shadertype); + GLenum precision_type = static_cast<GLenum>(c.precisiontype); + typedef gles2::GetShaderPrecisionFormat::Result Result; + Result* result = GetSharedMemoryAs<Result*>( + c.result_shm_id, c.result_shm_offset, sizeof(*result)); + if (!result) { + return error::kOutOfBounds; + } + if (!ValidateGLenumShaderType(shader_type) || + !ValidateGLenumShaderPrecision(precision_type)) { + result->success = 0; // false + SetGLError(GL_INVALID_ENUM); + } else { + result->success = 1; // true + switch (precision_type) { + case GL_LOW_INT: + case GL_MEDIUM_INT: + case GL_HIGH_INT: + result->min_range = -31; + result->max_range = 31; + result->precision = 0; + case GL_LOW_FLOAT: + case GL_MEDIUM_FLOAT: + case GL_HIGH_FLOAT: + result->min_range = -62; + result->max_range = 62; + result->precision = -16; + break; + default: + NOTREACHED(); + break; + } + } return error::kNoError; } error::Error GLES2DecoderImpl::HandleGetAttachedShaders( uint32 immediate_data_size, const gles2::GetAttachedShaders& c) { - // TODO(gman): Implement. - NOTREACHED(); + GLuint service_id; + uint32 result_size = c.result_size; + if (!id_manager_->GetServiceId(c.program, &service_id)) { + SetGLError(GL_INVALID_VALUE); + return error::kNoError; + } + typedef gles2::GetAttachedShaders::Result Result; + uint32 max_count = Result::ComputeMaxResults(result_size); + Result* result = GetSharedMemoryAs<Result*>( + c.result_shm_id, c.result_shm_offset, Result::ComputeSize(max_count)); + if (!result) { + return error::kOutOfBounds; + } + GLsizei count = 0; + glGetAttachedShaders(service_id, max_count, &count, result->GetData()); + for (GLsizei ii = 0; ii < count; ++ii) { + if (!id_manager_->GetClientId(result->GetData()[ii], + &result->GetData()[ii])) { + NOTREACHED(); + return error::kGenericError; + } + } + result->SetNumResults(count); return error::kNoError; } error::Error GLES2DecoderImpl::HandleGetActiveUniform( uint32 immediate_data_size, const gles2::GetActiveUniform& c) { - // TODO(gman): Implement. - NOTREACHED(); + GLuint program = c.program; + GLuint index = c.index; + uint32 name_bucket_id = c.name_bucket_id; + GLuint service_id; + typedef gles2::GetActiveUniform::Result Result; + Result* result = GetSharedMemoryAs<Result*>( + c.result_shm_id, c.result_shm_offset, sizeof(*result)); + if (!result) { + return error::kOutOfBounds; + } + result->success = 0; // false. + 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 error::kNoError; + } + const ProgramManager::ProgramInfo::UniformInfo* uniform_info = + info->GetUniformInfo(index); + if (!uniform_info) { + SetGLError(GL_INVALID_VALUE); + return error::kNoError; + } + result->success = 1; // true. + result->size = uniform_info->size; + result->type = uniform_info->type; + Bucket* bucket = CreateBucket(name_bucket_id); + bucket->SetFromString(uniform_info->name); return error::kNoError; } error::Error GLES2DecoderImpl::HandleGetActiveAttrib( uint32 immediate_data_size, const gles2::GetActiveAttrib& c) { - // TODO(gman): Implement. - NOTREACHED(); + GLuint program = c.program; + GLuint index = c.index; + uint32 name_bucket_id = c.name_bucket_id; + GLuint service_id; + typedef gles2::GetActiveAttrib::Result Result; + Result* result = GetSharedMemoryAs<Result*>( + c.result_shm_id, c.result_shm_offset, sizeof(*result)); + if (!result) { + return error::kOutOfBounds; + } + result->success = 0; // false. + 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 error::kNoError; + } + const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info = + info->GetAttribInfo(index); + if (!attrib_info) { + SetGLError(GL_INVALID_VALUE); + return error::kNoError; + } + result->success = 1; // true. + result->size = attrib_info->size; + result->type = attrib_info->type; + Bucket* bucket = CreateBucket(name_bucket_id); + bucket->SetFromString(attrib_info->name); return error::kNoError; } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 6cb0b54..1b8d0e8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "base/string_util.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/gl_mock.h" @@ -19,10 +20,20 @@ using ::testing::Return; using ::testing::SetArrayArgument; using ::testing::SetArgumentPointee; using ::testing::StrEq; +using ::testing::StrictMock; namespace gpu { namespace gles2 { +namespace { + +bool IsInvalidPrefix(const char* name) { + static const char kInvalidPrefix[] = { 'g', 'l', '_' }; + return memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0; +} + +} // anonymous namespace + class GLES2DecoderTest : public testing::Test { public: GLES2DecoderTest() @@ -52,7 +63,8 @@ class GLES2DecoderTest : public testing::Test { static const uint32 kSharedMemoryOffset = 132; static const int32 kInvalidSharedMemoryId = 402; static const uint32 kInvalidSharedMemoryOffset = kSharedBufferSize + 1; - static const uint32 kInitialResult = 0xDEADBEEFu; + static const uint32 kInitialResult = 0xBDBDBDBDu; + static const uint8 kInitialMemoryValue = 0xBDu; static const uint32 kNewClientId = 501; static const uint32 kNewServiceId = 502; @@ -84,8 +96,12 @@ class GLES2DecoderTest : public testing::Test { reinterpret_cast<T>(ImmediateDataAddress(cmd)); } + void ClearSharedMemory() { + engine_->ClearSharedMemory(); + } + virtual void SetUp() { - gl_.reset(new MockGLInterface()); + gl_.reset(new StrictMock<MockGLInterface>()); ::gles2::GLInterface::SetGLInterface(gl_.get()); EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _)) @@ -94,7 +110,7 @@ class GLES2DecoderTest : public testing::Test { EXPECT_CALL(*gl_, GetError()) .WillRepeatedly(Return(GL_NO_ERROR)); - engine_.reset(new MockCommandBufferEngine()); + engine_.reset(new StrictMock<MockCommandBufferEngine>()); Buffer buffer = engine_->GetSharedMemoryBuffer(kSharedMemoryId); shared_memory_offset_ = kSharedMemoryOffset; shared_memory_address_ = reinterpret_cast<int8*>(buffer.ptr) + @@ -147,11 +163,6 @@ class GLES2DecoderTest : public testing::Test { } EXPECT_EQ(GL_NO_ERROR, GetGLError()); - - result_ = GetSharedMemoryAs<SizedResult*>(); - GLuint* result_value = result_->GetDataAs<GLuint*>(); - result_->size = kInitialResult; - *result_value = kInitialResult; } virtual void TearDown() { @@ -203,7 +214,8 @@ class GLES2DecoderTest : public testing::Test { return static_cast<GLint>(*GetSharedMemoryAs<GLenum*>()); } - scoped_ptr<MockGLInterface> gl_; + // Use StrictMock to make 100% sure we know how GL will be called. + scoped_ptr<StrictMock<MockGLInterface> > gl_; scoped_ptr<GLES2Decoder> decoder_; GLuint client_buffer_id_; @@ -217,7 +229,6 @@ class GLES2DecoderTest : public testing::Test { uint32 shared_memory_id_; uint32 shared_memory_offset_; void* shared_memory_address_; - SizedResult* result_; int8 immediate_buffer_[256]; @@ -226,6 +237,7 @@ class GLES2DecoderTest : public testing::Test { public: MockCommandBufferEngine() { data_.reset(new int8[kSharedBufferSize]); + ClearSharedMemory(); valid_buffer_.ptr = data_.get(); valid_buffer_.size = kSharedBufferSize; } @@ -237,6 +249,10 @@ class GLES2DecoderTest : public testing::Test { return shm_id == kSharedMemoryId ? valid_buffer_ : invalid_buffer_; } + void ClearSharedMemory() { + memset(data_.get(), kInitialMemoryValue, kSharedBufferSize); + } + void set_token(int32 token) { DCHECK(false); } @@ -259,7 +275,7 @@ class GLES2DecoderTest : public testing::Test { Buffer invalid_buffer_; }; - scoped_ptr<MockCommandBufferEngine> engine_; + scoped_ptr<StrictMock<MockCommandBufferEngine> > engine_; }; const GLint GLES2DecoderTest::kNumVertexAttribs; @@ -311,12 +327,23 @@ class GLES2DecoderWithShaderTest : public GLES2DecoderTest { static const int kInvalidIndexRangeStart = 0; static const int kInvalidIndexRangeCount = 7; static const int kOutOfRangeIndexRangeEnd = 10; - static const GLint kNumAttribs = 3; + static const GLint kMaxAttribLength = 10; static const char* kAttrib1Name; static const char* kAttrib2Name; static const char* kAttrib3Name; - static const GLint kNumUniforms = 3; + static const GLint kAttrib1Size = 1; + static const GLint kAttrib2Size = 1; + static const GLint kAttrib3Size = 1; + static const GLint kAttrib1Location = 0; + static const GLint kAttrib2Location = 1; + static const GLint kAttrib3Location = 2; + static const GLenum kAttrib1Type = GL_FLOAT_VEC4; + static const GLenum kAttrib2Type = GL_FLOAT_VEC2; + static const GLenum kAttrib3Type = GL_FLOAT_VEC3; + static const GLint kInvalidAttribLocation = 30; + static const GLint kBadAttribIndex = kNumVertexAttribs; + static const GLint kMaxUniformLength = 10; static const char* kUniform1Name; static const char* kUniform2Name; @@ -324,120 +351,144 @@ class GLES2DecoderWithShaderTest : public GLES2DecoderTest { static const GLint kUniform1Size = 1; static const GLint kUniform2Size = 3; static const GLint kUniform3Size = 2; - static const GLint kUniform1Location = 0; - static const GLint kUniform2Location = 1; - static const GLint kUniform3Location = 2; + static const GLint kUniform1Location = 3; + static const GLint kUniform2Location = 10; + static const GLint kUniform2ElementLocation = 12; + static const GLint kUniform3Location = 20; static const GLenum kUniform1Type = GL_FLOAT_VEC4; static const GLenum kUniform2Type = GL_INT_VEC2; static const GLenum kUniform3Type = GL_FLOAT_VEC3; - static const GLint kInvalidUniformLocation = 3; + static const GLint kInvalidUniformLocation = 30; + static const GLint kBadUniformIndex = 1000; protected: + struct AttribInfo { + const char* name; + GLint size; + GLenum type; + GLint location; + }; + + struct UniformInfo { + const char* name; + GLint size; + GLenum type; + GLint location; + }; + virtual void SetUp() { GLES2DecoderTest::SetUp(); { - struct AttribInfo { - const char* name; - GLint size; - GLenum type; - GLint location; - }; static AttribInfo attribs[] = { - { kAttrib1Name, 1, GL_FLOAT_VEC4, 0, }, - { kAttrib2Name, 1, GL_FLOAT_VEC2, 1, }, - { kAttrib3Name, 1, GL_FLOAT_VEC3, 2, }, - }; - struct UniformInfo { - const char* name; - GLint size; - GLenum type; - GLint location; + { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, }, + { kAttrib2Name, kAttrib2Size, kAttrib2Type, kAttrib2Location, }, + { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, }, }; static UniformInfo uniforms[] = { { kUniform1Name, kUniform1Size, GL_FLOAT_VEC4, kUniform1Location, }, { kUniform2Name, kUniform2Size, GL_INT_VEC2, kUniform2Location, }, { kUniform3Name, kUniform3Size, GL_FLOAT_VEC3, kUniform3Location, }, }; + SetupShader(attribs, arraysize(attribs), uniforms, arraysize(uniforms), + client_program_id_, kServiceProgramId); + } - LinkProgram cmd; + { + EXPECT_CALL(*gl_, UseProgram(kServiceProgramId)) + .Times(1) + .RetiresOnSaturation(); + UseProgram cmd; cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + } - { - InSequence s; - EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetError()) - .WillOnce(Return(GL_NO_ERROR)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, - GetProgramiv(kServiceProgramId, GL_ACTIVE_ATTRIBUTES, _)) - .WillOnce(SetArgumentPointee<2>(kNumAttribs)) - .RetiresOnSaturation(); + virtual void TearDown() { + GLES2DecoderTest::TearDown(); + } + + void SetupShader(AttribInfo* attribs, size_t num_attribs, + UniformInfo* uniforms, size_t num_uniforms, + GLuint client_id, GLuint service_id) { + LinkProgram cmd; + cmd.Init(client_id); + + { + InSequence s; + EXPECT_CALL(*gl_, LinkProgram(service_id)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _)) + .WillOnce(SetArgumentPointee<2>(num_attribs)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _)) + .WillOnce(SetArgumentPointee<2>(kMaxAttribLength)) + .RetiresOnSaturation(); + for (size_t ii = 0; ii < num_attribs; ++ii) { + const AttribInfo& info = attribs[ii]; EXPECT_CALL(*gl_, - GetProgramiv(kServiceProgramId, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _)) - .WillOnce(SetArgumentPointee<2>(kMaxAttribLength)) + GetActiveAttrib(service_id, ii, + kMaxAttribLength, _, _, _, _)) + .WillOnce(DoAll( + SetArgumentPointee<3>(strlen(info.name)), + SetArgumentPointee<4>(info.size), + SetArgumentPointee<5>(info.type), + SetArrayArgument<6>(info.name, + info.name + strlen(info.name) + 1))) .RetiresOnSaturation(); - for (GLint ii = 0; ii < kNumAttribs; ++ii) { - const AttribInfo& info = attribs[ii]; - EXPECT_CALL(*gl_, - GetActiveAttrib(kServiceProgramId, ii, - kMaxAttribLength, _, _, _, _)) - .WillOnce(DoAll( - SetArgumentPointee<3>(strlen(info.name)), - SetArgumentPointee<4>(info.size), - SetArgumentPointee<5>(info.type), - SetArrayArgument<6>(info.name, - info.name + strlen(info.name) + 1))) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetAttribLocation(kServiceProgramId, + if (!IsInvalidPrefix(info.name)) { + EXPECT_CALL(*gl_, GetAttribLocation(service_id, StrEq(info.name))) .WillOnce(Return(info.location)) .RetiresOnSaturation(); } + } + EXPECT_CALL(*gl_, + GetProgramiv(service_id, GL_ACTIVE_UNIFORMS, _)) + .WillOnce(SetArgumentPointee<2>(num_uniforms)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + GetProgramiv(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, _)) + .WillOnce(SetArgumentPointee<2>(kMaxUniformLength)) + .RetiresOnSaturation(); + for (size_t ii = 0; ii < num_uniforms; ++ii) { + const UniformInfo& info = uniforms[ii]; EXPECT_CALL(*gl_, - GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORMS, _)) - .WillOnce(SetArgumentPointee<2>(kNumUniforms)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, - GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_MAX_LENGTH, _)) - .WillOnce(SetArgumentPointee<2>(kMaxUniformLength)) + GetActiveUniform(service_id, ii, + kMaxUniformLength, _, _, _, _)) + .WillOnce(DoAll( + SetArgumentPointee<3>(strlen(info.name)), + SetArgumentPointee<4>(info.size), + SetArgumentPointee<5>(info.type), + SetArrayArgument<6>(info.name, + info.name + strlen(info.name) + 1))) .RetiresOnSaturation(); - for (GLint ii = 0; ii < kNumUniforms; ++ii) { - const UniformInfo& info = uniforms[ii]; - EXPECT_CALL(*gl_, - GetActiveUniform(kServiceProgramId, ii, - kMaxUniformLength, _, _, _, _)) - .WillOnce(DoAll( - SetArgumentPointee<3>(strlen(info.name)), - SetArgumentPointee<4>(info.size), - SetArgumentPointee<5>(info.type), - SetArrayArgument<6>(info.name, - info.name + strlen(info.name) + 1))) - .RetiresOnSaturation(); - EXPECT_CALL(*gl_, GetUniformLocation(kServiceProgramId, + if (!IsInvalidPrefix(info.name)) { + EXPECT_CALL(*gl_, GetUniformLocation(service_id, StrEq(info.name))) .WillOnce(Return(info.location)) .RetiresOnSaturation(); + if (info.size > 1) { + for (GLsizei jj = 1; jj < info.size; ++jj) { + std::string element_name( + std::string(info.name) + "[" + IntToString(jj) + "]"); + EXPECT_CALL(*gl_, GetUniformLocation(service_id, + StrEq(element_name))) + .WillOnce(Return(info.location + jj)) + .RetiresOnSaturation(); + } + } } } - - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - } - - { - EXPECT_CALL(*gl_, UseProgram(kServiceProgramId)) - .Times(1) - .RetiresOnSaturation(); - UseProgram cmd; - cmd.Init(client_program_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } - } - virtual void TearDown() { - GLES2DecoderTest::TearDown(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); } inline GLvoid* BufferOffset(unsigned i) { @@ -540,7 +591,6 @@ class GLES2DecoderWithShaderTest : public GLES2DecoderTest { } }; -const GLint GLES2DecoderWithShaderTest::kNumAttribs; const GLint GLES2DecoderWithShaderTest::kMaxAttribLength; const GLsizei GLES2DecoderWithShaderTest::kNumVertices; const GLsizei GLES2DecoderWithShaderTest::kNumIndices; @@ -802,13 +852,15 @@ TEST_F(GLES2DecoderWithShaderTest, GetVertexAttribPointervSucceeds) { const float dummy = 0; const GLuint kOffsetToTestFor = sizeof(dummy) * 4; const GLuint kIndexToTest = 1; - const GLuint* result_value = result_->GetDataAs<const GLuint*>(); + GetVertexAttribPointerv::Result* result = + static_cast<GetVertexAttribPointerv::Result*>(shared_memory_address_); + const GLuint* result_value = result->GetData(); // Test that initial value is 0. GetVertexAttribPointerv cmd; cmd.Init(kIndexToTest, GL_VERTEX_ATTRIB_ARRAY_POINTER, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(sizeof(*result_value), result_->size); + EXPECT_EQ(sizeof(*result_value), result->size); EXPECT_EQ(0u, *result_value); EXPECT_EQ(GL_NO_ERROR, GetGLError()); @@ -816,20 +868,22 @@ TEST_F(GLES2DecoderWithShaderTest, GetVertexAttribPointervSucceeds) { SetupVertexBuffer(); DoVertexAttribPointer(kIndexToTest, 2, GL_FLOAT, 0, kOffsetToTestFor); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(sizeof(*result_value), result_->size); + EXPECT_EQ(sizeof(*result_value), result->size); EXPECT_EQ(kOffsetToTestFor, *result_value); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } TEST_F(GLES2DecoderWithShaderTest, GetVertexAttribPointervBadArgsFails) { const GLuint kIndexToTest = 1; - const GLuint* result_value = result_->GetDataAs<const GLuint*>(); + GetVertexAttribPointerv::Result* result = + static_cast<GetVertexAttribPointerv::Result*>(shared_memory_address_); + const GLuint* result_value = result->GetData(); // Test pname invalid fails. GetVertexAttribPointerv cmd; cmd.Init(kIndexToTest, GL_VERTEX_ATTRIB_ARRAY_POINTER + 1, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0u, result_->size); + EXPECT_EQ(0u, result->size); EXPECT_EQ(kInitialResult, *result_value); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); @@ -837,7 +891,7 @@ TEST_F(GLES2DecoderWithShaderTest, GetVertexAttribPointervBadArgsFails) { cmd.Init(kNumVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_POINTER, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0u, result_->size); + EXPECT_EQ(0u, result->size); EXPECT_EQ(kInitialResult, *result_value); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); @@ -853,17 +907,33 @@ TEST_F(GLES2DecoderWithShaderTest, GetVertexAttribPointervBadArgsFails) { } TEST_F(GLES2DecoderWithShaderTest, GetUniformivSucceeds) { + GetUniformiv::Result* result = + static_cast<GetUniformiv::Result*>(shared_memory_address_); GetUniformiv cmd; cmd.Init(client_program_id_, kUniform2Location, kSharedMemoryId, kSharedMemoryOffset); EXPECT_CALL(*gl_, GetUniformiv(kServiceProgramId, kUniform2Location, _)) .Times(1); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(kUniform2Size * GLES2Util::GetGLDataTypeSize(kUniform2Type), - result_->size); + EXPECT_EQ(GLES2Util::GetGLDataTypeSize(kUniform2Type), result->size); +} + +TEST_F(GLES2DecoderWithShaderTest, GetUniformivArrayElementSucceeds) { + GetUniformiv::Result* result = + static_cast<GetUniformiv::Result*>(shared_memory_address_); + GetUniformiv cmd; + cmd.Init(client_program_id_, kUniform2ElementLocation, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_CALL(*gl_, + GetUniformiv(kServiceProgramId, kUniform2ElementLocation, _)) + .Times(1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GLES2Util::GetGLDataTypeSize(kUniform2Type), result->size); } TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadProgramFails) { + GetUniformiv::Result* result = + static_cast<GetUniformiv::Result*>(shared_memory_address_); GetUniformiv cmd; // non-existant program cmd.Init(kInvalidClientId, kUniform2Location, @@ -871,15 +941,15 @@ TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadProgramFails) { EXPECT_CALL(*gl_, GetUniformiv(_, _, _)) .Times(0); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result_->size); + EXPECT_EQ(0, result->size); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); // Valid id that is not a program. The GL spec requires a different error for // this case. - result_->size = kInitialResult; + result->size = kInitialResult; cmd.Init(client_texture_id_, kUniform2Location, kSharedMemoryId, kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result_->size); + EXPECT_EQ(0, result->size); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); // Unlinked program EXPECT_CALL(*gl_, CreateProgram()) @@ -889,15 +959,17 @@ TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadProgramFails) { CreateProgram cmd2; cmd2.Init(kNewClientId); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - result_->size = kInitialResult; + result->size = kInitialResult; cmd.Init(kNewClientId, kUniform2Location, kSharedMemoryId, kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result_->size); + EXPECT_EQ(0, result->size); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); } TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadLocationFails) { + GetUniformiv::Result* result = + static_cast<GetUniformiv::Result*>(shared_memory_address_); GetUniformiv cmd; // invalid location cmd.Init(client_program_id_, kInvalidUniformLocation, @@ -905,7 +977,7 @@ TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadLocationFails) { EXPECT_CALL(*gl_, GetUniformiv(_, _, _)) .Times(0); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result_->size); + EXPECT_EQ(0, result->size); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); } @@ -922,17 +994,33 @@ TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadSharedMemoryFails) { }; TEST_F(GLES2DecoderWithShaderTest, GetUniformfvSucceeds) { + GetUniformfv::Result* result = + static_cast<GetUniformfv::Result*>(shared_memory_address_); GetUniformfv cmd; cmd.Init(client_program_id_, kUniform2Location, kSharedMemoryId, kSharedMemoryOffset); EXPECT_CALL(*gl_, GetUniformfv(kServiceProgramId, kUniform2Location, _)) .Times(1); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(kUniform2Size * GLES2Util::GetGLDataTypeSize(kUniform2Type), - result_->size); + EXPECT_EQ(GLES2Util::GetGLDataTypeSize(kUniform2Type), result->size); +} + +TEST_F(GLES2DecoderWithShaderTest, GetUniformfvArrayElementSucceeds) { + GetUniformfv::Result* result = + static_cast<GetUniformfv::Result*>(shared_memory_address_); + GetUniformfv cmd; + cmd.Init(client_program_id_, kUniform2ElementLocation, + kSharedMemoryId, kSharedMemoryOffset); + EXPECT_CALL(*gl_, + GetUniformfv(kServiceProgramId, kUniform2ElementLocation, _)) + .Times(1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GLES2Util::GetGLDataTypeSize(kUniform2Type), result->size); } TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadProgramFails) { + GetUniformfv::Result* result = + static_cast<GetUniformfv::Result*>(shared_memory_address_); GetUniformfv cmd; // non-existant program cmd.Init(kInvalidClientId, kUniform2Location, @@ -940,15 +1028,15 @@ TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadProgramFails) { EXPECT_CALL(*gl_, GetUniformfv(_, _, _)) .Times(0); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result_->size); + EXPECT_EQ(0, result->size); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); // Valid id that is not a program. The GL spec requires a different error for // this case. - result_->size = kInitialResult; + result->size = kInitialResult; cmd.Init(client_texture_id_, kUniform2Location, kSharedMemoryId, kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result_->size); + EXPECT_EQ(0, result->size); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); // Unlinked program EXPECT_CALL(*gl_, CreateProgram()) @@ -958,15 +1046,17 @@ TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadProgramFails) { CreateProgram cmd2; cmd2.Init(kNewClientId); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2)); - result_->size = kInitialResult; + result->size = kInitialResult; cmd.Init(kNewClientId, kUniform2Location, kSharedMemoryId, kSharedMemoryOffset); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result_->size); + EXPECT_EQ(0, result->size); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); } TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadLocationFails) { + GetUniformfv::Result* result = + static_cast<GetUniformfv::Result*>(shared_memory_address_); GetUniformfv cmd; // invalid location cmd.Init(client_program_id_, kInvalidUniformLocation, @@ -974,7 +1064,7 @@ TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadLocationFails) { EXPECT_CALL(*gl_, GetUniformfv(_, _, _)) .Times(0); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(0, result_->size); + EXPECT_EQ(0, result->size); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); } @@ -990,6 +1080,255 @@ TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadSharedMemoryFails) { EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); }; +TEST_F(GLES2DecoderWithShaderTest, GetAttachedShadersSucceeds) { + GetAttachedShaders cmd; + typedef GetAttachedShaders::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetAttachedShaders(kServiceProgramId, 1, _, _)) + .WillOnce(DoAll(SetArgumentPointee<2>(1), + SetArgumentPointee<3>(kServiceShaderId))); + cmd.Init(client_program_id_, shared_memory_id_, shared_memory_offset_, + Result::ComputeSize(1)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1, result->GetNumResults()); + EXPECT_EQ(client_shader_id_, result->GetData()[0]); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES2DecoderWithShaderTest, GetAttachedShadersBadProgramFails) { + GetAttachedShaders cmd; + typedef GetAttachedShaders::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)) + .Times(0); + cmd.Init(kInvalidClientId, shared_memory_id_, shared_memory_offset_, + Result::ComputeSize(1)); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->size); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_F(GLES2DecoderWithShaderTest, GetAttachedShadersBadSharedMemoryFails) { + GetAttachedShaders cmd; + typedef GetAttachedShaders::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + cmd.Init(client_program_id_, kInvalidSharedMemoryId, shared_memory_offset_, + Result::ComputeSize(1)); + EXPECT_CALL(*gl_, GetAttachedShaders(_, _, _, _)) + .Times(0); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, shared_memory_id_, kInvalidSharedMemoryOffset, + Result::ComputeSize(1)); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_F(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatSucceeds) { + GetShaderPrecisionFormat cmd; + typedef GetShaderPrecisionFormat::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + // NOTE: GL will not be called. There is no equivalent Desktop OpenGL + // function. + cmd.Init(GL_VERTEX_SHADER, GL_HIGH_FLOAT, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_NE(0, result->success); + EXPECT_EQ(-62, result->min_range); + EXPECT_EQ(62, result->max_range); + EXPECT_EQ(-16, result->precision); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_F(GLES2DecoderWithShaderTest, GetShaderPrecisionFormatBadArgsFails) { + GetShaderPrecisionFormat cmd; + typedef GetShaderPrecisionFormat::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + cmd.Init(GL_TEXTURE_2D, GL_HIGH_FLOAT, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + cmd.Init(GL_VERTEX_SHADER, GL_TEXTURE_2D, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + +TEST_F(GLES2DecoderWithShaderTest, + GetShaderPrecisionFormatBadSharedMemoryFails) { + GetShaderPrecisionFormat cmd; + typedef GetShaderPrecisionFormat::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + cmd.Init(GL_VERTEX_SHADER, GL_HIGH_FLOAT, + kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(GL_VERTEX_SHADER, GL_TEXTURE_2D, + shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_F(GLES2DecoderWithShaderTest, GetActiveUniformSucceeds) { + const GLuint kUniformIndex = 1; + const uint32 kBucketId = 123; + GetActiveUniform cmd; + typedef GetActiveUniform::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + cmd.Init(client_program_id_, kUniformIndex, kBucketId, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_NE(0, result->success); + EXPECT_EQ(kUniform2Size, result->size); + EXPECT_EQ(kUniform2Type, result->type); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); + ASSERT_TRUE(bucket != NULL); + EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()), kUniform2Name, + bucket->size())); +} + +TEST_F(GLES2DecoderWithShaderTest, GetActiveUniformBadProgramFails) { + const GLuint kUniformIndex = 1; + const uint32 kBucketId = 123; + GetActiveUniform cmd; + typedef GetActiveUniform::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + cmd.Init(kInvalidClientId, kUniformIndex, kBucketId, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(client_texture_id_, kUniformIndex, kBucketId, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_F(GLES2DecoderWithShaderTest, GetActiveUniformBadIndexFails) { + const uint32 kBucketId = 123; + GetActiveUniform cmd; + typedef GetActiveUniform::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + cmd.Init(client_program_id_, kBadUniformIndex, kBucketId, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_F(GLES2DecoderWithShaderTest, GetActiveUniformBadSharedMemoryFails) { + const GLuint kUniformIndex = 1; + const uint32 kBucketId = 123; + GetActiveUniform cmd; + typedef GetActiveUniform::Result Result; + cmd.Init(client_program_id_, kUniformIndex, kBucketId, + kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, kUniformIndex, kBucketId, + shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_F(GLES2DecoderWithShaderTest, GetActiveAttribSucceeds) { + const GLuint kAttribIndex = 1; + const uint32 kBucketId = 123; + GetActiveAttrib cmd; + typedef GetActiveAttrib::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + cmd.Init(client_program_id_, kAttribIndex, kBucketId, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_NE(0, result->success); + EXPECT_EQ(kAttrib2Size, result->size); + EXPECT_EQ(kAttrib2Type, result->type); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId); + ASSERT_TRUE(bucket != NULL); + EXPECT_EQ(0, memcmp(bucket->GetData(0, bucket->size()), kAttrib2Name, + bucket->size())); +} + +TEST_F(GLES2DecoderWithShaderTest, GetActiveAttribBadProgramFails) { + const GLuint kAttribIndex = 1; + const uint32 kBucketId = 123; + GetActiveAttrib cmd; + typedef GetActiveAttrib::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + cmd.Init(kInvalidClientId, kAttribIndex, kBucketId, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + cmd.Init(client_texture_id_, kAttribIndex, kBucketId, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_F(GLES2DecoderWithShaderTest, GetActiveAttribBadIndexFails) { + const uint32 kBucketId = 123; + GetActiveAttrib cmd; + typedef GetActiveAttrib::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + cmd.Init(client_program_id_, kBadAttribIndex, kBucketId, + shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, result->success); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_F(GLES2DecoderWithShaderTest, GetActiveAttribBadSharedMemoryFails) { + const GLuint kAttribIndex = 1; + const uint32 kBucketId = 123; + GetActiveAttrib cmd; + typedef GetActiveAttrib::Result Result; + cmd.Init(client_program_id_, kAttribIndex, kBucketId, + kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, kAttribIndex, kBucketId, + shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +// TODO(gman): BindAttribLocation + +// TODO(gman): BindAttribLocationImmediate + +// TODO(gman): BufferData + +// TODO(gman): BufferDataImmediate + +// TODO(gman): BufferSubData + +// TODO(gman): BufferSubDataImmediate + +// TODO(gman): CompressedTexImage2D + +// TODO(gman): CompressedTexImage2DImmediate + +// TODO(gman): CompressedTexSubImage2D + +// TODO(gman): CompressedTexSubImage2DImmediate + +// TODO(gman): DeleteProgram + +// TODO(gman): DeleteShader + +// TODO(gman): GetAttribLocation + +// TODO(gman): GetAttribLocationImmediate + +// TODO(gman): GetUniformLocation + +// TODO(gman): GetUniformLocationImmediate + +// TODO(gman): PixelStorei + +// TODO(gman): ReadPixels + +// TODO(gman): ShaderSource + +// TODO(gman): ShaderSourceImmediate + #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_autogen.h" } // namespace gles2 diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index c7047a6..0573e3c 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h @@ -33,7 +33,7 @@ bool ValidateGLenumRenderBufferFormat(GLenum value); bool ValidateGLenumRenderBufferParameter(GLenum value); bool ValidateGLenumRenderBufferTarget(GLenum value); bool ValidateGLenumShaderParameter(GLenum value); -bool ValidateGLenumShaderPercision(GLenum value); +bool ValidateGLenumShaderPrecision(GLenum value); bool ValidateGLenumShaderType(GLenum value); bool ValidateGLenumSrcBlendFactor(GLenum value); bool ValidateGLenumStencilOp(GLenum value); diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index 1513a43..b082c09 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -4,8 +4,8 @@ // This file is auto-generated. DO NOT EDIT! -#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ -#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ +#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ // NOLINT +#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ // NOLINT bool ValidateGLenumAttachment(GLenum value) { switch (value) { @@ -325,7 +325,7 @@ bool ValidateGLenumShaderParameter(GLenum value) { } } -bool ValidateGLenumShaderPercision(GLenum value) { +bool ValidateGLenumShaderPrecision(GLenum value) { switch (value) { case GL_LOW_FLOAT: case GL_MEDIUM_FLOAT: @@ -509,5 +509,5 @@ bool ValidateGLenumVertexPointer(GLenum value) { } } -#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ +#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_ // NOLINT |