Index: gpu/command_buffer/service/gles2_cmd_decoder.cc |
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
index f37c61a4808d9832879583c2321d05c2fdac9602..9b8e63521ebd82282316474833e1feed8031452a 100644 |
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
@@ -1163,16 +1163,16 @@ class GLES2DecoderImpl : public GLES2Decoder, |
GLuint client_id, GLint location, const char* name); |
error::Error GetAttribLocationHelper( |
- GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
- const std::string& name_str); |
+ GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
+ const std::string& name_str); |
error::Error GetUniformLocationHelper( |
- GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
- const std::string& name_str); |
+ GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
+ const std::string& name_str); |
error::Error GetFragDataLocationHelper( |
- GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
- const std::string& name_str); |
+ GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
+ const std::string& name_str); |
// Wrapper for glShaderSource. |
void DoShaderSource( |
@@ -2842,6 +2842,14 @@ Capabilities GLES2DecoderImpl::GetCapabilities() { |
DoGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &caps.num_shader_binary_formats); |
DoGetIntegerv(GL_BIND_GENERATES_RESOURCE_CHROMIUM, |
&caps.bind_generates_resource_chromium); |
+ if (unsafe_es3_apis_enabled()) { |
+ DoGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, |
+ &caps.max_transform_feedback_separate_attribs); |
+ DoGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, |
+ &caps.max_uniform_buffer_bindings); |
+ DoGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, |
+ &caps.uniform_buffer_offset_alignment); |
+ } |
caps.egl_image_external = |
feature_info_->feature_flags().oes_egl_image_external; |
@@ -7051,14 +7059,17 @@ void GLES2DecoderImpl::DoShaderSource( |
GLuint client_id, GLsizei count, const char** data, const GLint* length) { |
std::string str; |
for (GLsizei ii = 0; ii < count; ++ii) { |
- str.append(data[ii]); |
+ if (length && length[ii] > 0) |
+ str.append(data[ii], length[ii]); |
+ else |
+ str.append(data[ii]); |
} |
Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource"); |
if (!shader) { |
return; |
} |
// Note: We don't actually call glShaderSource here. We wait until |
- // the call to glCompileShader. |
+ // we actually compile the shader. |
shader->set_source(str); |
} |
@@ -7086,6 +7097,10 @@ void GLES2DecoderImpl::DoCompileShader(GLuint client_id) { |
vertex_translator_.get() : fragment_translator_.get(); |
} |
+ shader->RequestCompile(); |
+ |
+ // TODO(dyen): Currently we compile immediately when glCompileShader is |
+ // requested. Eventually this should be deffered to the linker stage. |
shader->DoCompile( |
translator, |
feature_info_->feature_flags().angle_translated_shader_source ? |
@@ -8186,6 +8201,39 @@ error::Error GLES2DecoderImpl::HandleGetFragDataLocation( |
c.program, c.location_shm_id, c.location_shm_offset, name_str); |
} |
+error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex( |
+ uint32 immediate_data_size, const void* cmd_data) { |
+ if (!unsafe_es3_apis_enabled()) |
+ return error::kUnknownCommand; |
+ const gles2::cmds::GetUniformBlockIndex& c = |
+ *static_cast<const gles2::cmds::GetUniformBlockIndex*>(cmd_data); |
+ Bucket* bucket = GetBucket(c.name_bucket_id); |
+ if (!bucket) { |
+ return error::kInvalidArguments; |
+ } |
+ std::string name_str; |
+ if (!bucket->GetAsString(&name_str)) { |
+ return error::kInvalidArguments; |
+ } |
+ GLuint* index = GetSharedMemoryAs<GLuint*>( |
+ c.index_shm_id, c.index_shm_offset, sizeof(GLuint)); |
+ if (!index) { |
+ return error::kOutOfBounds; |
+ } |
+ // Require the client to init this in case the context is lost and we are no |
+ // longer executing commands. |
+ if (*index != GL_INVALID_INDEX) { |
+ return error::kGenericError; |
+ } |
+ Program* program = GetProgramInfoNotShader( |
+ c.program, "glGetUniformBlockIndex"); |
+ if (!program) { |
+ return error::kNoError; |
+ } |
+ *index = glGetUniformBlockIndex(program->service_id(), name_str.c_str()); |
+ return error::kNoError; |
+} |
+ |
error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size, |
const void* cmd_data) { |
const gles2::cmds::GetString& c = |
@@ -9682,6 +9730,59 @@ error::Error GLES2DecoderImpl::HandleGetActiveUniform( |
return error::kNoError; |
} |
+error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName( |
+ uint32 immediate_data_size, const void* cmd_data) { |
+ if (!unsafe_es3_apis_enabled()) |
+ return error::kUnknownCommand; |
+ const gles2::cmds::GetActiveUniformBlockName& c = |
+ *static_cast<const gles2::cmds::GetActiveUniformBlockName*>(cmd_data); |
+ GLuint program_id = c.program; |
+ GLuint index = c.index; |
+ uint32 name_bucket_id = c.name_bucket_id; |
+ typedef cmds::GetActiveUniformBlockName::Result Result; |
+ Result* result = GetSharedMemoryAs<Result*>( |
+ c.result_shm_id, c.result_shm_offset, sizeof(*result)); |
+ if (!result) { |
+ return error::kOutOfBounds; |
+ } |
+ // Check that the client initialized the result. |
+ if (*result != 0) { |
+ return error::kInvalidArguments; |
+ } |
+ Program* program = GetProgramInfoNotShader( |
+ program_id, "glGetActiveUniformBlockName"); |
+ if (!program) { |
+ return error::kNoError; |
+ } |
+ GLuint service_id = program->service_id(); |
+ GLint link_status = GL_FALSE; |
+ glGetProgramiv(service_id, GL_LINK_STATUS, &link_status); |
+ if (link_status != GL_TRUE) { |
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, |
+ "glGetActiveActiveUniformBlockName", "program not linked"); |
+ return error::kNoError; |
+ } |
+ GLint max_length = 0; |
+ glGetProgramiv( |
+ service_id, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_length); |
+ // Increase one so &buffer[0] is always valid. |
+ GLsizei buf_size = static_cast<GLsizei>(max_length) + 1; |
+ std::vector<char> buffer(buf_size); |
+ GLsizei length = 0; |
+ glGetActiveUniformBlockName( |
+ service_id, index, buf_size, &length, &buffer[0]); |
+ if (length == 0) { |
+ *result = 0; |
+ return error::kNoError; |
+ } |
+ *result = 1; |
+ Bucket* bucket = CreateBucket(name_bucket_id); |
+ DCHECK_GT(buf_size, length); |
+ DCHECK_EQ(0, buffer[length]); |
+ bucket->SetFromString(&buffer[0]); |
+ return error::kNoError; |
+} |
+ |
error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size, |
const void* cmd_data) { |
const gles2::cmds::GetActiveAttrib& c = |
@@ -10016,6 +10117,25 @@ error::Error GLES2DecoderImpl::HandleGetProgramInfoCHROMIUM( |
return error::kNoError; |
} |
+error::Error GLES2DecoderImpl::HandleGetUniformBlocksCHROMIUM( |
+ uint32 immediate_data_size, const void* cmd_data) { |
+ if (!unsafe_es3_apis_enabled()) |
+ return error::kUnknownCommand; |
+ const gles2::cmds::GetUniformBlocksCHROMIUM& c = |
+ *static_cast<const gles2::cmds::GetUniformBlocksCHROMIUM*>(cmd_data); |
+ GLuint program_id = static_cast<GLuint>(c.program); |
+ uint32 bucket_id = c.bucket_id; |
+ Bucket* bucket = CreateBucket(bucket_id); |
+ bucket->SetSize(sizeof(UniformBlocksHeader)); // in case we fail. |
+ Program* program = NULL; |
+ program = GetProgram(program_id); |
+ if (!program || !program->IsValid()) { |
+ return error::kNoError; |
+ } |
+ program->GetUniformBlocks(bucket); |
+ return error::kNoError; |
+} |
+ |
error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() { |
switch (reset_status_) { |
case GL_NO_ERROR: |