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 38cbb494e9f7316ae51ad0f02dce7a7c26bf5107..922c1f9488ae28991361e313a3fd3e92d75b142d 100755 |
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py |
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py |
@@ -1368,6 +1368,27 @@ _NAMED_TYPE_INFO = { |
'GL_UNKNOWN_CONTEXT_RESET_ARB', |
], |
}, |
+ 'SyncCondition': { |
+ 'type': 'GLenum', |
+ 'is_complete': True, |
+ 'valid': [ |
+ #TODO(zmo): avoid using the direct number. |
+ '0x9117', # GL_SYNC_GPU_COMMANDS_COMPLETE |
+ ], |
+ 'invalid': [ |
+ '0', |
+ ], |
+ }, |
+ 'SyncFlags': { |
+ 'type': 'GLbitfield', |
+ 'is_complete': True, |
+ 'valid': [ |
+ '0', |
+ ], |
+ 'invalid': [ |
+ '1', |
+ ], |
+ }, |
} |
# This table specifies the different pepper interfaces that are supported for |
@@ -1815,7 +1836,7 @@ _FUNCTION_INFO = { |
'resource_type': 'Framebuffer', |
'resource_types': 'Framebuffers', |
}, |
- 'DeleteProgram': {'type': 'Delete', 'decoder_func': 'DoDeleteProgram'}, |
+ 'DeleteProgram': { 'type': 'Delete' }, |
'DeleteRenderbuffers': { |
'type': 'DELn', |
'gl_test_func': 'glDeleteRenderbuffersEXT', |
@@ -1828,7 +1849,13 @@ _FUNCTION_INFO = { |
'resource_types': 'Samplers', |
'unsafe': True, |
}, |
- 'DeleteShader': {'type': 'Delete', 'decoder_func': 'DoDeleteShader'}, |
+ 'DeleteShader': { 'type': 'Delete' }, |
+ 'DeleteSync': { |
+ 'type': 'Delete', |
+ 'cmd_args': 'GLuint sync', |
+ 'resource_type': 'Sync', |
+ 'unsafe': True, |
+ }, |
'DeleteTextures': { |
'type': 'DELn', |
'resource_type': 'Texture', |
@@ -1883,6 +1910,11 @@ _FUNCTION_INFO = { |
'decoder_func': 'DoEnableVertexAttribArray', |
'impl_decl': False, |
}, |
+ 'FenceSync': { |
+ 'type': 'Create', |
+ 'client_test': False, |
+ 'unsafe': True, |
+ }, |
'Finish': { |
'impl_func': False, |
'client_test': False, |
@@ -2209,6 +2241,7 @@ _FUNCTION_INFO = { |
'IsEnabled': { |
'type': 'Is', |
'decoder_func': 'DoIsEnabled', |
+ 'client_test': False, |
'impl_func': False, |
'expectation': False, |
}, |
@@ -2238,6 +2271,13 @@ _FUNCTION_INFO = { |
'expectation': False, |
'unsafe': True, |
}, |
+ 'IsSync': { |
+ 'type': 'Is', |
+ 'id_mapping': [ 'Sync' ], |
+ 'cmd_args': 'GLuint sync', |
+ 'expectation': False, |
+ 'unsafe': True, |
+ }, |
'IsTexture': { |
'type': 'Is', |
'decoder_func': 'DoIsTexture', |
@@ -2398,12 +2438,12 @@ _FUNCTION_INFO = { |
'client_test': False, |
}, |
'ShaderSource': { |
- 'type': 'Manual', |
+ 'type': 'PUTSTR', |
+ 'decoder_func': 'DoShaderSource', |
'data_transfer_methods': ['bucket'], |
- 'needs_size': True, |
'client_test': False, |
'cmd_args': |
- 'GLuint shader, const char* data', |
+ 'GLuint shader, const char** str', |
'pepper_args': |
'GLuint shader, GLsizei count, const char** str, const GLint* length', |
}, |
@@ -3383,17 +3423,23 @@ static_assert(offsetof(%(cmd_name)s::Result, %(field_name)s) == %(offset)d, |
file.Write(" // TODO(gman): Compute correct size.\n") |
file.Write(" EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);\n") |
+ def __WriteIdMapping(self, func, file): |
+ """Writes client side / service side ID mapping.""" |
+ if not func.IsUnsafe() or not func.GetInfo('id_mapping'): |
+ return |
+ for id_type in func.GetInfo('id_mapping'): |
+ file.Write(" group_->Get%sServiceId(%s, &%s);\n" % |
+ (id_type, id_type.lower(), id_type.lower())) |
+ |
def WriteImmediateHandlerImplementation (self, func, file): |
"""Writes the handler impl for the immediate version of a command.""" |
- if func.IsUnsafe() and func.GetInfo('id_mapping'): |
- for id_type in func.GetInfo('id_mapping'): |
- file.Write(" group_->Get%sServiceId(%s, &%s);\n" % |
- (id_type, id_type.lower(), id_type.lower())) |
+ self.__WriteIdMapping(func, file) |
file.Write(" %s(%s);\n" % |
(func.GetGLFunctionName(), func.MakeOriginalArgString(""))) |
def WriteBucketHandlerImplementation (self, func, file): |
"""Writes the handler impl for the bucket version of a command.""" |
+ self.__WriteIdMapping(func, file) |
file.Write(" %s(%s);\n" % |
(func.GetGLFunctionName(), func.MakeOriginalArgString(""))) |
@@ -3449,9 +3495,7 @@ static_assert(offsetof(%(cmd_name)s::Result, %(field_name)s) == %(offset)d, |
self.WriteServiceHandlerFunctionHeader(func, file) |
self.WriteHandlerExtensionCheck(func, file) |
self.WriteHandlerDeferReadWrite(func, file); |
- for arg in func.GetOriginalArgs(): |
- if arg.IsPointer(): |
- self.WriteGetDataSizeCode(func, file) |
+ for arg in func.GetCmdArgs(): |
arg.WriteGetCode(file) |
func.WriteHandlerValidation(file) |
func.WriteHandlerImplementation(file) |
@@ -4252,10 +4296,6 @@ class HandWrittenHandler(CustomHandler): |
"""Overrriden from TypeHandler.""" |
pass |
- def WriteBucketCmdHelper(self, func, file): |
- """Overrriden from TypeHandler.""" |
- pass |
- |
def WriteCmdHelper(self, func, file): |
"""Overrriden from TypeHandler.""" |
pass |
@@ -4942,26 +4982,61 @@ class CreateHandler(TypeHandler): |
"""Overrriden from TypeHandler.""" |
func.AddCmdArg(Argument("client_id", 'uint32_t')) |
+ def __GetResourceType(self, func): |
+ if func.return_type == "GLsync": |
+ return "Sync" |
+ else: |
+ return func.name[6:] # Create* |
+ |
def WriteServiceUnitTest(self, func, file, *extras): |
"""Overrriden from TypeHandler.""" |
valid_test = """ |
TEST_P(%(test_name)s, %(name)sValidArgs) { |
- EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)) |
- .WillOnce(Return(kNewServiceId)); |
+ %(id_type_cast)sEXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)) |
+ .WillOnce(Return(%(const_service_id)s)); |
SpecializedSetup<cmds::%(name)s, 0>(true); |
cmds::%(name)s cmd; |
- cmd.Init(%(args)s%(comma)skNewClientId); |
+ cmd.Init(%(args)s%(comma)skNewClientId);""" |
+ if func.IsUnsafe(): |
+ valid_test += """ |
+ decoder_->set_unsafe_es3_apis_enabled(true);""" |
+ valid_test += """ |
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); |
- EXPECT_EQ(GL_NO_ERROR, GetGLError()); |
- EXPECT_TRUE(Get%(resource_type)s(kNewClientId) != NULL); |
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());""" |
+ if func.IsUnsafe(): |
+ valid_test += """ |
+ %(return_type)s service_id = 0; |
+ EXPECT_TRUE(Get%(resource_type)sServiceId(kNewClientId, &service_id)); |
+ EXPECT_EQ(%(const_service_id)s, service_id); |
+ decoder_->set_unsafe_es3_apis_enabled(false); |
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); |
+} |
+""" |
+ else: |
+ valid_test += """ |
+ EXPECT_TRUE(Get%(resource_type)s(kNewClientId)); |
} |
""" |
comma = "" |
- if len(func.GetOriginalArgs()): |
- comma =", " |
+ cmd_arg_count = 0 |
+ for arg in func.GetOriginalArgs(): |
+ if not arg.IsConstant(): |
+ cmd_arg_count += 1 |
+ if cmd_arg_count: |
+ comma = ", " |
+ if func.return_type == 'GLsync': |
+ id_type_cast = ("const GLsync kNewServiceIdGLuint = reinterpret_cast" |
+ "<GLsync>(kNewServiceId);\n ") |
+ const_service_id = "kNewServiceIdGLuint" |
+ else: |
+ id_type_cast = "" |
+ const_service_id = "kNewServiceId" |
self.WriteValidUnitTest(func, file, valid_test, { |
'comma': comma, |
- 'resource_type': func.name[6:], |
+ 'resource_type': self.__GetResourceType(func), |
+ 'return_type': func.return_type, |
+ 'id_type_cast': id_type_cast, |
+ 'const_service_id': const_service_id, |
}, *extras) |
invalid_test = """ |
TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) { |
@@ -4978,11 +5053,33 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) { |
def WriteHandlerImplementation (self, func, file): |
"""Overrriden from TypeHandler.""" |
- file.Write(" uint32_t client_id = c.client_id;\n") |
- file.Write(" if (!%sHelper(%s)) {\n" % |
- (func.name, func.MakeCmdArgString(""))) |
- file.Write(" return error::kInvalidArguments;\n") |
- file.Write(" }\n") |
+ if func.IsUnsafe(): |
+ code = """ uint32_t client_id = c.client_id; |
+ %(return_type)s service_id = 0; |
+ if (group_->Get%(resource_name)sServiceId(client_id, &service_id)) { |
+ return error::kInvalidArguments; |
+ } |
+ service_id = %(gl_func_name)s(%(gl_args)s); |
+ if (service_id) { |
+ group_->Add%(resource_name)sId(client_id, service_id); |
+ } |
+""" |
+ else: |
+ code = """ uint32_t client_id = c.client_id; |
+ if (Get%(resource_name)s(client_id)) { |
+ return error::kInvalidArguments; |
+ } |
+ %(return_type)s service_id = %(gl_func_name)s(%(gl_args)s); |
+ if (service_id) { |
+ Create%(resource_name)s(client_id, service_id%(gl_args_with_comma)s); |
+ } |
+""" |
+ file.Write(code % { |
+ 'resource_name': self.__GetResourceType(func), |
+ 'return_type': func.return_type, |
+ 'gl_func_name': func.GetGLFunctionName(), |
+ 'gl_args': func.MakeOriginalArgString(""), |
+ 'gl_args_with_comma': func.MakeOriginalArgString("", True) }) |
def WriteGLES2Implementation(self, func, file): |
"""Overrriden from TypeHandler.""" |
@@ -4995,14 +5092,21 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) { |
for arg in func.GetOriginalArgs(): |
arg.WriteClientSideValidationCode(file, func) |
file.Write(" GLuint client_id;\n") |
- file.Write( |
- " GetIdHandler(id_namespaces::kProgramsAndShaders)->\n") |
+ if func.return_type == "GLsync": |
+ file.Write( |
+ " GetIdHandler(id_namespaces::kSyncs)->\n") |
+ else: |
+ file.Write( |
+ " GetIdHandler(id_namespaces::kProgramsAndShaders)->\n") |
file.Write(" MakeIds(this, 0, 1, &client_id);\n") |
file.Write(" helper_->%s(%s);\n" % |
(func.name, func.MakeCmdArgString(""))) |
file.Write(' GPU_CLIENT_LOG("returned " << client_id);\n') |
file.Write(" CheckGLError();\n") |
- file.Write(" return client_id;\n") |
+ if func.return_type == "GLsync": |
+ file.Write(" return reinterpret_cast<GLsync>(client_id);\n") |
+ else: |
+ file.Write(" return client_id;\n") |
file.Write("}\n") |
file.Write("\n") |
@@ -5015,6 +5119,9 @@ class DeleteHandler(TypeHandler): |
def WriteServiceImplementation(self, func, file): |
"""Overrriden from TypeHandler.""" |
+ if func.IsUnsafe(): |
+ TypeHandler.WriteServiceImplementation(self, func, file) |
+ # HandleDeleteShader and HandleDeleteProgram are manually written. |
pass |
def WriteGLES2Implementation(self, func, file): |
@@ -5035,6 +5142,25 @@ class DeleteHandler(TypeHandler): |
file.Write("}\n") |
file.Write("\n") |
+ def WriteHandlerImplementation (self, func, file): |
+ """Overrriden from TypeHandler.""" |
+ assert len(func.GetOriginalArgs()) == 1 |
+ arg = func.GetOriginalArgs()[0] |
+ if func.IsUnsafe(): |
+ file.Write(""" %(arg_type)s service_id = 0; |
+ if (group_->Get%(resource_type)sServiceId(%(arg_name)s, &service_id)) { |
+ glDelete%(resource_type)s(service_id); |
+ group_->Remove%(resource_type)sId(%(arg_name)s); |
+ } else { |
+ LOCAL_SET_GL_ERROR( |
+ GL_INVALID_VALUE, "gl%(func_name)s", "unknown %(arg_name)s"); |
+ } |
+""" % { 'resource_type': func.GetInfo('resource_type'), |
+ 'arg_name': arg.name, |
+ 'arg_type': arg.type, |
+ 'func_name': func.original_name }) |
+ else: |
+ file.Write(" %sHelper(%s);\n" % (func.original_name, arg.name)) |
class DELnHandler(TypeHandler): |
"""Handler for glDelete___ type functions.""" |
@@ -6227,6 +6353,160 @@ TEST_F(GLES2ImplementationTest, %(name)sInvalidConstantArg%(invalid_index)d) { |
file.Write("}\n") |
file.Write("\n") |
+class PUTSTRHandler(ArrayArgTypeHandler): |
+ """Handler for functions that pass a string array.""" |
+ |
+ def __init__(self): |
+ ArrayArgTypeHandler.__init__(self) |
+ |
+ def __GetDataArg(self, func): |
+ """Return the argument that points to the 2D char arrays""" |
+ for arg in func.GetOriginalArgs(): |
+ if arg.IsPointer2D(): |
+ return arg |
+ return None |
+ |
+ def __GetLengthArg(self, func): |
+ """Return the argument that holds length for each char array""" |
+ for arg in func.GetOriginalArgs(): |
+ if arg.IsPointer() and not arg.IsPointer2D(): |
+ return arg |
+ return None |
+ |
+ def WriteGLES2Implementation(self, func, file): |
+ """Overrriden from TypeHandler.""" |
+ file.Write("%s GLES2Implementation::%s(%s) {\n" % |
+ (func.return_type, func.original_name, |
+ func.MakeTypedOriginalArgString(""))) |
+ file.Write(" GPU_CLIENT_SINGLE_THREAD_CHECK();\n") |
+ func.WriteDestinationInitalizationValidation(file) |
+ self.WriteClientGLCallLog(func, file) |
+ data_arg = self.__GetDataArg(func) |
+ length_arg = self.__GetLengthArg(func) |
+ log_code_block = """ GPU_CLIENT_LOG_CODE_BLOCK({ |
+ for (GLsizei ii = 0; ii < count; ++ii) { |
+ if (%(data)s[ii]) {""" |
+ if length_arg == None: |
+ log_code_block += """ |
+ GPU_CLIENT_LOG(" " << ii << ": ---\\n" << %(data)s[ii] << "\\n---");""" |
+ else: |
+ log_code_block += """ |
+ if (%(length)s && %(length)s[ii] >= 0) { |
+ const std::string my_str(%(data)s[ii], %(length)s[ii]); |
+ GPU_CLIENT_LOG(" " << ii << ": ---\\n" << my_str << "\\n---"); |
+ } else { |
+ GPU_CLIENT_LOG(" " << ii << ": ---\\n" << %(data)s[ii] << "\\n---"); |
+ }""" |
+ log_code_block += """ |
+ } else { |
+ GPU_CLIENT_LOG(" " << ii << ": NULL"); |
+ } |
+ } |
+ }); |
+""" |
+ file.Write(log_code_block % { |
+ 'data': data_arg.name, |
+ 'length': length_arg.name if not length_arg == None else '' |
+ }) |
+ for arg in func.GetOriginalArgs(): |
+ arg.WriteClientSideValidationCode(file, func) |
+ size_code_block = """ // Compute the total size. |
+ base::CheckedNumeric<size_t> total_size = count; |
+ total_size += 1; |
+ total_size *= sizeof(GLint); |
+ if (!total_size.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, "glShaderSource", "overflow"); |
+ return; |
+ } |
+ size_t header_size = total_size.ValueOrDefault(0); |
+ std::vector<GLint> header(count + 1); |
+ header[0] = static_cast<GLint>(count); |
+ for (GLsizei ii = 0; ii < count; ++ii) { |
+ GLint len = 0; |
+ if (%(data)s[ii]) {""" |
+ if length_arg == None: |
+ size_code_block += """ |
+ len = base::static_cast<GLint>(strlen(%(data)s[ii]));""" |
+ else: |
+ size_code_block += """ |
+ len = (%(length)s && %(length)s[ii] >= 0) ? |
+ %(length)s[ii] : base::checked_cast<GLint>(strlen(%(data)s[ii]));""" |
+ size_code_block += """ |
+ } |
+ total_size += len; |
+ total_size += 1; // NULL at the end of each char array. |
+ if (!total_size.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, "glShaderSource", "overflow"); |
+ return; |
+ } |
+ header[ii + 1] = len; |
+} |
+""" |
+ file.Write(size_code_block % { |
+ 'data': data_arg.name, |
+ 'length': length_arg.name if not length_arg == None else '' |
+ }) |
+ data_code_block = """ // Pack data into a bucket on the service. |
+ helper_->SetBucketSize(kResultBucketId, total_size.ValueOrDefault(0)); |
+ size_t offset = 0; |
+ for (GLsizei ii = 0; ii <= count; ++ii) { |
+ const char* src = (ii == 0) ? reinterpret_cast<const char*>(&header[0]) : |
+ %(data)s[ii - 1]; |
+ base::CheckedNumeric<size_t> checked_size = (ii == 0) ? header_size : |
+ static_cast<size_t>(header[ii]); |
+ if (ii > 0) { |
+ checked_size += 1; // NULL in the end. |
+ } |
+ if (!checked_size.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, "glShaderSource", "overflow"); |
+ return; |
+ } |
+ size_t size = checked_size.ValueOrDefault(0); |
+ while (size) { |
+ ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); |
+ if (!buffer.valid() || buffer.size() == 0) { |
+ SetGLError(GL_OUT_OF_MEMORY, "glShaderSource", "too large"); |
+ return; |
+ } |
+ size_t copy_size = buffer.size(); |
+ if (ii > 0 && buffer.size() == size) |
+ --copy_size; |
+ if (copy_size) |
+ memcpy(buffer.address(), src, copy_size); |
+ if (copy_size < buffer.size()) { |
+ // Append NULL in the end. |
+ DCHECK(copy_size + 1 == buffer.size()); |
+ char* str = reinterpret_cast<char*>(buffer.address()); |
+ str[copy_size] = 0; |
+ } |
+ helper_->SetBucketData(kResultBucketId, offset, buffer.size(), |
+ buffer.shm_id(), buffer.offset()); |
+ offset += buffer.size(); |
+ src += buffer.size(); |
+ size -= buffer.size(); |
+ } |
+ } |
+ DCHECK_EQ(total_size.ValueOrDefault(0), offset); |
+""" |
+ file.Write(data_code_block % { |
+ 'data': data_arg.name, |
+ 'length': length_arg.name if not length_arg == None else '' |
+ }) |
+ bucket_cmd_arg_string = "" |
+ for arg in func.GetCmdArgs()[0:-2]: |
+ if bucket_cmd_arg_string: |
+ bucket_cmd_arg_string += ", " |
+ bucket_cmd_arg_string += arg.name |
+ if bucket_cmd_arg_string: |
+ bucket_cmd_arg_string += ", " |
+ bucket_cmd_arg_string += 'kResultBucketId' |
+ file.Write(" helper_->%sBucket(%s);\n" % |
+ (func.name, bucket_cmd_arg_string)) |
+ file.Write(" helper_->SetBucketSize(kResultBucketId, 0);"); |
+ file.Write(" CheckGLError();\n") |
+ file.Write("}\n") |
+ file.Write("\n") |
+ |
class PUTXnHandler(ArrayArgTypeHandler): |
"""Handler for glUniform?f functions.""" |
@@ -6561,8 +6841,10 @@ TEST_P(%(test_name)s, %(name)sInvalidArgsBadSharedMemoryId) { |
if func.IsUnsafe(): |
assert func.GetInfo('id_mapping') |
assert len(func.GetInfo('id_mapping')) == 1 |
+ assert len(args) == 1 |
id_type = func.GetInfo('id_mapping')[0] |
- file.Write(" *result_dst = group_->Get%sServiceId(%s, &%s);\n" % |
+ file.Write(" %s service_%s = 0;\n" % (args[0].type, id_type.lower())) |
+ file.Write(" *result_dst = group_->Get%sServiceId(%s, &service_%s);\n" % |
(id_type, id_type.lower(), id_type.lower())) |
else: |
file.Write(" *result_dst = %s(%s);\n" % |
@@ -6589,13 +6871,15 @@ TEST_P(%(test_name)s, %(name)sInvalidArgsBadSharedMemoryId) { |
file.Write(" return %s;\n" % error_value) |
file.Write(" }\n") |
file.Write(" *result = 0;\n") |
- arg_string = func.MakeOriginalArgString("") |
- comma = "" |
- if len(arg_string) > 0: |
- comma = ", " |
+ assert len(func.GetOriginalArgs()) == 1 |
+ id_arg = func.GetOriginalArgs()[0] |
+ if id_arg.type == 'GLsync': |
+ arg_string = "ToGLuint(%s)" % func.MakeOriginalArgString("") |
+ else: |
+ arg_string = func.MakeOriginalArgString("") |
file.Write( |
- " helper_->%s(%s%sGetResultShmId(), GetResultShmOffset());\n" % |
- (func.name, arg_string, comma)) |
+ " helper_->%s(%s, GetResultShmId(), GetResultShmOffset());\n" % |
+ (func.name, arg_string)) |
file.Write(" WaitForCmd();\n") |
file.Write(" %s result_value = *result" % func.return_type) |
if func.return_type == "GLboolean": |
@@ -6619,20 +6903,23 @@ TEST_F(GLES2ImplementationTest, %(name)s) { |
Cmds expected; |
ExpectedMemoryInfo result1 = |
GetExpectedResultMemory(sizeof(cmds::%(name)s::Result)); |
- expected.cmd.Init(1, result1.id, result1.offset); |
+ expected.cmd.Init(%(cmd_id_value)s, result1.id, result1.offset); |
EXPECT_CALL(*command_buffer(), OnFlush()) |
- .WillOnce(SetMemory(result1.ptr, uint32_t(1))) |
+ .WillOnce(SetMemory(result1.ptr, uint32_t(GL_TRUE))) |
.RetiresOnSaturation(); |
- GLboolean result = gl_->%(name)s(1); |
+ GLboolean result = gl_->%(name)s(%(gl_id_value)s); |
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); |
EXPECT_TRUE(result); |
} |
""" |
+ args = func.GetOriginalArgs() |
+ assert len(args) == 1 |
file.Write(code % { |
- 'name': func.name, |
- }) |
+ 'name': func.name, |
+ 'cmd_id_value': args[0].GetValidClientSideCmdArg(func), |
+ 'gl_id_value': args[0].GetValidClientSideArg(func) }) |
class STRnHandler(TypeHandler): |
@@ -6823,6 +7110,10 @@ class Argument(object): |
"""Returns true if argument is a pointer.""" |
return False |
+ def IsPointer2D(self): |
+ """Returns true if argument is a 2D pointer.""" |
+ return False |
+ |
def IsConstant(self): |
"""Returns true if the argument has only one valid value.""" |
return False |
@@ -6853,6 +7144,8 @@ class Argument(object): |
return valid_arg |
index = func.GetOriginalArgs().index(self) |
+ if self.type == 'GLsync': |
+ return ("reinterpret_cast<GLsync>(%d)" % (index + 1)) |
return str(index + 1) |
def GetValidClientSideCmdArg(self, func): |
@@ -6870,7 +7163,10 @@ class Argument(object): |
def GetValidGLArg(self, func): |
"""Gets a valid GL value for this argument.""" |
- return self.GetValidArg(func) |
+ value = self.GetValidArg(func) |
+ if self.type == 'GLsync': |
+ return ("reinterpret_cast<GLsync>(%s)" % value) |
+ return value |
def GetValidNonCachedClientSideArg(self, func): |
"""Returns a valid value for this argument in a GL call. |
@@ -6903,8 +7199,12 @@ class Argument(object): |
def WriteGetCode(self, file): |
"""Writes the code to get an argument from a command structure.""" |
+ if self.type == 'GLsync': |
+ my_type = 'GLuint' |
+ else: |
+ my_type = self.type |
file.Write(" %s %s = static_cast<%s>(c.%s);\n" % |
- (self.type, self.name, self.type, self.name)) |
+ (my_type, self.name, my_type, self.name)) |
def WriteValidationCode(self, file, func): |
"""Writes the validation code for an argument.""" |
@@ -7038,7 +7338,8 @@ class SizeNotNegativeArgument(SizeArgument): |
class EnumBaseArgument(Argument): |
- """Base class for EnumArgument, IntArgument and ValidatedBoolArgument""" |
+ """Base class for EnumArgument, IntArgument, BitfieldArgument, and |
+ ValidatedBoolArgument.""" |
def __init__(self, name, gl_type, type, gl_error): |
Argument.__init__(self, name, gl_type) |
@@ -7154,7 +7455,7 @@ class EnumArgument(EnumBaseArgument): |
class IntArgument(EnumBaseArgument): |
- """A class for a GLint argument that can only except specific values. |
+ """A class for a GLint argument that can only accept specific values. |
For example glTexImage2D takes a GLint for its internalformat |
argument instead of a GLenum. |
@@ -7165,7 +7466,7 @@ class IntArgument(EnumBaseArgument): |
class ValidatedBoolArgument(EnumBaseArgument): |
- """A class for a GLboolean argument that can only except specific values. |
+ """A class for a GLboolean argument that can only accept specific values. |
For example glUniformMatrix takes a GLboolean for it's transpose but it |
must be false. |
@@ -7179,6 +7480,18 @@ class ValidatedBoolArgument(EnumBaseArgument): |
return 'GLES2Util::GetStringBool(%s)' % self.name |
+class BitFieldArgument(EnumBaseArgument): |
+ """A class for a GLbitfield argument that can only accept specific values. |
+ |
+ For example glFenceSync takes a GLbitfield for its flags argument bit it |
+ must be 0. |
+ """ |
+ |
+ def __init__(self, name, type): |
+ EnumBaseArgument.__init__(self, name, "GLbitfield", type, |
+ "GL_INVALID_VALUE") |
+ |
+ |
class ImmediatePointerArgument(Argument): |
"""A class that represents an immediate argument to a function. |
@@ -7269,6 +7582,10 @@ class PointerArgument(Argument): |
"""Returns true if argument is a pointer.""" |
return True |
+ def IsPointer2D(self): |
+ """Returns true if argument is a 2D pointer.""" |
+ return self.type.count('*') == 2 |
+ |
def GetPointedType(self): |
match = re.match('(const\s+)?(?P<element_type>[\w]+)\s*\*', self.type) |
assert match |
@@ -7333,7 +7650,9 @@ class PointerArgument(Argument): |
def GetBucketVersion(self): |
"""Overridden from Argument.""" |
- if self.type == "const char*": |
+ if self.type.find('char') >= 0: |
+ if self.IsPointer2D(): |
+ return InputStringArrayBucketArgument(self.name, self.type) |
return InputStringBucketArgument(self.name, self.type) |
return BucketPointerArgument(self.name, self.type) |
@@ -7343,26 +7662,68 @@ class PointerArgument(Argument): |
class InputStringBucketArgument(Argument): |
- """An string input argument where the string is passed in a bucket.""" |
+ """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") |
+ |
+ |
+class InputStringArrayBucketArgument(Argument): |
+ """A string array input argument where the strings are passed in a bucket.""" |
def __init__(self, name, type): |
Argument.__init__(self, name + "_bucket_id", "uint32_t") |
+ self._original_name = name |
def WriteGetCode(self, file): |
"""Overridden from Argument.""" |
code = """ |
- Bucket* %(name)s_bucket = GetBucket(c.%(name)s); |
- if (!%(name)s_bucket) { |
+ const size_t kMinBucketSize = sizeof(GLint); |
+ // Each string has at least |length| in the header and a NUL character. |
+ const size_t kMinStringSize = sizeof(GLint) + 1; |
+ Bucket* bucket = GetBucket(c.%(name)s); |
+ if (!bucket) { |
+ return error::kInvalidArguments; |
+ } |
+ const size_t bucket_size = bucket->size(); |
+ if (bucket_size < kMinBucketSize) { |
+ return error::kInvalidArguments; |
+ } |
+ const char* bucket_data = bucket->GetDataAs<const char*>(0, bucket_size); |
+ const GLint* header = reinterpret_cast<const GLint*>(bucket_data); |
+ GLsizei count = static_cast<GLsizei>(header[0]); |
+ if (count < 0) { |
return error::kInvalidArguments; |
} |
- std::string %(name)s_str; |
- if (!%(name)s_bucket->GetAsString(&%(name)s_str)) { |
+ const size_t max_count = (bucket_size - kMinBucketSize) / kMinStringSize; |
+ if (max_count < static_cast<size_t>(count)) { |
+ return error::kInvalidArguments; |
+ } |
+ const GLint* length = header + 1; |
+ scoped_ptr<const char*[]> strs; |
+ if (count > 0) |
+ strs.reset(new const char*[count]); |
+ const char** %(original_name)s = strs.get(); |
+ base::CheckedNumeric<size_t> total_size = sizeof(GLint); |
+ total_size *= count + 1; // Header size. |
+ if (!total_size.IsValid()) |
+ return error::kInvalidArguments; |
+ for (GLsizei ii = 0; ii < count; ++ii) { |
+ %(original_name)s[ii] = bucket_data + total_size.ValueOrDefault(0); |
+ total_size += length[ii]; |
+ total_size += 1; // NUL char at the end of each char array. |
+ if (!total_size.IsValid() || total_size.ValueOrDefault(0) > bucket_size || |
+ %(original_name)s[ii][length[ii]] != 0) { |
+ return error::kInvalidArguments; |
+ } |
+ } |
+ if (total_size.ValueOrDefault(0) != bucket_size) { |
return error::kInvalidArguments; |
} |
- const char* %(name)s = %(name)s_str.c_str(); |
""" |
file.Write(code % { |
'name': self.name, |
+ 'original_name': self._original_name, |
}) |
def GetValidArg(self, func): |
@@ -7378,17 +7739,26 @@ class ResourceIdArgument(Argument): |
def __init__(self, name, type): |
match = re.match("(GLid\w+)", type) |
self.resource_type = match.group(1)[4:] |
- type = type.replace(match.group(1), "GLuint") |
+ if self.resource_type == "Sync": |
+ type = type.replace(match.group(1), "GLsync") |
+ else: |
+ type = type.replace(match.group(1), "GLuint") |
Argument.__init__(self, name, type) |
def WriteGetCode(self, file): |
"""Overridden from Argument.""" |
- file.Write(" %s %s = c.%s;\n" % (self.type, self.name, self.name)) |
+ if self.type == "GLsync": |
+ my_type = "GLuint" |
+ else: |
+ my_type = self.type |
+ file.Write(" %s %s = c.%s;\n" % (my_type, self.name, self.name)) |
def GetValidArg(self, func): |
return "client_%s_id_" % self.resource_type.lower() |
def GetValidGLArg(self, func): |
+ if self.resource_type == "Sync": |
+ return "reinterpret_cast<GLsync>(kService%sId)" % self.resource_type |
return "kService%sId" % self.resource_type |
@@ -7462,6 +7832,7 @@ class Function(object): |
'Manual': ManualHandler(), |
'PUT': PUTHandler(), |
'PUTn': PUTnHandler(), |
+ 'PUTSTR': PUTSTRHandler(), |
'PUTXn': PUTXnHandler(), |
'StateSet': StateSetHandler(), |
'StateSetRGBAlpha': StateSetRGBAlphaHandler(), |
@@ -7653,7 +8024,7 @@ class Function(object): |
return arg |
return None |
- def __MaybePrependComma(self, arg_string, add_comma): |
+ def _MaybePrependComma(self, arg_string, add_comma): |
"""Adds a comma if arg_string is not empty and add_comma is true.""" |
comma = "" |
if add_comma and len(arg_string): |
@@ -7665,14 +8036,14 @@ class Function(object): |
args = self.GetOriginalArgs() |
arg_string = ", ".join( |
["%s %s%s" % (arg.type, prefix, arg.name) for arg in args]) |
- return self.__MaybePrependComma(arg_string, add_comma) |
+ return self._MaybePrependComma(arg_string, add_comma) |
def MakeOriginalArgString(self, prefix, add_comma = False, separator = ", "): |
"""Gets the list of arguments as they are in GL.""" |
args = self.GetOriginalArgs() |
arg_string = separator.join( |
["%s%s" % (prefix, arg.name) for arg in args]) |
- return self.__MaybePrependComma(arg_string, add_comma) |
+ return self._MaybePrependComma(arg_string, add_comma) |
def MakeTypedHelperArgString(self, prefix, add_comma = False): |
"""Gets a list of typed GL arguments after removing unneeded arguments.""" |
@@ -7683,7 +8054,7 @@ class Function(object): |
prefix, |
arg.name, |
) for arg in args if not arg.IsConstant()]) |
- return self.__MaybePrependComma(arg_string, add_comma) |
+ return self._MaybePrependComma(arg_string, add_comma) |
def MakeHelperArgString(self, prefix, add_comma = False, separator = ", "): |
"""Gets a list of GL arguments after removing unneeded arguments.""" |
@@ -7691,7 +8062,7 @@ class Function(object): |
arg_string = separator.join( |
["%s%s" % (prefix, arg.name) |
for arg in args if not arg.IsConstant()]) |
- return self.__MaybePrependComma(arg_string, add_comma) |
+ return self._MaybePrependComma(arg_string, add_comma) |
def MakeTypedPepperArgString(self, prefix): |
"""Gets a list of arguments as they need to be for Pepper.""" |
@@ -7740,28 +8111,28 @@ class Function(object): |
args = self.GetCmdArgs() |
arg_string = ", ".join( |
["%s %s%s" % (arg.type, prefix, arg.name) for arg in args]) |
- return self.__MaybePrependComma(arg_string, add_comma) |
+ return self._MaybePrependComma(arg_string, add_comma) |
def MakeCmdArgString(self, prefix, add_comma = False): |
"""Gets the list of arguments as they need to be for command buffers.""" |
args = self.GetCmdArgs() |
arg_string = ", ".join( |
["%s%s" % (prefix, arg.name) for arg in args]) |
- return self.__MaybePrependComma(arg_string, add_comma) |
+ return self._MaybePrependComma(arg_string, add_comma) |
def MakeTypedInitString(self, prefix, add_comma = False): |
"""Gets a typed list of arguments as they need to be for cmd Init/Set.""" |
args = self.GetInitArgs() |
arg_string = ", ".join( |
["%s %s%s" % (arg.type, prefix, arg.name) for arg in args]) |
- return self.__MaybePrependComma(arg_string, add_comma) |
+ return self._MaybePrependComma(arg_string, add_comma) |
def MakeInitString(self, prefix, add_comma = False): |
"""Gets the list of arguments as they need to be for cmd Init/Set.""" |
args = self.GetInitArgs() |
arg_string = ", ".join( |
["%s%s" % (prefix, arg.name) for arg in args]) |
- return self.__MaybePrependComma(arg_string, add_comma) |
+ return self._MaybePrependComma(arg_string, add_comma) |
def MakeLogArgString(self): |
"""Makes a string of the arguments for the LOG macros""" |
@@ -8069,9 +8440,17 @@ class BucketFunction(Function): |
self.type_handler.WriteBucketHandlerImplementation(self, file) |
def WriteServiceUnitTest(self, file, *extras): |
- """Writes the service implementation for a command.""" |
+ """Overridden from Function""" |
self.type_handler.WriteBucketServiceUnitTest(self, file, *extras) |
+ def MakeOriginalArgString(self, prefix, add_comma = False, separator = ", "): |
+ """Overridden from Function""" |
+ args = self.GetOriginalArgs() |
+ arg_string = separator.join( |
+ ["%s%s" % (prefix, arg.name[0:-10] if arg.name.endswith("_bucket_id") |
+ else arg.name) for arg in args]) |
+ return super(BucketFunction, self)._MaybePrependComma(arg_string, add_comma) |
+ |
def CreateArg(arg_string): |
"""Creates an Argument.""" |
@@ -8092,6 +8471,8 @@ def CreateArg(arg_string): |
return ResourceIdArgument(arg_parts[-1], " ".join(arg_parts[0:-1])) |
elif arg_parts[0].startswith('GLenum') and len(arg_parts[0]) > 6: |
return EnumArgument(arg_parts[-1], " ".join(arg_parts[0:-1])) |
+ elif arg_parts[0].startswith('GLbitfield') and len(arg_parts[0]) > 10: |
+ return BitFieldArgument(arg_parts[-1], " ".join(arg_parts[0:-1])) |
elif arg_parts[0].startswith('GLboolean') and len(arg_parts[0]) > 9: |
return ValidatedBoolArgument(arg_parts[-1], " ".join(arg_parts[0:-1])) |
elif arg_parts[0].startswith('GLboolean'): |