summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-03 01:11:37 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-03 01:11:37 +0000
commitf7b85373bada6dc2da2ca3b47c38fc25d89dcf2e (patch)
treeb14cdb3fd116c4287f2d61cd0f4e75c91cdf13b4 /gpu
parent50d22375941bee74a33e504c78e4355c878c30b9 (diff)
downloadchromium_src-f7b85373bada6dc2da2ca3b47c38fc25d89dcf2e.zip
chromium_src-f7b85373bada6dc2da2ca3b47c38fc25d89dcf2e.tar.gz
chromium_src-f7b85373bada6dc2da2ca3b47c38fc25d89dcf2e.tar.bz2
Implements glGetUniformiv and glGetUniformfv.
TEST=none BUG=none Review URL: http://codereview.chromium.org/566019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37918 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc11
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format.h12
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.cc41
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc142
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc233
6 files changed, 413 insertions, 28 deletions
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index e0cbb04..8ea20ab 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -291,7 +291,6 @@ void GLES2Implementation::TexSubImage2D(
}
}
-
GLenum GLES2Implementation::CheckFramebufferStatus(GLenum target) {
// TODO(gman): implement.
return 0;
@@ -341,12 +340,18 @@ const GLubyte* GLES2Implementation::GetString(GLenum name) {
void GLES2Implementation::GetUniformfv(
GLuint program, GLint location, GLfloat* params) {
- // TODO(gman): implement.
+ helper_->GetUniformfv(
+ program, location, result_shm_id(), result_shm_offset());
+ WaitForCmd();
+ CopyResult(params);
}
void GLES2Implementation::GetUniformiv(
GLuint program, GLint location, GLint* params) {
- // TODO(gman): implement.
+ helper_->GetUniformiv(
+ program, location, result_shm_id(), result_shm_offset());
+ WaitForCmd();
+ CopyResult(params);
}
void GLES2Implementation::ReadPixels(
diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h
index 7598318..d6d3beb 100644
--- a/gpu/command_buffer/common/gles2_cmd_format.h
+++ b/gpu/command_buffer/common/gles2_cmd_format.h
@@ -40,10 +40,22 @@ struct SizedResult {
T GetDataAs() {
return static_cast<T>(static_cast<void*>(&data));
}
+
+ // Returns the size of the SizedResult for a given size of result.
+ static size_t GetSize(size_t size_of_result) {
+ return size_of_result + sizeof(uint32); // NOLINT
+ }
+
uint32 size; // in bytes.
int32 data; // this is just here to get an offset.
};
+COMPILE_ASSERT(sizeof(SizedResult) == 8, SizedResult_size_not_8);
+COMPILE_ASSERT(offsetof(SizedResult, size) == 0,
+ OffsetOf_SizedResult_size_not_0);
+COMPILE_ASSERT(offsetof(SizedResult, data) == 4,
+ OffsetOf_SizedResult_data_not_4);
+
#include "gpu/command_buffer/common/gles2_cmd_format_autogen.h"
// These are hand written commands.
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 8145315..aac4b84 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -343,6 +343,47 @@ uint32 GLES2Util::ComputeImageDataSize(
return height * row_size;
}
+uint32 GLES2Util::GetGLDataTypeSize(int type) {
+ switch (type) {
+ case GL_FLOAT:
+ return sizeof(GLfloat); // NOLINT
+ case GL_FLOAT_VEC2:
+ return sizeof(GLfloat) * 2; // NOLINT
+ case GL_FLOAT_VEC3:
+ return sizeof(GLfloat) * 3; // NOLINT
+ case GL_FLOAT_VEC4:
+ return sizeof(GLfloat) * 4; // NOLINT
+ case GL_INT:
+ return sizeof(GLint); // NOLINT
+ case GL_INT_VEC2:
+ return sizeof(GLint) * 2; // NOLINT
+ case GL_INT_VEC3:
+ return sizeof(GLint) * 3; // NOLINT
+ case GL_INT_VEC4:
+ return sizeof(GLint) * 4; // NOLINT
+ case GL_BOOL:
+ return sizeof(GLint); // NOLINT
+ case GL_BOOL_VEC2:
+ return sizeof(GLint) * 1; // NOLINT
+ case GL_BOOL_VEC3:
+ return sizeof(GLint) * 2; // NOLINT
+ case GL_BOOL_VEC4:
+ return sizeof(GLint) * 3; // NOLINT
+ case GL_FLOAT_MAT2:
+ return sizeof(GLfloat) * 2 * 2; // NOLINT
+ case GL_FLOAT_MAT3:
+ return sizeof(GLfloat) * 3 * 3; // NOLINT
+ case GL_FLOAT_MAT4:
+ return sizeof(GLfloat) * 4 * 4; // NOLINT
+ case GL_SAMPLER_2D:
+ return sizeof(GLint); // NOLINT
+ case GL_SAMPLER_CUBE:
+ return sizeof(GLint); // NOLINT
+ default:
+ return 0;
+ }
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index 6a14133..1d2139d 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -30,6 +30,8 @@ class GLES2Util {
static uint32 ComputeImageDataSize(
int width, int height, int format, int type, int unpack_alignment);
+ static uint32 GetGLDataTypeSize(int type);
+
private:
int num_compressed_texture_formats_;
};
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 7abccc9..e708a69 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -35,6 +35,8 @@ COMPILE_ASSERT(sizeof(GLint) == sizeof(uint32), // NOLINT
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 @@ class ProgramManager {
// 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 @@ class ProgramManager {
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 @@ 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;
@@ -364,17 +405,32 @@ void ProgramManager::UpdateProgramInfo(GLuint program) {
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 @@ class GLES2DecoderImpl : public GLES2Decoder {
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 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
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(
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 7133eab..6cb0b54 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -4,6 +4,7 @@
#include "gpu/command_buffer/service/gles2_cmd_decoder.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"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -288,6 +289,12 @@ void GLES2DecoderTest::SpecializedSetup<LinkProgram, 0>() {
*gl_,
GetProgramiv(kServiceProgramId, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _))
.WillOnce(SetArgumentPointee<2>(0));
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORMS, _))
+ .WillOnce(SetArgumentPointee<2>(0));
+ EXPECT_CALL(
+ *gl_,
+ GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORM_MAX_LENGTH, _))
+ .WillOnce(SetArgumentPointee<2>(0));
};
@@ -297,8 +304,6 @@ class GLES2DecoderWithShaderTest : public GLES2DecoderTest {
: GLES2DecoderTest() {
}
- static const GLint kNumAttribs = 3;
- static const GLint kMaxAttribLength = 10;
static const GLsizei kNumVertices = 100;
static const GLsizei kNumIndices = 10;
static const int kValidIndexRangeStart = 1;
@@ -306,9 +311,26 @@ 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 kMaxUniformLength = 10;
+ static const char* kUniform1Name;
+ static const char* kUniform2Name;
+ static const char* kUniform3Name;
+ 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 GLenum kUniform1Type = GL_FLOAT_VEC4;
+ static const GLenum kUniform2Type = GL_INT_VEC2;
+ static const GLenum kUniform3Type = GL_FLOAT_VEC3;
+ static const GLint kInvalidUniformLocation = 3;
protected:
virtual void SetUp() {
@@ -326,30 +348,42 @@ class GLES2DecoderWithShaderTest : public GLES2DecoderTest {
{ kAttrib2Name, 1, GL_FLOAT_VEC2, 1, },
{ kAttrib3Name, 1, GL_FLOAT_VEC3, 2, },
};
+ struct UniformInfo {
+ const char* name;
+ GLint size;
+ GLenum type;
+ GLint location;
+ };
+ static UniformInfo uniforms[] = {
+ { kUniform1Name, kUniform1Size, GL_FLOAT_VEC4, kUniform1Location, },
+ { kUniform2Name, kUniform2Size, GL_INT_VEC2, kUniform2Location, },
+ { kUniform3Name, kUniform3Size, GL_FLOAT_VEC3, kUniform3Location, },
+ };
+
LinkProgram cmd;
cmd.Init(client_program_id_);
- 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();
- EXPECT_CALL(*gl_,
- GetProgramiv(kServiceProgramId, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _))
- .WillOnce(SetArgumentPointee<2>(kMaxAttribLength))
- .RetiresOnSaturation();
{
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();
+ EXPECT_CALL(*gl_,
+ GetProgramiv(kServiceProgramId, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _))
+ .WillOnce(SetArgumentPointee<2>(kMaxAttribLength))
+ .RetiresOnSaturation();
for (GLint ii = 0; ii < kNumAttribs; ++ii) {
const AttribInfo& info = attribs[ii];
EXPECT_CALL(*gl_,
GetActiveAttrib(kServiceProgramId, ii,
- kMaxAttribLength + 1, _, _, _, _))
+ kMaxAttribLength, _, _, _, _))
.WillOnce(DoAll(
SetArgumentPointee<3>(strlen(info.name)),
SetArgumentPointee<4>(info.size),
@@ -362,6 +396,31 @@ class GLES2DecoderWithShaderTest : public GLES2DecoderTest {
.WillOnce(Return(info.location))
.RetiresOnSaturation();
}
+ 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))
+ .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,
+ StrEq(info.name)))
+ .WillOnce(Return(info.location))
+ .RetiresOnSaturation();
+ }
}
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
@@ -493,6 +552,9 @@ const int GLES2DecoderWithShaderTest::kOutOfRangeIndexRangeEnd;
const char* GLES2DecoderWithShaderTest::kAttrib1Name = "attrib1";
const char* GLES2DecoderWithShaderTest::kAttrib2Name = "attrib2";
const char* GLES2DecoderWithShaderTest::kAttrib3Name = "attrib3";
+const char* GLES2DecoderWithShaderTest::kUniform1Name = "uniform1";
+const char* GLES2DecoderWithShaderTest::kUniform2Name = "uniform2";
+const char* GLES2DecoderWithShaderTest::kUniform3Name = "uniform3";
TEST_F(GLES2DecoderWithShaderTest, DrawArraysNoAttributesSucceeds) {
EXPECT_CALL(*gl_, DrawArrays(GL_TRIANGLES, 0, kNumVertices))
@@ -790,6 +852,143 @@ TEST_F(GLES2DecoderWithShaderTest, GetVertexAttribPointervBadArgsFails) {
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
+TEST_F(GLES2DecoderWithShaderTest, GetUniformivSucceeds) {
+ 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);
+}
+
+TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadProgramFails) {
+ GetUniformiv cmd;
+ // non-existant program
+ cmd.Init(kInvalidClientId, kUniform2Location,
+ kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetUniformiv(_, _, _))
+ .Times(0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ 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;
+ cmd.Init(client_texture_id_, kUniform2Location,
+ kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result_->size);
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ // Unlinked program
+ EXPECT_CALL(*gl_, CreateProgram())
+ .Times(1)
+ .WillOnce(Return(kNewServiceId))
+ .RetiresOnSaturation();
+ CreateProgram cmd2;
+ cmd2.Init(kNewClientId);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
+ result_->size = kInitialResult;
+ cmd.Init(kNewClientId, kUniform2Location,
+ kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result_->size);
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadLocationFails) {
+ GetUniformiv cmd;
+ // invalid location
+ cmd.Init(client_program_id_, kInvalidUniformLocation,
+ kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetUniformiv(_, _, _))
+ .Times(0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result_->size);
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_F(GLES2DecoderWithShaderTest, GetUniformivBadSharedMemoryFails) {
+ GetUniformiv cmd;
+ cmd.Init(client_program_id_, kUniform2Location,
+ kInvalidSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetUniformiv(_, _, _))
+ .Times(0);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(client_program_id_, kUniform2Location,
+ kSharedMemoryId, kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+};
+
+TEST_F(GLES2DecoderWithShaderTest, GetUniformfvSucceeds) {
+ 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);
+}
+
+TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadProgramFails) {
+ GetUniformfv cmd;
+ // non-existant program
+ cmd.Init(kInvalidClientId, kUniform2Location,
+ kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetUniformfv(_, _, _))
+ .Times(0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ 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;
+ cmd.Init(client_texture_id_, kUniform2Location,
+ kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result_->size);
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ // Unlinked program
+ EXPECT_CALL(*gl_, CreateProgram())
+ .Times(1)
+ .WillOnce(Return(kNewServiceId))
+ .RetiresOnSaturation();
+ CreateProgram cmd2;
+ cmd2.Init(kNewClientId);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
+ result_->size = kInitialResult;
+ cmd.Init(kNewClientId, kUniform2Location,
+ kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result_->size);
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadLocationFails) {
+ GetUniformfv cmd;
+ // invalid location
+ cmd.Init(client_program_id_, kInvalidUniformLocation,
+ kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetUniformfv(_, _, _))
+ .Times(0);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result_->size);
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_F(GLES2DecoderWithShaderTest, GetUniformfvBadSharedMemoryFails) {
+ GetUniformfv cmd;
+ cmd.Init(client_program_id_, kUniform2Location,
+ kInvalidSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetUniformfv(_, _, _))
+ .Times(0);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(client_program_id_, kUniform2Location,
+ kSharedMemoryId, kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+};
#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_autogen.h"