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 5d55c94f25797d7dd2389829560a7dc16fe99948..7bd93976d18f0a806bf8b8bba4e3bc1207185ea2 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -1270,6 +1270,16 @@ class GLES2DecoderImpl : public GLES2Decoder, |
| } |
| void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name); |
| + |
| + error::Error DoBindFragDataLocation(GLuint program_id, |
| + GLuint colorName, |
| + const char* name); |
| + |
| + error::Error DoBindFragDataLocationIndexed(GLuint program_id, |
| + GLuint colorName, |
| + GLuint index, |
| + const char* name); |
| + |
| void DoBindUniformLocationCHROMIUM( |
| GLuint client_id, GLint location, const char* name); |
| @@ -1285,6 +1295,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); |
| @@ -3247,6 +3262,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; |
| @@ -3279,6 +3295,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; |
| @@ -5449,6 +5467,12 @@ bool GLES2DecoderImpl::GetHelper( |
| params[0] = group_->bind_generates_resource() ? 1 : 0; |
| } |
| return true; |
| + case GL_MAX_DUAL_SOURCE_DRAW_BUFFERS: |
| + *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()) { |
| @@ -5629,6 +5653,114 @@ error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket( |
| return error::kNoError; |
| } |
| +error::Error GLES2DecoderImpl::DoBindFragDataLocation(GLuint program_id, |
| + GLuint colorName, |
| + const char* name) { |
| + if (!unsafe_es3_apis_enabled()) |
|
Zhenyao Mo
2015/08/31 21:12:30
No need for this as the extension can be applied t
Kimmo Kinnunen
2015/09/24 13:16:27
No, these functions are not specified in ext_bfe f
|
| + return error::kUnknownCommand; |
| + |
| + const char kFunctionName[] = "glBindFragDataLocationEXT"; |
| + if (!StringIsValidForGLES(name)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "Invalid character"); |
| + return error::kNoError; |
| + } |
| + if (ProgramManager::IsInvalidPrefix(name, strlen(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; |
| + } |
| + DCHECK(!IsWebGLContext()); |
| + // Note: the name is passed directly, since names are never hashed for |
| + // non-WebGL context. Also the |
| + // potential built-in names can not be controlled by the client, since they |
| + // will be overridden if |
| + // used. |
| + glBindFragDataLocation(program->service_id(), colorName, name); |
| + return error::kNoError; |
| +} |
| +error::Error GLES2DecoderImpl::HandleBindFragDataLocationEXTBucket( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + 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); |
| + 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.c_str()); |
| +} |
| + |
| +error::Error GLES2DecoderImpl::DoBindFragDataLocationIndexed(GLuint program_id, |
| + GLuint colorName, |
| + GLuint index, |
| + const char* name) { |
| + if (!unsafe_es3_apis_enabled()) |
|
Zhenyao Mo
2015/08/31 21:12:30
No need for this.
Kimmo Kinnunen
2015/09/24 13:16:27
Not specified for ES2.
For this usecase, ES2 versi
|
| + return error::kUnknownCommand; |
| + |
| + const char kFunctionName[] = "glBindFragDataLocationIndexEXT"; |
| + if (!StringIsValidForGLES(name)) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "Invalid character"); |
| + return error::kNoError; |
| + } |
| + if (ProgramManager::IsInvalidPrefix(name, strlen(name))) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, kFunctionName, "reserved prefix"); |
| + return error::kNoError; |
| + } |
| + if ((index == 0 && colorName >= group_->max_draw_buffers()) || |
| + (index == 1 && colorName >= group_->max_dual_source_draw_buffers())) { |
|
Zhenyao Mo
2015/08/31 21:12:30
I think it should be index >= 1 instead of index =
Kimmo Kinnunen
2015/09/24 13:16:27
Nope. In the extension, it says index must be 0 or
|
| + 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; |
| + } |
| + DCHECK(!IsWebGLContext()); |
| + // Note: the name is passed directly, since names are never hashed for |
| + // non-WebGL context. Also the |
| + // potential built-in names can not be controlled by the client, since they |
| + // will be overridden if |
| + // used. |
| + glBindFragDataLocationIndexed(program->service_id(), colorName, index, name); |
| + return error::kNoError; |
| +} |
| + |
| +error::Error GLES2DecoderImpl::HandleBindFragDataLocationIndexedEXTBucket( |
| + uint32 immediate_data_size, |
| + const void* cmd_data) { |
| + 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); |
| + GLuint index = static_cast<GLint>(c.index); |
| + 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.c_str()); |
| +} |
| + |
| void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM( |
| GLuint program_id, GLint location, const char* name) { |
| if (!StringIsValidForGLES(name)) { |
| @@ -9182,6 +9314,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) { |
| @@ -9192,12 +9325,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; |
| } |
| @@ -9220,6 +9358,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; |
| + } |
| + 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 (!unsafe_es3_apis_enabled()) |
| + 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, |
| + |
|
Zhenyao Mo
2015/08/31 21:12:30
nit: remove the empty line.
Kimmo Kinnunen
2015/09/24 13:16:27
Done.
|
| + name_str); |
| +} |
| + |
| error::Error GLES2DecoderImpl::HandleGetUniformBlockIndex( |
| uint32 immediate_data_size, const void* cmd_data) { |
| if (!unsafe_es3_apis_enabled()) |