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 30f92692f9527fc0ea2d7e9c9cb66208d3654040..e8537669a790e4239f6973d07343d51e226dc593 100644 |
--- a/gpu/command_buffer/client/gles2_implementation.cc |
+++ b/gpu/command_buffer/client/gles2_implementation.cc |
@@ -1066,6 +1066,52 @@ GLint GLES2Implementation::GetUniformLocation( |
return loc; |
} |
+bool GLES2Implementation::GetUniformIndicesHelper( |
+ GLuint program, GLsizei count, const char* const* names, GLuint* indices) { |
+ typedef cmds::GetUniformIndices::Result Result; |
+ Result* result = GetResultAs<Result*>(); |
+ if (!result) { |
+ return false; |
+ } |
+ result->SetNumResults(0); |
+ if (!PackStringsToBucket(count, names, NULL, "glGetUniformIndices")) { |
+ return false; |
+ } |
+ helper_->GetUniformIndices(program, kResultBucketId, |
+ GetResultShmId(), GetResultShmOffset()); |
+ WaitForCmd(); |
+ if (result->GetNumResults() != count) { |
+ return false; |
+ } |
+ result->CopyResult(indices); |
+ return true; |
+} |
+ |
+void GLES2Implementation::GetUniformIndices( |
+ GLuint program, GLsizei count, const char* const* names, GLuint* indices) { |
+ GPU_CLIENT_SINGLE_THREAD_CHECK(); |
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program |
+ << ", " << count << ", " << names << ", " << indices << ")"); |
+ TRACE_EVENT0("gpu", "GLES2::GetUniformIndices"); |
+ if (count < 0) { |
+ SetGLError(GL_INVALID_VALUE, "glGetUniformIndices", "count < 0"); |
+ return; |
+ } |
+ if (count == 0) { |
+ return; |
+ } |
+ bool success = share_group_->program_info_manager()->GetUniformIndices( |
+ this, program, count, names, indices); |
+ if (success) { |
+ GPU_CLIENT_LOG_CODE_BLOCK({ |
+ for (GLsizei ii = 0; ii < count; ++ii) { |
+ GPU_CLIENT_LOG(" " << ii << ": " << indices[ii]); |
+ } |
+ }); |
+ } |
+ CheckGLError(); |
+} |
+ |
bool GLES2Implementation::GetProgramivHelper( |
GLuint program, GLenum pname, GLint* params) { |
bool got_value = share_group_->program_info_manager()->GetProgramiv( |
@@ -2363,7 +2409,7 @@ void GLES2Implementation::GetActiveUniformBlockName( |
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName(" |
<< program << ", " << index << ", " << bufsize << ", " |
<< static_cast<const void*>(length) << ", " |
- << static_cast<const void*>(name) << ", "); |
+ << static_cast<const void*>(name) << ")"); |
if (bufsize < 0) { |
SetGLError(GL_INVALID_VALUE, "glGetActiveUniformBlockName", "bufsize < 0"); |
return; |
@@ -2380,6 +2426,114 @@ void GLES2Implementation::GetActiveUniformBlockName( |
CheckGLError(); |
} |
+bool GLES2Implementation::GetActiveUniformBlockivHelper( |
+ GLuint program, GLuint index, GLenum pname, GLint* params) { |
+ typedef cmds::GetActiveUniformBlockiv::Result Result; |
+ Result* result = GetResultAs<Result*>(); |
+ if (!result) { |
+ return false; |
+ } |
+ result->SetNumResults(0); |
+ helper_->GetActiveUniformBlockiv( |
+ program, index, pname, GetResultShmId(), GetResultShmOffset()); |
+ WaitForCmd(); |
+ if (result->GetNumResults() > 0) { |
+ if (params) { |
+ result->CopyResult(params); |
+ } |
+ GPU_CLIENT_LOG_CODE_BLOCK({ |
+ for (int32_t i = 0; i < result->GetNumResults(); ++i) { |
+ GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); |
+ } |
+ }); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+void GLES2Implementation::GetActiveUniformBlockiv( |
+ GLuint program, GLuint index, GLenum pname, GLint* params) { |
+ GPU_CLIENT_SINGLE_THREAD_CHECK(); |
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv(" |
+ << program << ", " << index << ", " |
+ << GLES2Util::GetStringUniformBlockParameter(pname) << ", " |
+ << static_cast<const void*>(params) << ")"); |
+ TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv"); |
+ bool success = |
+ share_group_->program_info_manager()->GetActiveUniformBlockiv( |
+ this, program, index, pname, params); |
+ if (success) { |
+ if (params) { |
+ // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will |
+ // be more than one value returned in params. |
+ GPU_CLIENT_LOG(" params: " << params[0]); |
+ } |
+ } |
+ CheckGLError(); |
+} |
+ |
+bool GLES2Implementation::GetActiveUniformsivHelper( |
+ GLuint program, GLsizei count, const GLuint* indices, |
+ GLenum pname, GLint* params) { |
+ typedef cmds::GetActiveUniformsiv::Result Result; |
+ Result* result = GetResultAs<Result*>(); |
+ if (!result) { |
+ return false; |
+ } |
+ result->SetNumResults(0); |
+ base::CheckedNumeric<size_t> bytes = static_cast<size_t>(count); |
+ bytes *= sizeof(GLuint); |
+ if (!bytes.IsValid()) { |
+ SetGLError(GL_INVALID_VALUE, "glGetActiveUniformsiv", "count overflow"); |
+ return false; |
+ } |
+ SetBucketContents(kResultBucketId, indices, bytes.ValueOrDefault(0)); |
+ helper_->GetActiveUniformsiv( |
+ program, kResultBucketId, pname, GetResultShmId(), GetResultShmOffset()); |
+ WaitForCmd(); |
+ bool success = result->GetNumResults() == count; |
+ if (success) { |
+ if (params) { |
+ result->CopyResult(params); |
+ } |
+ GPU_CLIENT_LOG_CODE_BLOCK({ |
+ for (int32_t i = 0; i < result->GetNumResults(); ++i) { |
+ GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); |
+ } |
+ }); |
+ } |
+ helper_->SetBucketSize(kResultBucketId, 0); |
+ return success; |
+} |
+ |
+void GLES2Implementation::GetActiveUniformsiv( |
+ GLuint program, GLsizei count, const GLuint* indices, |
+ GLenum pname, GLint* params) { |
+ GPU_CLIENT_SINGLE_THREAD_CHECK(); |
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv(" |
+ << program << ", " << count << ", " |
+ << static_cast<const void*>(indices) << ", " |
+ << GLES2Util::GetStringUniformParameter(pname) << ", " |
+ << static_cast<const void*>(params) << ")"); |
+ TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv"); |
+ if (count < 0) { |
+ SetGLError(GL_INVALID_VALUE, "glGetActiveUniformsiv", "count < 0"); |
+ return; |
+ } |
+ bool success = share_group_->program_info_manager()->GetActiveUniformsiv( |
+ this, program, count, indices, pname, params); |
+ if (success) { |
+ if (params) { |
+ GPU_CLIENT_LOG_CODE_BLOCK({ |
+ for (GLsizei ii = 0; ii < count; ++ii) { |
+ GPU_CLIENT_LOG(" " << ii << ": " << params[ii]); |
+ } |
+ }); |
+ } |
+ } |
+ CheckGLError(); |
+} |
+ |
void GLES2Implementation::GetAttachedShaders( |
GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { |
GPU_CLIENT_SINGLE_THREAD_CHECK(); |
@@ -2522,6 +2676,84 @@ const GLubyte* GLES2Implementation::GetString(GLenum name) { |
return result; |
} |
+bool GLES2Implementation::GetTransformFeedbackVaryingHelper( |
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, |
+ GLenum* type, char* name) { |
+ // Clear the bucket so if the command fails nothing will be in it. |
+ helper_->SetBucketSize(kResultBucketId, 0); |
+ typedef cmds::GetTransformFeedbackVarying::Result Result; |
+ Result* result = GetResultAs<Result*>(); |
+ if (!result) { |
+ return false; |
+ } |
+ // Set as failed so if the command fails we'll recover. |
+ result->success = false; |
+ helper_->GetTransformFeedbackVarying( |
+ program, index, kResultBucketId, GetResultShmId(), GetResultShmOffset()); |
+ WaitForCmd(); |
+ if (result->success) { |
+ if (size) { |
+ *size = result->size; |
+ } |
+ if (type) { |
+ *type = result->type; |
+ } |
+ if (length || name) { |
+ std::vector<int8> str; |
+ GetBucketContents(kResultBucketId, &str); |
+ GLsizei max_size = std::min(bufsize, static_cast<GLsizei>(str.size())); |
+ if (max_size > 0) { |
+ --max_size; |
+ } |
+ if (length) { |
+ *length = max_size; |
+ } |
+ if (name) { |
+ if (max_size > 0) { |
+ memcpy(name, &str[0], max_size); |
+ name[max_size] = '\0'; |
+ } else if (bufsize > 0) { |
+ name[0] = '\0'; |
+ } |
+ } |
+ } |
+ } |
+ return result->success != 0; |
+} |
+ |
+void GLES2Implementation::GetTransformFeedbackVarying( |
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, |
+ GLenum* type, char* name) { |
+ GPU_CLIENT_SINGLE_THREAD_CHECK(); |
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying(" |
+ << program << ", " << index << ", " << bufsize << ", " |
+ << static_cast<const void*>(length) << ", " |
+ << static_cast<const void*>(size) << ", " |
+ << static_cast<const void*>(type) << ", " |
+ << static_cast<const void*>(name) << ", "); |
+ if (bufsize < 0) { |
+ SetGLError(GL_INVALID_VALUE, "glGetTransformFeedbackVarying", |
+ "bufsize < 0"); |
+ return; |
+ } |
+ TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying"); |
+ bool success = |
+ share_group_->program_info_manager()->GetTransformFeedbackVarying( |
+ this, program, index, bufsize, length, size, type, name); |
+ if (success) { |
+ if (size) { |
+ GPU_CLIENT_LOG(" size: " << *size); |
+ } |
+ if (type) { |
+ GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type)); |
+ } |
+ if (name) { |
+ GPU_CLIENT_LOG(" name: " << name); |
+ } |
+ } |
+ CheckGLError(); |
+} |
+ |
void GLES2Implementation::GetUniformfv( |
GLuint program, GLint location, GLfloat* params) { |
GPU_CLIENT_SINGLE_THREAD_CHECK(); |
@@ -3628,11 +3860,11 @@ void GLES2Implementation::GetUniformBlocksCHROMIUM( |
GPU_CLIENT_SINGLE_THREAD_CHECK(); |
if (bufsize < 0) { |
SetGLError( |
- GL_INVALID_VALUE, "glUniformBlocksCHROMIUM", "bufsize less than 0."); |
+ GL_INVALID_VALUE, "glGetUniformBlocksCHROMIUM", "bufsize less than 0."); |
return; |
} |
if (size == NULL) { |
- SetGLError(GL_INVALID_VALUE, "glUniformBlocksCHROMIUM", "size is null."); |
+ SetGLError(GL_INVALID_VALUE, "glGetUniformBlocksCHROMIUM", "size is null."); |
return; |
} |
// Make sure they've set size to 0 else the value will be undefined on |
@@ -3648,8 +3880,91 @@ void GLES2Implementation::GetUniformBlocksCHROMIUM( |
return; |
} |
if (static_cast<size_t>(bufsize) < result.size()) { |
+ SetGLError(GL_INVALID_OPERATION, "glGetUniformBlocksCHROMIUM", |
+ "bufsize is too small for result."); |
+ return; |
+ } |
+ memcpy(info, &result[0], result.size()); |
+} |
+ |
+void GLES2Implementation::GetUniformsES3CHROMIUMHelper( |
+ GLuint program, std::vector<int8>* result) { |
+ DCHECK(result); |
+ // Clear the bucket so if the command fails nothing will be in it. |
+ helper_->SetBucketSize(kResultBucketId, 0); |
+ helper_->GetUniformsES3CHROMIUM(program, kResultBucketId); |
+ GetBucketContents(kResultBucketId, result); |
+} |
+ |
+void GLES2Implementation::GetUniformsES3CHROMIUM( |
+ GLuint program, GLsizei bufsize, GLsizei* size, void* info) { |
+ GPU_CLIENT_SINGLE_THREAD_CHECK(); |
+ if (bufsize < 0) { |
+ SetGLError( |
+ GL_INVALID_VALUE, "glGetUniformsES3CHROMIUM", "bufsize less than 0."); |
+ return; |
+ } |
+ if (size == NULL) { |
+ SetGLError(GL_INVALID_VALUE, "glGetUniformsES3CHROMIUM", "size is null."); |
+ return; |
+ } |
+ // Make sure they've set size to 0 else the value will be undefined on |
+ // lost context. |
+ DCHECK_EQ(0, *size); |
+ std::vector<int8> result; |
+ GetUniformsES3CHROMIUMHelper(program, &result); |
+ if (result.empty()) { |
+ return; |
+ } |
+ *size = result.size(); |
+ if (!info) { |
+ return; |
+ } |
+ if (static_cast<size_t>(bufsize) < result.size()) { |
SetGLError(GL_INVALID_OPERATION, |
- "glUniformBlocksCHROMIUM", "bufsize is too small for result."); |
+ "glGetUniformsES3CHROMIUM", "bufsize is too small for result."); |
+ return; |
+ } |
+ memcpy(info, &result[0], result.size()); |
+} |
+ |
+void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper( |
+ GLuint program, std::vector<int8>* result) { |
+ DCHECK(result); |
+ // Clear the bucket so if the command fails nothing will be in it. |
+ helper_->SetBucketSize(kResultBucketId, 0); |
+ helper_->GetTransformFeedbackVaryingsCHROMIUM(program, kResultBucketId); |
+ GetBucketContents(kResultBucketId, result); |
+} |
+ |
+void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM( |
+ GLuint program, GLsizei bufsize, GLsizei* size, void* info) { |
+ GPU_CLIENT_SINGLE_THREAD_CHECK(); |
+ if (bufsize < 0) { |
+ SetGLError(GL_INVALID_VALUE, "glGetTransformFeedbackVaryingsCHROMIUM", |
+ "bufsize less than 0."); |
+ return; |
+ } |
+ if (size == NULL) { |
+ SetGLError(GL_INVALID_VALUE, "glGetTransformFeedbackVaryingsCHROMIUM", |
+ "size is null."); |
+ return; |
+ } |
+ // Make sure they've set size to 0 else the value will be undefined on |
+ // lost context. |
+ DCHECK_EQ(0, *size); |
+ std::vector<int8> result; |
+ GetTransformFeedbackVaryingsCHROMIUMHelper(program, &result); |
+ if (result.empty()) { |
+ return; |
+ } |
+ *size = result.size(); |
+ if (!info) { |
+ return; |
+ } |
+ if (static_cast<size_t>(bufsize) < result.size()) { |
+ SetGLError(GL_INVALID_OPERATION, "glGetTransformFeedbackVaryingsCHROMIUM", |
+ "bufsize is too small for result."); |
return; |
} |
memcpy(info, &result[0], result.size()); |
@@ -4528,6 +4843,94 @@ 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; |
+} |
+ |
+void GLES2Implementation::UniformBlockBinding(GLuint program, |
+ GLuint index, |
+ GLuint binding) { |
+ GPU_CLIENT_SINGLE_THREAD_CHECK(); |
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program |
+ << ", " << index << ", " << binding << ")"); |
+ share_group_->program_info_manager()->UniformBlockBinding( |
+ this, program, index, binding); |
+ helper_->UniformBlockBinding(program, index, binding); |
+ CheckGLError(); |
+} |
+ |
+ |
// 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. |