Index: gpu/command_buffer/build_gles2_cmd_buffer.py |
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py |
index 922c1f9488ae28991361e313a3fd3e92d75b142d..577861a1d0d108368157550d4fb93ee350ed8e86 100755 |
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py |
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py |
@@ -1372,8 +1372,7 @@ _NAMED_TYPE_INFO = { |
'type': 'GLenum', |
'is_complete': True, |
'valid': [ |
- #TODO(zmo): avoid using the direct number. |
- '0x9117', # GL_SYNC_GPU_COMMANDS_COMPLETE |
+ 'GL_SYNC_GPU_COMMANDS_COMPLETE', |
], |
'invalid': [ |
'0', |
@@ -2029,7 +2028,16 @@ _FUNCTION_INFO = { |
'cmd_args': |
'GLidProgram program, uint32_t name_bucket_id, GLint* location', |
'result': ['GLint'], |
- 'error_return': -1, # http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml |
+ 'error_return': -1, |
+ }, |
+ 'GetFragDataLocation': { |
+ 'type': 'Custom', |
+ 'data_transfer_methods': ['shm'], |
+ 'cmd_args': |
+ 'GLidProgram program, uint32_t name_bucket_id, GLint* location', |
+ 'result': ['GLint'], |
+ 'error_return': -1, |
+ 'unsafe': True, |
}, |
'GetBooleanv': { |
'type': 'GETn', |
@@ -2441,7 +2449,6 @@ _FUNCTION_INFO = { |
'type': 'PUTSTR', |
'decoder_func': 'DoShaderSource', |
'data_transfer_methods': ['bucket'], |
- 'client_test': False, |
'cmd_args': |
'GLuint shader, const char** str', |
'pepper_args': |
@@ -3840,7 +3847,7 @@ TEST_F(GLES2ImplementationTest, %(name)sInvalidConstantArg%(invalid_index)d) { |
}) |
else: |
if client_test != False: |
- file.Write("// TODO: Implement unit test for %s\n" % func.name) |
+ file.Write("// TODO(zmo): Implement unit test for %s\n" % func.name) |
def WriteDestinationInitalizationValidation(self, func, file): |
"""Writes the client side destintion initialization validation.""" |
@@ -6507,6 +6514,245 @@ class PUTSTRHandler(ArrayArgTypeHandler): |
file.Write("}\n") |
file.Write("\n") |
+ def WriteGLES2ImplementationUnitTest(self, func, file): |
+ """Overrriden from TypeHandler.""" |
+ code = """ |
+TEST_F(GLES2ImplementationTest, %(name)s) { |
+ const uint32 kBucketId = GLES2Implementation::kResultBucketId; |
+ const char* kString1 = "happy"; |
+ const char* kString2 = "ending"; |
+ const size_t kString1Size = ::strlen(kString1) + 1; |
+ const size_t kString2Size = ::strlen(kString2) + 1; |
+ const size_t kHeaderSize = sizeof(GLint) * 3; |
+ const size_t kSourceSize = kHeaderSize + kString1Size + kString2Size; |
+ const size_t kPaddedHeaderSize = |
+ transfer_buffer_->RoundToAlignment(kHeaderSize); |
+ const size_t kPaddedString1Size = |
+ transfer_buffer_->RoundToAlignment(kString1Size); |
+ const size_t kPaddedString2Size = |
+ transfer_buffer_->RoundToAlignment(kString2Size); |
+ struct Cmds { |
+ cmd::SetBucketSize set_bucket_size; |
+ cmd::SetBucketData set_bucket_header; |
+ cmd::SetToken set_token1; |
+ cmd::SetBucketData set_bucket_data1; |
+ cmd::SetToken set_token2; |
+ cmd::SetBucketData set_bucket_data2; |
+ cmd::SetToken set_token3; |
+ cmds::ShaderSourceBucket shader_source_bucket; |
+ cmd::SetBucketSize clear_bucket_size; |
+ }; |
+ |
+ ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize); |
+ ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size); |
+ ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size); |
+ |
+ Cmds expected; |
+ expected.set_bucket_size.Init(kBucketId, kSourceSize); |
+ expected.set_bucket_header.Init( |
+ kBucketId, 0, kHeaderSize, mem0.id, mem0.offset); |
+ expected.set_token1.Init(GetNextToken()); |
+ expected.set_bucket_data1.Init( |
+ kBucketId, kHeaderSize, kString1Size, mem1.id, mem1.offset); |
+ expected.set_token2.Init(GetNextToken()); |
+ expected.set_bucket_data2.Init( |
+ kBucketId, kHeaderSize + kString1Size, kString2Size, mem2.id, |
+ mem2.offset); |
+ expected.set_token3.Init(GetNextToken()); |
+ expected.shader_source_bucket.Init(%(cmd_args)s, kBucketId); |
+ expected.clear_bucket_size.Init(kBucketId, 0); |
+ const char* kStrings[] = { kString1, kString2 }; |
+ gl_->%(name)s(%(gl_args)s); |
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); |
+} |
+""" |
+ gl_args = [] |
+ cmd_args = [] |
+ for arg in func.GetOriginalArgs(): |
+ if arg == self.__GetDataArg(func): |
+ gl_args.append('kStrings') |
+ elif arg == self.__GetLengthArg(func): |
+ gl_args.append('NULL') |
+ elif arg.name == 'count': |
+ gl_args.append('2') |
+ else: |
+ gl_args.append(arg.GetValidClientSideArg(func)) |
+ cmd_args.append(arg.GetValidClientSideArg(func)) |
+ file.Write(code % { |
+ 'name': func.name, |
+ 'gl_args': ", ".join(gl_args), |
+ 'cmd_args': ", ".join(cmd_args), |
+ }) |
+ |
+ if self.__GetLengthArg(func) == None: |
+ return |
+ code = """ |
+TEST_F(GLES2ImplementationTest, %(name)sWithLength) { |
+ const uint32 kBucketId = GLES2Implementation::kResultBucketId; |
+ const char* kString = "foobar******"; |
+ const size_t kStringSize = 6; // We only need "foobar". |
+ const size_t kHeaderSize = sizeof(GLint) * 2; |
+ const size_t kSourceSize = kHeaderSize + kStringSize + 1; |
+ const size_t kPaddedHeaderSize = |
+ transfer_buffer_->RoundToAlignment(kHeaderSize); |
+ const size_t kPaddedStringSize = |
+ transfer_buffer_->RoundToAlignment(kStringSize + 1); |
+ struct Cmds { |
+ cmd::SetBucketSize set_bucket_size; |
+ cmd::SetBucketData set_bucket_header; |
+ cmd::SetToken set_token1; |
+ cmd::SetBucketData set_bucket_data; |
+ cmd::SetToken set_token2; |
+ cmds::ShaderSourceBucket shader_source_bucket; |
+ cmd::SetBucketSize clear_bucket_size; |
+ }; |
+ |
+ ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize); |
+ ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedStringSize); |
+ |
+ Cmds expected; |
+ expected.set_bucket_size.Init(kBucketId, kSourceSize); |
+ expected.set_bucket_header.Init( |
+ kBucketId, 0, kHeaderSize, mem0.id, mem0.offset); |
+ expected.set_token1.Init(GetNextToken()); |
+ expected.set_bucket_data.Init( |
+ kBucketId, kHeaderSize, kStringSize + 1, mem1.id, mem1.offset); |
+ expected.set_token2.Init(GetNextToken()); |
+ expected.shader_source_bucket.Init(%(cmd_args)s, kBucketId); |
+ expected.clear_bucket_size.Init(kBucketId, 0); |
+ const char* kStrings[] = { kString }; |
+ const GLint kLength[] = { kStringSize }; |
+ gl_->%(name)s(%(gl_args)s); |
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); |
+} |
+""" |
+ gl_args = [] |
+ for arg in func.GetOriginalArgs(): |
+ if arg == self.__GetDataArg(func): |
+ gl_args.append('kStrings') |
+ elif arg == self.__GetLengthArg(func): |
+ gl_args.append('kLength') |
+ elif arg.name == 'count': |
+ gl_args.append('1') |
+ else: |
+ gl_args.append(arg.GetValidClientSideArg(func)) |
+ file.Write(code % { |
+ 'name': func.name, |
+ 'gl_args': ", ".join(gl_args), |
+ 'cmd_args': ", ".join(cmd_args), |
+ }) |
+ |
+ def WriteBucketServiceUnitTest(self, func, file, *extras): |
+ """Overrriden from TypeHandler.""" |
+ cmd_args = [] |
+ cmd_args_with_invalid_id = [] |
+ for index, arg in enumerate(func.GetOriginalArgs()): |
+ if (arg == self.__GetLengthArg(func) or |
+ arg == self.__GetDataArg(func) or arg.name == 'count'): |
+ continue |
+ if index == 0: # Resource ID arg |
+ cmd_args.append(arg.GetValidArg(func)) |
+ cmd_args_with_invalid_id.append('kInvalidClientId') |
+ else: |
+ cmd_args.append(arg.GetValidArg(func)) |
+ cmd_args_with_invalid_id.append(arg.GetValidArg(func)) |
+ |
+ test = """ |
+TEST_P(%(test_name)s, %(name)sValidArgs) { |
+ const uint32 kBucketId = 123; |
+ const char kSource0[] = "hello"; |
+ const char* kSource[] = { kSource0 }; |
+ const char kValidStrEnd = 0; |
+ SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); |
+ cmds::%(name)s cmd; |
+ cmd.Init(%(cmd_args)s, kBucketId); |
+ decoder_->set_unsafe_es3_apis_enabled(true); |
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));""" |
+ if func.IsUnsafe(): |
+ test += """ |
+ decoder_->set_unsafe_es3_apis_enabled(false); |
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); |
+""" |
+ test += """ |
+} |
+""" |
+ self.WriteValidUnitTest(func, file, test, { |
+ 'cmd_args': ", ".join(cmd_args), |
+ }, *extras) |
+ |
+ test = """ |
+TEST_P(%(test_name)s, %(name)sInvalidArgs) { |
+ const uint32 kBucketId = 123; |
+ const char kSource0[] = "hello"; |
+ const char* kSource[] = { kSource0 }; |
+ const char kValidStrEnd = 0; |
+ decoder_->set_unsafe_es3_apis_enabled(true); |
+ cmds::%(name)s cmd; |
+ // Test no bucket. |
+ cmd.Init(%(cmd_args)s, kBucketId); |
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); |
+ // Test invalid client. |
+ SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); |
+ cmd.Init(%(cmd_args_with_invalid_id)s, kBucketId); |
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); |
+} |
+""" |
+ self.WriteValidUnitTest(func, file, test, { |
+ 'cmd_args': ", ".join(cmd_args), |
+ 'cmd_args_with_invalid_id': ", ".join(cmd_args_with_invalid_id), |
+ }, *extras) |
+ |
+ test = """ |
+TEST_P(%(test_name)s, %(name)sInvalidHeader) { |
+ const uint32 kBucketId = 123; |
+ const char kSource0[] = "hello"; |
+ const char* kSource[] = { kSource0 }; |
+ const char kValidStrEnd = 0; |
+ const GLsizei kCount = static_cast<GLsizei>(arraysize(kSource)); |
+ const GLsizei kTests[] = { |
+ kCount, |
+ 0, |
+ std::numeric_limits<GLsizei>::max(), |
+ -1, |
+ kCount, |
+ }; |
+ decoder_->set_unsafe_es3_apis_enabled(true); |
+ for (size_t ii = 0; ii < arraysize(kTests); ++ii) { |
+ SetBucketAsCStrings(kBucketId, 1, kSource, kTests[ii], kValidStrEnd); |
+ cmds::%(name)s cmd; |
+ cmd.Init(%(cmd_args)s, kBucketId); |
+ if (kTests[ii] == kCount) { |
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
+ } else { |
+ EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); |
+ } |
+ } |
+ EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
+} |
+""" |
+ self.WriteValidUnitTest(func, file, test, { |
+ 'cmd_args': ", ".join(cmd_args), |
+ }, *extras) |
+ |
+ test = """ |
+TEST_P(%(test_name)s, %(name)sInvalidStringEnding) { |
+ const uint32 kBucketId = 123; |
+ const char kSource0[] = "hello"; |
+ const char* kSource[] = { kSource0 }; |
+ const char kInvalidStrEnd = '*'; |
+ SetBucketAsCStrings(kBucketId, 1, kSource, 1, kInvalidStrEnd); |
+ cmds::%(name)s cmd; |
+ cmd.Init(%(cmd_args)s, kBucketId); |
+ decoder_->set_unsafe_es3_apis_enabled(true); |
+ EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); |
+ EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
+} |
+""" |
+ self.WriteValidUnitTest(func, file, test, { |
+ 'cmd_args': ", ".join(cmd_args), |
+ }, *extras) |
+ |
class PUTXnHandler(ArrayArgTypeHandler): |
"""Handler for glUniform?f functions.""" |
@@ -7539,39 +7785,6 @@ class ImmediatePointerArgument(Argument): |
return "static_cast<const void*>(%s)" % self.name |
-class BucketPointerArgument(Argument): |
- """A class that represents an bucket argument to a function.""" |
- |
- def __init__(self, name, type): |
- Argument.__init__(self, name, type) |
- |
- def AddCmdArgs(self, args): |
- """Overridden from Argument.""" |
- pass |
- |
- def WriteGetCode(self, file): |
- """Overridden from Argument.""" |
- file.Write( |
- " %s %s = bucket->GetData(0, data_size);\n" % |
- (self.type, self.name)) |
- |
- def WriteValidationCode(self, file, func): |
- """Overridden from Argument.""" |
- pass |
- |
- def GetImmediateVersion(self): |
- """Overridden from Argument.""" |
- return None |
- |
- def WriteDestinationInitalizationValidation(self, file, func): |
- """Overridden from Argument.""" |
- self.WriteDestinationInitalizationValidatationIfNeeded(file, func) |
- |
- def GetLogArg(self): |
- """Overridden from Argument.""" |
- return "static_cast<const void*>(%s)" % self.name |
- |
- |
class PointerArgument(Argument): |
"""A class that represents a pointer argument to a function.""" |
@@ -7579,11 +7792,11 @@ class PointerArgument(Argument): |
Argument.__init__(self, name, type) |
def IsPointer(self): |
- """Returns true if argument is a pointer.""" |
+ """Overridden from Argument.""" |
return True |
def IsPointer2D(self): |
- """Returns true if argument is a 2D pointer.""" |
+ """Overridden from Argument.""" |
return self.type.count('*') == 2 |
def GetPointedType(self): |
@@ -7661,12 +7874,53 @@ class PointerArgument(Argument): |
self.WriteDestinationInitalizationValidatationIfNeeded(file, func) |
+class BucketPointerArgument(PointerArgument): |
+ """A class that represents an bucket argument to a function.""" |
+ |
+ def __init__(self, name, type): |
+ Argument.__init__(self, name, type) |
+ |
+ def AddCmdArgs(self, args): |
+ """Overridden from Argument.""" |
+ pass |
+ |
+ def WriteGetCode(self, file): |
+ """Overridden from Argument.""" |
+ file.Write( |
+ " %s %s = bucket->GetData(0, data_size);\n" % |
+ (self.type, self.name)) |
+ |
+ def WriteValidationCode(self, file, func): |
+ """Overridden from Argument.""" |
+ pass |
+ |
+ def GetImmediateVersion(self): |
+ """Overridden from Argument.""" |
+ return None |
+ |
+ def WriteDestinationInitalizationValidation(self, file, func): |
+ """Overridden from Argument.""" |
+ self.WriteDestinationInitalizationValidatationIfNeeded(file, func) |
+ |
+ def GetLogArg(self): |
+ """Overridden from Argument.""" |
+ return "static_cast<const void*>(%s)" % self.name |
+ |
+ |
class InputStringBucketArgument(Argument): |
"""A string input argument where the string is passed in a bucket.""" |
def __init__(self, name, type): |
Argument.__init__(self, name + "_bucket_id", "uint32_t") |
+ def IsPointer(self): |
+ """Overridden from Argument.""" |
+ return True |
+ |
+ def IsPointer2D(self): |
+ """Overridden from Argument.""" |
+ return False |
+ |
class InputStringArrayBucketArgument(Argument): |
"""A string array input argument where the strings are passed in a bucket.""" |
@@ -7732,6 +7986,14 @@ class InputStringArrayBucketArgument(Argument): |
def GetValidGLArg(self, func): |
return "_" |
+ def IsPointer(self): |
+ """Overridden from Argument.""" |
+ return True |
+ |
+ def IsPointer2D(self): |
+ """Overridden from Argument.""" |
+ return True |
+ |
class ResourceIdArgument(Argument): |
"""A class that represents a resource id argument to a function.""" |
@@ -8635,6 +8897,15 @@ class GLGenerator(object): |
def WriteFormat(self, filename): |
"""Writes the command buffer format""" |
file = CHeaderWriter(filename) |
+ # Forward declaration of a few enums used in constant argument |
+ # to avoid including GL header files. |
+ enum_defines = { |
+ 'GL_SYNC_GPU_COMMANDS_COMPLETE': 0x9117, |
+ } |
+ file.Write('\n') |
+ for enum in enum_defines: |
+ file.Write("#define %s 0x%x\n" % (enum, enum_defines[enum])) |
+ file.Write('\n') |
for func in self.functions: |
if True: |
#gen_cmd = func.GetInfo('gen_cmd') |