Chromium Code Reviews| 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 7fe1db9fd18f38b4523de103e26375b2ee6fefdb..ae577b53a849baa4f37e9400024ee737f873af1b 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -325,13 +325,10 @@ static bool CharacterIsValidForGLES(unsigned char c) { |
| return false; |
| } |
| -static bool StringIsValidForGLES(const char* str) { |
| - for (; *str; ++str) { |
| - if (!CharacterIsValidForGLES(*str)) { |
| - return false; |
| - } |
| - } |
| - return true; |
| +static bool StringIsValidForGLES(const std::string& str) { |
| + return str.length() == 0 || |
| + std::find_if_not(str.begin(), str.end(), CharacterIsValidForGLES) == |
| + str.end(); |
| } |
| // This class prevents any GL errors that occur when it is in scope from |
| @@ -1272,9 +1269,22 @@ class GLES2DecoderImpl : public GLES2Decoder, |
| client_id, service_id, group_->max_vertex_attribs(), client_visible); |
| } |
| - void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name); |
| - void DoBindUniformLocationCHROMIUM( |
| - GLuint client_id, GLint location, const char* name); |
| + void DoBindAttribLocation(GLuint client_id, |
| + GLuint index, |
| + const std::string& name); |
| + |
| + error::Error DoBindFragDataLocation(GLuint program_id, |
| + GLuint colorName, |
| + const std::string& name); |
| + |
| + error::Error DoBindFragDataLocationIndexed(GLuint program_id, |
| + GLuint colorName, |
| + GLuint index, |
| + const std::string& name); |
| + |
| + void DoBindUniformLocationCHROMIUM(GLuint client_id, |
| + GLint location, |
| + const std::string& name); |
| error::Error GetAttribLocationHelper( |
| GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
| @@ -1288,6 +1298,11 @@ class GLES2DecoderImpl : public GLES2Decoder, |
| GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
| const std::string& name_str); |
| + error::Error GetFragDataIndexHelper(GLuint program_id, |
| + uint32 index_shm_id, |
| + uint32 index_shm_offset, |
| + const std::string& name_str); |
| + |
| // Wrapper for glShaderSource. |
| void DoShaderSource( |
| GLuint client_id, GLsizei count, const char** data, const GLint* length); |
| @@ -1948,7 +1963,7 @@ class GLES2DecoderImpl : public GLES2Decoder, |
| void DoBindFragmentInputLocationCHROMIUM(GLuint program_id, |
| GLint location, |
| - const char* name); |
| + const std::string& name); |
| // Generate a member function prototype for each command in an automated and |
| // typesafe way. |
| @@ -3265,6 +3280,7 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { |
| resources.MaxDrawBuffers = group_->max_draw_buffers(); |
| resources.MaxExpressionComplexity = 256; |
| resources.MaxCallStackDepth = 256; |
| + resources.MaxDualSourceDrawBuffers = group_->max_dual_source_draw_buffers(); |
| GLint range[2] = { 0, 0 }; |
| GLint precision = 0; |
| @@ -3297,6 +3313,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { |
| features().ext_shader_texture_lod ? 1 : 0; |
| resources.NV_draw_buffers = |
| features().nv_draw_buffers ? 1 : 0; |
| + resources.EXT_blend_func_extended = |
| + features().ext_blend_func_extended ? 1 : 0; |
| } |
| ShShaderSpec shader_spec; |
| @@ -5518,6 +5536,12 @@ bool GLES2DecoderImpl::GetHelper( |
| params[0] = group_->bind_generates_resource() ? 1 : 0; |
| } |
| return true; |
| + case GL_MAX_DUAL_SOURCE_DRAW_BUFFERS: |
|
Zhenyao Mo
2015/09/30 00:23:47
Use _EXT instead.
Kimmo Kinnunen
2015/10/08 13:18:12
Done.
|
| + *num_written = 1; |
| + if (params) { |
| + params[0] = group_->max_dual_source_draw_buffers(); |
| + } |
| + return true; |
| default: |
| if (pname >= GL_DRAW_BUFFER0_ARB && |
| pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) { |
| @@ -5647,14 +5671,15 @@ void GLES2DecoderImpl::DoGetBufferParameteriv( |
| &state_, target, pname, params); |
| } |
| -void GLES2DecoderImpl::DoBindAttribLocation( |
| - GLuint program_id, GLuint index, const char* name) { |
| +void GLES2DecoderImpl::DoBindAttribLocation(GLuint program_id, |
| + GLuint index, |
| + const std::string& name) { |
| if (!StringIsValidForGLES(name)) { |
| LOCAL_SET_GL_ERROR( |
| GL_INVALID_VALUE, "glBindAttribLocation", "Invalid character"); |
| return; |
| } |
| - if (ProgramManager::IsInvalidPrefix(name, strlen(name))) { |
| + if (ProgramManager::HasBuiltInPrefix(name)) { |
| LOCAL_SET_GL_ERROR( |
| GL_INVALID_OPERATION, "glBindAttribLocation", "reserved prefix"); |
| return; |
| @@ -5676,7 +5701,7 @@ void GLES2DecoderImpl::DoBindAttribLocation( |
| // Program::ExecuteBindAttribLocationCalls() right before link. |
| program->SetAttribLocationBinding(name, static_cast<GLint>(index)); |
| // TODO(zmo): Get rid of the following glBindAttribLocation call. |
| - glBindAttribLocation(program->service_id(), index, name); |
| + glBindAttribLocation(program->service_id(), index, name.c_str()); |
| } |
| error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket( |
| @@ -5694,19 +5719,123 @@ error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket( |
| if (!bucket->GetAsString(&name_str)) { |
| return error::kInvalidArguments; |
| } |
| - DoBindAttribLocation(program, index, name_str.c_str()); |
| + DoBindAttribLocation(program, index, name_str); |
| + return error::kNoError; |
| +} |
| + |
| +error::Error GLES2DecoderImpl::DoBindFragDataLocation(GLuint program_id, |
| + GLuint colorName, |
| + const std::string& name) { |
| + const char kFunctionName[] = "glBindFragDataLocationEXT"; |
| + if (!StringIsValidForGLES(name)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "invalid character"); |
| + return error::kNoError; |
| + } |
| + if (ProgramManager::HasBuiltInPrefix(name)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "reserved prefix"); |
| + return error::kNoError; |
| + } |
| + if (colorName >= group_->max_draw_buffers()) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, |
| + "colorName out of range"); |
| + return error::kNoError; |
| + } |
| + Program* program = GetProgramInfoNotShader(program_id, kFunctionName); |
| + if (!program) { |
| + return error::kNoError; |
| + } |
| + if (!program->SetProgramOutputLocationBinding(name, colorName)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "invalid name"); |
| + return error::kNoError; |
| + } |
| + return error::kNoError; |
| +} |
| + |
| +error::Error GLES2DecoderImpl::HandleBindFragDataLocationEXTBucket( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + if (!features().ext_blend_func_extended) { |
| + return error::kUnknownCommand; |
| + } |
| + const gles2::cmds::BindFragDataLocationEXTBucket& c = |
| + *static_cast<const gles2::cmds::BindFragDataLocationEXTBucket*>(cmd_data); |
| + GLuint program = static_cast<GLuint>(c.program); |
| + GLuint colorNumber = static_cast<GLint>(c.colorNumber); |
|
Zhenyao Mo
2015/09/30 00:23:47
static_cast<GLuint>
Kimmo Kinnunen
2015/10/08 13:18:12
Done.
|
| + Bucket* bucket = GetBucket(c.name_bucket_id); |
| + if (!bucket || bucket->size() == 0) { |
| + return error::kInvalidArguments; |
| + } |
| + std::string name_str; |
| + if (!bucket->GetAsString(&name_str)) { |
| + return error::kInvalidArguments; |
| + } |
| + return DoBindFragDataLocation(program, colorNumber, name_str); |
| +} |
| + |
| +error::Error GLES2DecoderImpl::DoBindFragDataLocationIndexed( |
| + GLuint program_id, |
| + GLuint colorName, |
| + GLuint index, |
| + const std::string& name) { |
| + const char kFunctionName[] = "glBindFragDataLocationIndexEXT"; |
| + if (!StringIsValidForGLES(name)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "invalid character"); |
| + return error::kNoError; |
| + } |
| + if (ProgramManager::HasBuiltInPrefix(name)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "reserved prefix"); |
| + return error::kNoError; |
| + } |
| + if ((index == 0 && colorName >= group_->max_draw_buffers()) || |
|
Zhenyao Mo
2015/09/30 00:23:47
You should validate index == 0 || index == 1) firs
Kimmo Kinnunen
2015/10/08 13:18:12
Done.
|
| + (index == 1 && colorName >= group_->max_dual_source_draw_buffers())) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, |
| + "colorName out of range for the color index"); |
| + return error::kNoError; |
| + } |
| + Program* program = GetProgramInfoNotShader(program_id, kFunctionName); |
| + if (!program) { |
| + return error::kNoError; |
| + } |
| + if (!program->SetProgramOutputLocationBinding(name, colorName, index)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "invalid name"); |
| + return error::kNoError; |
| + } |
| return error::kNoError; |
| } |
| -void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM( |
| - GLuint program_id, GLint location, const char* name) { |
| +error::Error GLES2DecoderImpl::HandleBindFragDataLocationIndexedEXTBucket( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + if (!features().ext_blend_func_extended) { |
| + return error::kUnknownCommand; |
| + } |
| + const gles2::cmds::BindFragDataLocationIndexedEXTBucket& c = |
| + *static_cast<const gles2::cmds::BindFragDataLocationIndexedEXTBucket*>( |
| + cmd_data); |
| + GLuint program = static_cast<GLuint>(c.program); |
| + GLuint colorNumber = static_cast<GLint>(c.colorNumber); |
|
Zhenyao Mo
2015/09/30 00:23:47
GLuint
Kimmo Kinnunen
2015/10/08 13:18:12
Done.
|
| + GLuint index = static_cast<GLint>(c.index); |
|
Zhenyao Mo
2015/09/30 00:23:47
GLuint
Kimmo Kinnunen
2015/10/08 13:18:12
Done.
|
| + Bucket* bucket = GetBucket(c.name_bucket_id); |
| + if (!bucket || bucket->size() == 0) { |
| + return error::kInvalidArguments; |
| + } |
| + std::string name_str; |
| + if (!bucket->GetAsString(&name_str)) { |
| + return error::kInvalidArguments; |
| + } |
| + return DoBindFragDataLocationIndexed(program, colorNumber, index, name_str); |
| +} |
| + |
| +void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(GLuint program_id, |
| + GLint location, |
| + const std::string& name) { |
| if (!StringIsValidForGLES(name)) { |
| LOCAL_SET_GL_ERROR( |
| GL_INVALID_VALUE, |
| "glBindUniformLocationCHROMIUM", "Invalid character"); |
| return; |
| } |
| - if (ProgramManager::IsInvalidPrefix(name, strlen(name))) { |
| + if (ProgramManager::HasBuiltInPrefix(name)) { |
| LOCAL_SET_GL_ERROR( |
| GL_INVALID_OPERATION, |
| "glBindUniformLocationCHROMIUM", "reserved prefix"); |
| @@ -5748,7 +5877,7 @@ error::Error GLES2DecoderImpl::HandleBindUniformLocationCHROMIUMBucket( |
| if (!bucket->GetAsString(&name_str)) { |
| return error::kInvalidArguments; |
| } |
| - DoBindUniformLocationCHROMIUM(program, location, name_str.c_str()); |
| + DoBindUniformLocationCHROMIUM(program, location, name_str); |
| return error::kNoError; |
| } |
| @@ -9303,7 +9432,7 @@ error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM( |
| error::Error GLES2DecoderImpl::GetAttribLocationHelper( |
| GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
| const std::string& name_str) { |
| - if (!StringIsValidForGLES(name_str.c_str())) { |
| + if (!StringIsValidForGLES(name_str)) { |
| LOCAL_SET_GL_ERROR( |
| GL_INVALID_VALUE, "glGetAttribLocation", "Invalid character"); |
| return error::kNoError; |
| @@ -9352,7 +9481,7 @@ error::Error GLES2DecoderImpl::HandleGetAttribLocation( |
| error::Error GLES2DecoderImpl::GetUniformLocationHelper( |
| GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
| const std::string& name_str) { |
| - if (!StringIsValidForGLES(name_str.c_str())) { |
| + if (!StringIsValidForGLES(name_str)) { |
| LOCAL_SET_GL_ERROR( |
| GL_INVALID_VALUE, "glGetUniformLocation", "Invalid character"); |
| return error::kNoError; |
| @@ -9453,6 +9582,7 @@ error::Error GLES2DecoderImpl::HandleGetUniformIndices( |
| error::Error GLES2DecoderImpl::GetFragDataLocationHelper( |
| GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, |
| const std::string& name_str) { |
| + const char kFunctionName[] = "glGetFragDataLocation"; |
| GLint* location = GetSharedMemoryAs<GLint*>( |
| location_shm_id, location_shm_offset, sizeof(GLint)); |
| if (!location) { |
| @@ -9463,12 +9593,17 @@ error::Error GLES2DecoderImpl::GetFragDataLocationHelper( |
| if (*location != -1) { |
| return error::kGenericError; |
| } |
| - Program* program = GetProgramInfoNotShader( |
| - client_id, "glGetFragDataLocation"); |
| + Program* program = GetProgramInfoNotShader(client_id, kFunctionName); |
| if (!program) { |
| return error::kNoError; |
| } |
| - *location = glGetFragDataLocation(program->service_id(), name_str.c_str()); |
| + if (!program->IsValid()) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, |
| + "program not linked"); |
| + return error::kNoError; |
| + } |
| + |
| + *location = program->GetFragDataLocation(name_str); |
| return error::kNoError; |
| } |
| @@ -9491,6 +9626,56 @@ error::Error GLES2DecoderImpl::HandleGetFragDataLocation( |
| c.program, c.location_shm_id, c.location_shm_offset, name_str); |
| } |
| +error::Error GLES2DecoderImpl::GetFragDataIndexHelper( |
| + GLuint program_id, |
| + uint32 index_shm_id, |
| + uint32 index_shm_offset, |
| + const std::string& name_str) { |
| + const char kFunctionName[] = "glGetFragDataIndexEXT"; |
| + GLint* index = |
| + GetSharedMemoryAs<GLint*>(index_shm_id, index_shm_offset, sizeof(GLint)); |
| + if (!index) { |
| + return error::kOutOfBounds; |
| + } |
| + // Require the client to init this incase the context is lost and we are no |
| + // longer executing commands. |
| + if (*index != -1) { |
| + return error::kGenericError; |
|
Zhenyao Mo
2015/09/30 00:23:47
We return kInvalidArguments in such cases.
Kimmo Kinnunen
2015/10/08 13:18:12
Done.
|
| + } |
| + Program* program = GetProgramInfoNotShader(program_id, kFunctionName); |
| + if (!program) { |
| + return error::kNoError; |
| + } |
| + if (!program->IsValid()) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, |
| + "program not linked"); |
| + return error::kNoError; |
| + } |
| + |
| + *index = program->GetFragDataIndex(name_str); |
| + return error::kNoError; |
| +} |
| + |
| +error::Error GLES2DecoderImpl::HandleGetFragDataIndexEXT( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + if (!features().ext_blend_func_extended) { |
| + return error::kUnknownCommand; |
| + } |
| + const gles2::cmds::GetFragDataIndexEXT& c = |
| + *static_cast<const gles2::cmds::GetFragDataIndexEXT*>(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; |
| + } |
| + return GetFragDataIndexHelper(c.program, c.index_shm_id, c.index_shm_offset, |
| + name_str); |
| +} |
| + |
| error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex( |
| uint32 immediate_data_size, const void* cmd_data) { |
| if (!unsafe_es3_apis_enabled()) |
| @@ -15642,23 +15827,24 @@ GLES2DecoderImpl::HandleStencilThenCoverStrokePathInstancedCHROMIUM( |
| return error::kNoError; |
| } |
| -void GLES2DecoderImpl::DoBindFragmentInputLocationCHROMIUM(GLuint program_id, |
| - GLint location, |
| - const char* name) { |
| +void GLES2DecoderImpl::DoBindFragmentInputLocationCHROMIUM( |
| + GLuint program_id, |
| + GLint location, |
| + const std::string& name) { |
| static const char kFunctionName[] = "glBindFragmentInputLocationCHROMIUM"; |
| - Program* program = GetProgram(program_id); |
| - if (!program || program->IsDeleted()) { |
| - LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "invalid program"); |
| - return; |
| - } |
| if (!StringIsValidForGLES(name)) { |
| LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "invalid character"); |
| return; |
| } |
| - if (ProgramManager::IsInvalidPrefix(name, strlen(name))) { |
| + if (ProgramManager::HasBuiltInPrefix(name)) { |
| LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "reserved prefix"); |
| return; |
| } |
| + Program* program = GetProgram(program_id); |
| + if (!program || program->IsDeleted()) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "invalid program"); |
| + return; |
| + } |
| if (location < 0 || |
| static_cast<uint32>(location) >= group_->max_varying_vectors() * 4) { |
| LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, |
| @@ -15692,7 +15878,7 @@ error::Error GLES2DecoderImpl::HandleBindFragmentInputLocationCHROMIUMBucket( |
| if (!bucket->GetAsString(&name_str)) { |
| return error::kInvalidArguments; |
| } |
| - DoBindFragmentInputLocationCHROMIUM(program, location, name_str.c_str()); |
| + DoBindFragmentInputLocationCHROMIUM(program, location, name_str); |
| return error::kNoError; |
| } |