| Index: gpu/command_buffer/client/gles2_implementation.cc
|
| diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
|
| index f0469a5cc5036d30307eecc86559df7b85e30687..7713d8fc2c3558b2661576b8bd13e1cb34ad93b1 100644
|
| --- a/gpu/command_buffer/client/gles2_implementation.cc
|
| +++ b/gpu/command_buffer/client/gles2_implementation.cc
|
| @@ -4521,6 +4521,81 @@ bool GLES2Implementation::GetSamplerParameterivHelper(
|
| return false;
|
| }
|
|
|
| +bool GLES2Implementation::PackStringsToBucket(GLsizei count,
|
| + const char* const* str,
|
| + const GLint* length,
|
| + const char* func_name) {
|
| + DCHECK_LE(0, count);
|
| + // 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, func_name, "overflow");
|
| + return false;
|
| + }
|
| + 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 (str[ii]) {
|
| + len = (length && length[ii] >= 0)
|
| + ? length[ii]
|
| + : base::checked_cast<GLint>(strlen(str[ii]));
|
| + }
|
| + total_size += len;
|
| + total_size += 1; // NULL at the end of each char array.
|
| + if (!total_size.IsValid()) {
|
| + SetGLError(GL_INVALID_VALUE, func_name, "overflow");
|
| + return false;
|
| + }
|
| + header[ii + 1] = len;
|
| + }
|
| + // 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]) : str[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, func_name, "overflow");
|
| + return false;
|
| + }
|
| + 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, func_name, "too large");
|
| + return false;
|
| + }
|
| + 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);
|
| + return true;
|
| +}
|
| +
|
| // Include the auto-generated part of this file. We split this because it means
|
| // we can easily edit the non-auto generated parts right here in this file
|
| // instead of having to edit some template or the code generator.
|
|
|