| 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 34ddc02171a0ff5e89669900151afc3dc263bb35..1dec5cf2002c7dfcdf9db9099edbdfd5c3b84b1b 100644
|
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
| @@ -294,13 +294,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
|
| @@ -1200,9 +1197,22 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
|
| 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,
|
| @@ -1216,6 +1226,11 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
|
| 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);
|
| @@ -1859,7 +1874,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
|
|
|
| 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.
|
| #define GLES2_CMD_OP(name) \
|
| @@ -3178,6 +3194,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;
|
| @@ -3210,6 +3227,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;
|
| @@ -5485,6 +5504,12 @@ bool GLES2DecoderImpl::GetHelper(
|
| params[0] = group_->bind_generates_resource() ? 1 : 0;
|
| }
|
| return true;
|
| + case GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT:
|
| + *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()) {
|
| @@ -5614,14 +5639,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;
|
| @@ -5643,7 +5669,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(
|
| @@ -5661,19 +5687,121 @@ 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;
|
| + }
|
| + program->SetProgramOutputLocationBinding(name, colorName);
|
| return error::kNoError;
|
| }
|
|
|
| -void GLES2DecoderImpl::DoBindUniformLocationCHROMIUM(
|
| - GLuint program_id, GLint location, const char* name) {
|
| +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<GLuint>(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);
|
| +}
|
| +
|
| +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 && index != 1) {
|
| + LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "index out of range");
|
| + return error::kNoError;
|
| + }
|
| + if ((index == 0 && colorName >= group_->max_draw_buffers()) ||
|
| + (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;
|
| + }
|
| + program->SetProgramOutputLocationIndexedBinding(name, colorName, index);
|
| + return error::kNoError;
|
| +}
|
| +
|
| +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<GLuint>(c.colorNumber);
|
| + GLuint index = static_cast<GLuint>(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);
|
| +}
|
| +
|
| +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");
|
| @@ -5715,7 +5843,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;
|
| }
|
|
|
| @@ -9360,7 +9488,7 @@ error::Error GLES2DecoderImpl::HandleScheduleCALayerCHROMIUM(
|
| 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;
|
| @@ -9408,7 +9536,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;
|
| @@ -9508,6 +9636,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) {
|
| @@ -9517,12 +9646,17 @@ error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
|
| if (*location != -1) {
|
| return error::kInvalidArguments;
|
| }
|
| - 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;
|
| }
|
|
|
| @@ -9545,6 +9679,55 @@ 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;
|
| + }
|
| + // Check that the client initialized the result.
|
| + if (*index != -1) {
|
| + return error::kInvalidArguments;
|
| + }
|
| + 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())
|
| @@ -15288,23 +15471,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,
|
| @@ -15335,7 +15519,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;
|
| }
|
|
|
|
|