Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """code generator for GLES2 command buffers.""" | 6 """code generator for GLES2 command buffers.""" |
| 7 | 7 |
| 8 import itertools | 8 import itertools |
| 9 import os | 9 import os |
| 10 import os.path | 10 import os.path |
| (...skipping 6455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6466 } | 6466 } |
| 6467 } | 6467 } |
| 6468 }); | 6468 }); |
| 6469 """ | 6469 """ |
| 6470 file.Write(log_code_block % { | 6470 file.Write(log_code_block % { |
| 6471 'data': data_arg.name, | 6471 'data': data_arg.name, |
| 6472 'length': length_arg.name if not length_arg == None else '' | 6472 'length': length_arg.name if not length_arg == None else '' |
| 6473 }) | 6473 }) |
| 6474 for arg in func.GetOriginalArgs(): | 6474 for arg in func.GetOriginalArgs(): |
| 6475 arg.WriteClientSideValidationCode(file, func) | 6475 arg.WriteClientSideValidationCode(file, func) |
| 6476 size_code_block = """ // Compute the total size. | 6476 |
| 6477 base::CheckedNumeric<size_t> total_size = count; | |
| 6478 total_size += 1; | |
| 6479 total_size *= sizeof(GLint); | |
| 6480 if (!total_size.IsValid()) { | |
| 6481 SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "overflow"); | |
| 6482 return; | |
| 6483 } | |
| 6484 size_t header_size = total_size.ValueOrDefault(0); | |
| 6485 std::vector<GLint> header(count + 1); | |
| 6486 header[0] = static_cast<GLint>(count); | |
| 6487 for (GLsizei ii = 0; ii < count; ++ii) { | |
| 6488 GLint len = 0; | |
| 6489 if (%(data)s[ii]) {""" | |
| 6490 if length_arg == None: | |
| 6491 size_code_block += """ | |
| 6492 len = static_cast<GLint>(strlen(%(data)s[ii]));""" | |
| 6493 else: | |
| 6494 size_code_block += """ | |
| 6495 len = (%(length)s && %(length)s[ii] >= 0) ? | |
| 6496 %(length)s[ii] : base::checked_cast<GLint>(strlen(%(data)s[ii]));""" | |
| 6497 size_code_block += """ | |
| 6498 } | |
| 6499 total_size += len; | |
| 6500 total_size += 1; // NULL at the end of each char array. | |
| 6501 if (!total_size.IsValid()) { | |
| 6502 SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "overflow"); | |
| 6503 return; | |
| 6504 } | |
| 6505 header[ii + 1] = len; | |
| 6506 } | |
| 6507 """ | |
| 6508 file.Write(size_code_block % { | |
| 6509 'data': data_arg.name, | |
| 6510 'length': length_arg.name if not length_arg == None else '', | |
| 6511 'func_name': func.name, | |
| 6512 }) | |
| 6513 data_code_block = """ // Pack data into a bucket on the service. | |
| 6514 helper_->SetBucketSize(kResultBucketId, total_size.ValueOrDefault(0)); | |
| 6515 size_t offset = 0; | |
| 6516 for (GLsizei ii = 0; ii <= count; ++ii) { | |
| 6517 const char* src = (ii == 0) ? reinterpret_cast<const char*>(&header[0]) : | |
| 6518 %(data)s[ii - 1]; | |
| 6519 base::CheckedNumeric<size_t> checked_size = (ii == 0) ? header_size : | |
| 6520 static_cast<size_t>(header[ii]); | |
| 6521 if (ii > 0) { | |
| 6522 checked_size += 1; // NULL in the end. | |
| 6523 } | |
| 6524 if (!checked_size.IsValid()) { | |
| 6525 SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "overflow"); | |
| 6526 return; | |
| 6527 } | |
| 6528 size_t size = checked_size.ValueOrDefault(0); | |
| 6529 while (size) { | |
| 6530 ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_); | |
| 6531 if (!buffer.valid() || buffer.size() == 0) { | |
| 6532 SetGLError(GL_OUT_OF_MEMORY, "gl%(func_name)s", "too large"); | |
| 6533 return; | |
| 6534 } | |
| 6535 size_t copy_size = buffer.size(); | |
| 6536 if (ii > 0 && buffer.size() == size) | |
| 6537 --copy_size; | |
| 6538 if (copy_size) | |
| 6539 memcpy(buffer.address(), src, copy_size); | |
| 6540 if (copy_size < buffer.size()) { | |
| 6541 // Append NULL in the end. | |
| 6542 DCHECK(copy_size + 1 == buffer.size()); | |
| 6543 char* str = reinterpret_cast<char*>(buffer.address()); | |
| 6544 str[copy_size] = 0; | |
| 6545 } | |
| 6546 helper_->SetBucketData(kResultBucketId, offset, buffer.size(), | |
| 6547 buffer.shm_id(), buffer.offset()); | |
| 6548 offset += buffer.size(); | |
| 6549 src += buffer.size(); | |
| 6550 size -= buffer.size(); | |
| 6551 } | |
| 6552 } | |
| 6553 DCHECK_EQ(total_size.ValueOrDefault(0), offset); | |
| 6554 """ | |
| 6555 file.Write(data_code_block % { | |
| 6556 'data': data_arg.name, | |
| 6557 'length': length_arg.name if not length_arg == None else '', | |
| 6558 'func_name': func.name, | |
| 6559 }) | |
| 6560 bucket_args = [] | 6477 bucket_args = [] |
| 6561 for arg in func.GetOriginalArgs(): | 6478 for arg in func.GetOriginalArgs(): |
| 6562 if arg.name == 'count' or arg == self.__GetLengthArg(func): | 6479 if arg.name == 'count' or arg == self.__GetLengthArg(func): |
| 6563 continue | 6480 continue |
| 6564 if arg == self.__GetDataArg(func): | 6481 if arg == self.__GetDataArg(func): |
| 6565 bucket_args.append('kResultBucketId') | 6482 bucket_args.append('kResultBucketId') |
| 6566 else: | 6483 else: |
| 6567 bucket_args.append(arg.name) | 6484 bucket_args.append(arg.name) |
| 6568 file.Write(" helper_->%sBucket(%s);\n" % | 6485 code_block = """ |
| 6569 (func.name, ", ".join(bucket_args))) | 6486 if (!PackStringsToBucket(count, %(data)s, %(length)s, "gl%(func_name)s")) { |
| 6570 file.Write(" helper_->SetBucketSize(kResultBucketId, 0);"); | 6487 return; |
| 6571 file.Write(" CheckGLError();\n") | 6488 } |
| 6572 file.Write("}\n") | 6489 helper_->%(func_name)sBucket(%(bucket_args)s); |
| 6573 file.Write("\n") | 6490 helper_->SetBucketSize(kResultBucketId, 0); |
| 6491 CheckGLError(); | |
| 6492 } | |
| 6493 | |
| 6494 """ | |
| 6495 file.Write(code_block % { | |
| 6496 'data': data_arg.name, | |
| 6497 'length': length_arg.name if not length_arg == None else 'NULL', | |
| 6498 'func_name': func.name, | |
| 6499 'bucket_args': ', '.join(bucket_args), | |
| 6500 }) | |
| 6574 | 6501 |
| 6575 def WriteGLES2ImplementationUnitTest(self, func, file): | 6502 def WriteGLES2ImplementationUnitTest(self, func, file): |
| 6576 """Overrriden from TypeHandler.""" | 6503 """Overrriden from TypeHandler.""" |
| 6577 code = """ | 6504 code = """ |
| 6578 TEST_F(GLES2ImplementationTest, %(name)s) { | 6505 TEST_F(GLES2ImplementationTest, %(name)s) { |
| 6579 const uint32 kBucketId = GLES2Implementation::kResultBucketId; | 6506 const uint32 kBucketId = GLES2Implementation::kResultBucketId; |
| 6580 const char* kString1 = "happy"; | 6507 const char* kString1 = "happy"; |
| 6581 const char* kString2 = "ending"; | 6508 const char* kString2 = "ending"; |
| 6582 const size_t kString1Size = ::strlen(kString1) + 1; | 6509 const size_t kString1Size = ::strlen(kString1) + 1; |
| 6583 const size_t kString2Size = ::strlen(kString2) + 1; | 6510 const size_t kString2Size = ::strlen(kString2) + 1; |
| (...skipping 1411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7995 class InputStringArrayBucketArgument(Argument): | 7922 class InputStringArrayBucketArgument(Argument): |
| 7996 """A string array input argument where the strings are passed in a bucket.""" | 7923 """A string array input argument where the strings are passed in a bucket.""" |
| 7997 | 7924 |
| 7998 def __init__(self, name, type): | 7925 def __init__(self, name, type): |
| 7999 Argument.__init__(self, name + "_bucket_id", "uint32_t") | 7926 Argument.__init__(self, name + "_bucket_id", "uint32_t") |
| 8000 self._original_name = name | 7927 self._original_name = name |
| 8001 | 7928 |
| 8002 def WriteGetCode(self, file): | 7929 def WriteGetCode(self, file): |
| 8003 """Overridden from Argument.""" | 7930 """Overridden from Argument.""" |
| 8004 code = """ | 7931 code = """ |
| 8005 const size_t kMinBucketSize = sizeof(GLint); | |
| 8006 // Each string has at least |length| in the header and a NUL character. | |
| 8007 const size_t kMinStringSize = sizeof(GLint) + 1; | |
| 8008 Bucket* bucket = GetBucket(c.%(name)s); | 7932 Bucket* bucket = GetBucket(c.%(name)s); |
| 8009 if (!bucket) { | 7933 if (!bucket) { |
| 8010 return error::kInvalidArguments; | 7934 return error::kInvalidArguments; |
| 8011 } | 7935 } |
| 8012 const size_t bucket_size = bucket->size(); | 7936 GLsizei count = 0; |
| 8013 if (bucket_size < kMinBucketSize) { | 7937 std::vector<char*> strs; |
| 7938 std::vector<GLint> len; | |
| 7939 if (!bucket->GetAsStrings(&count, &strs, &len)) { | |
| 8014 return error::kInvalidArguments; | 7940 return error::kInvalidArguments; |
| 8015 } | 7941 } |
| 8016 const char* bucket_data = bucket->GetDataAs<const char*>(0, bucket_size); | 7942 const char** %(original_name)s = |
| 8017 const GLint* header = reinterpret_cast<const GLint*>(bucket_data); | 7943 strs.size() > 0 ? const_cast<const char**>(&strs[0]) : NULL; |
|
no sievers
2015/02/06 21:01:38
Can we somehow assert that these are only NULL if
Zhenyao Mo
2015/02/06 21:53:50
This is the same as asserting strs.size() == len.s
| |
| 8018 GLsizei count = static_cast<GLsizei>(header[0]); | 7944 const GLint* length = |
| 8019 if (count < 0) { | 7945 len.size() > 0 ? const_cast<const GLint*>(&len[0]) : NULL; |
| 8020 return error::kInvalidArguments; | 7946 (void)length; |
| 8021 } | |
| 8022 const size_t max_count = (bucket_size - kMinBucketSize) / kMinStringSize; | |
| 8023 if (max_count < static_cast<size_t>(count)) { | |
| 8024 return error::kInvalidArguments; | |
| 8025 } | |
| 8026 const GLint* length = header + 1; | |
| 8027 scoped_ptr<const char*[]> strs; | |
| 8028 if (count > 0) | |
| 8029 strs.reset(new const char*[count]); | |
| 8030 const char** %(original_name)s = strs.get(); | |
| 8031 base::CheckedNumeric<size_t> total_size = sizeof(GLint); | |
| 8032 total_size *= count + 1; // Header size. | |
| 8033 if (!total_size.IsValid()) | |
| 8034 return error::kInvalidArguments; | |
| 8035 for (GLsizei ii = 0; ii < count; ++ii) { | |
| 8036 %(original_name)s[ii] = bucket_data + total_size.ValueOrDefault(0); | |
| 8037 total_size += length[ii]; | |
| 8038 total_size += 1; // NUL char at the end of each char array. | |
| 8039 if (!total_size.IsValid() || total_size.ValueOrDefault(0) > bucket_size || | |
| 8040 %(original_name)s[ii][length[ii]] != 0) { | |
| 8041 return error::kInvalidArguments; | |
| 8042 } | |
| 8043 } | |
| 8044 if (total_size.ValueOrDefault(0) != bucket_size) { | |
| 8045 return error::kInvalidArguments; | |
| 8046 } | |
| 8047 """ | 7947 """ |
| 8048 file.Write(code % { | 7948 file.Write(code % { |
| 8049 'name': self.name, | 7949 'name': self.name, |
| 8050 'original_name': self._original_name, | 7950 'original_name': self._original_name, |
| 8051 }) | 7951 }) |
| 8052 | 7952 |
| 8053 def GetValidArg(self, func): | 7953 def GetValidArg(self, func): |
| 8054 return "kNameBucketId" | 7954 return "kNameBucketId" |
| 8055 | 7955 |
| 8056 def GetValidGLArg(self, func): | 7956 def GetValidGLArg(self, func): |
| (...skipping 2074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10131 Format(gen.generated_cpp_filenames) | 10031 Format(gen.generated_cpp_filenames) |
| 10132 | 10032 |
| 10133 if gen.errors > 0: | 10033 if gen.errors > 0: |
| 10134 print "%d errors" % gen.errors | 10034 print "%d errors" % gen.errors |
| 10135 return 1 | 10035 return 1 |
| 10136 return 0 | 10036 return 0 |
| 10137 | 10037 |
| 10138 | 10038 |
| 10139 if __name__ == '__main__': | 10039 if __name__ == '__main__': |
| 10140 sys.exit(main(sys.argv[1:])) | 10040 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |