diff options
12 files changed, 161 insertions, 56 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index acea9d3..1b7df40 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1196,8 +1196,7 @@ _FUNCTION_INFO = { }, 'GetProgramInfoLog': { 'type': 'STRn', - 'get_len_func': 'glGetProgramiv', - 'get_len_enum': 'GL_INFO_LOG_LENGTH', + 'expectation': False, }, 'GetRenderbufferParameteriv': { 'type': 'GETn', @@ -3747,7 +3746,7 @@ TEST_F(%(test_name)s, %(name)sValidArgs) { 'args': '%s, kBucketId' % args[0].GetValidArg(0, 0), 'expect_len_code': '', } - if get_len_func[0:2] == 'gl': + if get_len_func and get_len_func[0:2] == 'gl': sub['expect_len_code'] = ( " EXPECT_CALL(*gl_, %s(%s, %s, _))\n" " .WillOnce(SetArgumentPointee<2>(strlen(kInfo) + 1));") % ( diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 9122b81..8d8ccb0 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -2722,8 +2722,6 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program) { return; } if (!info->CanLink()) { - SetGLError(GL_INVALID_OPERATION, - "glLinkProgram: must have both vertex and fragment shader"); return; } glLinkProgram(info->service_id()); @@ -3287,18 +3285,27 @@ void GLES2DecoderImpl::DoCompileShader(GLuint client_id) { compiler = ShConstructCompiler(language, dbg_options); if (!ShCompile(compiler, &shader_src, 1, EShOptNone, &resources, dbg_options)) { - info->SetTranslationStatus(false, ShGetInfoLog(compiler)); + info->SetStatus(false, ShGetInfoLog(compiler)); ShDestruct(compiler); return; } - - info->SetTranslationStatus(true, ""); shader_src = ShGetObjectCode(compiler); } #endif // GLES2_GPU_SERVICE_TRANSLATE_SHADER glShaderSource(info->service_id(), 1, &shader_src, NULL); glCompileShader(info->service_id()); + GLint status = GL_FALSE; + glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status); + if (status) { + info->SetStatus(true, ""); + } else { + GLint len = 0; + glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &len); + scoped_array<char> temp(new char[len]); + glGetShaderInfoLog(info->service_id(), len, &len, temp.get()); + info->SetStatus(false, std::string(temp.get(), len)); + } #ifdef GLES2_GPU_SERVICE_TRANSLATE_SHADER if (use_shader_translator_) { ShDestruct(compiler); @@ -3318,17 +3325,11 @@ void GLES2DecoderImpl::DoGetShaderiv( *params = info->source().size(); return; case GL_COMPILE_STATUS: - if (!info->translation_valid()) { - *params = GL_FALSE; - return; - } - break; + *params = info->IsValid(); + return; case GL_INFO_LOG_LENGTH: - if (!info->translation_valid()) { - *params = info->translation_log().size() + 1; - return; - } - break; + *params = info->log_info().size() + 1; + return; default: break; } @@ -3360,12 +3361,7 @@ error::Error GLES2DecoderImpl::HandleGetProgramInfoLog( if (!info) { return error::kNoError; } - GLint len = 0; - glGetProgramiv(info->service_id(), GL_INFO_LOG_LENGTH, &len); - bucket->SetSize(len); - glGetProgramInfoLog( - info->service_id(), - len, &len, bucket->GetDataAs<GLchar*>(0, len)); + bucket->SetFromString(info->log_info()); return error::kNoError; } @@ -3380,16 +3376,7 @@ error::Error GLES2DecoderImpl::HandleGetShaderInfoLog( bucket->SetSize(0); return error::kNoError; } - if (!info->translation_valid()) { - bucket->SetFromString(info->translation_log()); - } else { - GLint len = 0; - glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &len); - bucket->SetSize(len); - glGetShaderInfoLog( - info->service_id(), - len, &len, bucket->GetDataAs<GLchar*>(0, len)); - } + bucket->SetFromString(info->log_info()); return error::kNoError; } @@ -3455,7 +3442,12 @@ void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) { if (!info) { return; } + if (!info->CanLink()) { + info->set_log_info("Missing Shader"); + return; + } glValidateProgram(info->service_id()); + info->UpdateLogInfo(); } void GLES2DecoderImpl::DoGetVertexAttribfv( diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 989af20..e77b78f 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -913,6 +913,9 @@ TEST_F(GLES2DecoderWithShaderTest, GetShaderInfoLogValidArgs) { GetShaderInfoLog cmd; EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _)); EXPECT_CALL(*gl_, CompileShader(kServiceShaderId)); + EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _)) + .WillOnce(SetArgumentPointee<2>(GL_FALSE)) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_INFO_LOG_LENGTH, _)) .WillOnce(SetArgumentPointee<2>(strlen(kInfo) + 1)) .RetiresOnSaturation(); @@ -943,6 +946,9 @@ TEST_F(GLES2DecoderWithShaderTest, GetShaderInfoLogInvalidArgs) { TEST_F(GLES2DecoderTest, CompileShaderValidArgs) { EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _)); EXPECT_CALL(*gl_, CompileShader(kServiceShaderId)); + EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _)) + .WillOnce(SetArgumentPointee<2>(GL_TRUE)) + .RetiresOnSaturation(); CompileShader cmd; cmd.Init(client_shader_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc index c233d96..96c964d 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc @@ -76,6 +76,14 @@ void GLES2DecoderTestBase::SpecializedSetup<GetRenderbufferParameteriv, 0>( kServiceRenderbufferId); }; +template <> +void GLES2DecoderTestBase::SpecializedSetup<GetProgramInfoLog, 0>( + bool /* valid */) { + ProgramManager::ProgramInfo* info = GetProgramInfo(client_program_id_); + info->set_log_info("hello"); +}; + + #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h" } // namespace gles2 diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h index 76000af..ef44a59 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h @@ -1485,12 +1485,7 @@ TEST_F(GLES2DecoderTest1, GetProgramInfoLogValidArgs) { const char* kInfo = "hello"; const uint32 kBucketId = 123; SpecializedSetup<GetProgramInfoLog, 0>(true); - EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_INFO_LOG_LENGTH, _)) - .WillOnce(SetArgumentPointee<2>(strlen(kInfo) + 1)); - EXPECT_CALL( - *gl_, GetProgramInfoLog(kServiceProgramId, strlen(kInfo) + 1, _, _)) - .WillOnce(DoAll(SetArgumentPointee<2>(strlen(kInfo)), - SetArrayArgument<3>(kInfo, kInfo + strlen(kInfo) + 1))); + GetProgramInfoLog cmd; cmd.Init(client_program_id_, kBucketId); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); @@ -1504,8 +1499,6 @@ TEST_F(GLES2DecoderTest1, GetProgramInfoLogValidArgs) { TEST_F(GLES2DecoderTest1, GetProgramInfoLogInvalidArgs) { const uint32 kBucketId = 123; - EXPECT_CALL(*gl_, GetProgramInfoLog(_, _, _, _)) - .Times(0); GetProgramInfoLog cmd; cmd.Init(kInvalidClientId, kBucketId); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc index 0d29046..8c64240c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc @@ -43,6 +43,9 @@ void GLES2DecoderTestBase::SpecializedSetup<LinkProgram, 0>(bool /* valid */) { DoCreateShader( GL_FRAGMENT_SHADER, kClientFragmentShaderId, kServiceFragmentShaderId); + GetShaderInfo(kClientVertexShaderId)->SetStatus(true, ""); + GetShaderInfo(kClientFragmentShaderId)->SetStatus(true, ""); + InSequence dummy; EXPECT_CALL(*gl_, AttachShader(kServiceProgramId, kServiceVertexShaderId)) @@ -54,6 +57,14 @@ void GLES2DecoderTestBase::SpecializedSetup<LinkProgram, 0>(bool /* valid */) { .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _)) .WillOnce(SetArgumentPointee<2>(1)); + EXPECT_CALL(*gl_, + GetProgramiv(kServiceProgramId, GL_INFO_LOG_LENGTH, _)) + .WillOnce(SetArgumentPointee<2>(0)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + GetProgramInfoLog(kServiceProgramId, _, _, _)) + .Times(1) + .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_ACTIVE_ATTRIBUTES, _)) .WillOnce(SetArgumentPointee<2>(0)); EXPECT_CALL( @@ -73,7 +84,30 @@ void GLES2DecoderTestBase::SpecializedSetup<LinkProgram, 0>(bool /* valid */) { attach_cmd.Init(client_program_id_, kClientFragmentShaderId); EXPECT_EQ(error::kNoError, ExecuteCmd(attach_cmd)); +}; + +template <> +void GLES2DecoderTestBase::SpecializedSetup<ValidateProgram, 0>( + bool /* valid */) { + // Needs the same setup as LinkProgram. + SpecializedSetup<LinkProgram, 0>(false); + EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId)) + .Times(1) + .RetiresOnSaturation(); + + LinkProgram link_cmd; + link_cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(link_cmd)); + + EXPECT_CALL(*gl_, + GetProgramiv(kServiceProgramId, GL_INFO_LOG_LENGTH, _)) + .WillOnce(SetArgumentPointee<2>(0)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + GetProgramInfoLog(kServiceProgramId, _, _, _)) + .Times(1) + .RetiresOnSaturation(); }; template <> diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 7d61fe6..2671058 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -437,7 +437,15 @@ void GLES2DecoderTestBase::SetupShader( .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetProgramiv(program_service_id, GL_LINK_STATUS, _)) - .WillOnce(SetArgumentPointee<2>(1)) + .WillOnce(SetArgumentPointee<2>(GL_TRUE)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + GetProgramiv(program_service_id, GL_INFO_LOG_LENGTH, _)) + .WillOnce(SetArgumentPointee<2>(0)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + GetProgramInfoLog(program_service_id, _, _, _)) + .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*gl_, GetProgramiv(program_service_id, GL_ACTIVE_ATTRIBUTES, _)) @@ -519,6 +527,9 @@ void GLES2DecoderTestBase::SetupShader( GL_FRAGMENT_SHADER, fragment_shader_client_id, fragment_shader_service_id); + GetShaderInfo(vertex_shader_client_id)->SetStatus(true, ""); + GetShaderInfo(fragment_shader_client_id)->SetStatus(true, ""); + AttachShader attach_cmd; attach_cmd.Init(program_client_id, vertex_shader_client_id); EXPECT_EQ(error::kNoError, ExecuteCmd(attach_cmd)); diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index 2dcb368..66605b3 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc @@ -39,6 +39,15 @@ void ProgramManager::ProgramInfo::Reset() { sampler_indices_.clear(); attrib_location_to_index_map_.clear(); uniform_location_to_index_map_.clear(); + UpdateLogInfo(); +} + +void ProgramManager::ProgramInfo::UpdateLogInfo() { + GLint len = 0; + glGetProgramiv(service_id_, GL_INFO_LOG_LENGTH, &len); + scoped_array<char> temp(new char[len]); + glGetProgramInfoLog(service_id_, len, &len, temp.get()); + set_log_info(std::string(temp.get(), len)); } void ProgramManager::ProgramInfo::Update() { @@ -261,6 +270,17 @@ void ProgramManager::ProgramInfo::GetProgramiv(GLenum pname, GLint* params) { case GL_LINK_STATUS: *params = valid_; break; + case GL_INFO_LOG_LENGTH: + // Notice +1 to accomodate NULL terminator. + *params = log_info_.size() + 1; + break; + case GL_VALIDATE_STATUS: + if (!CanLink()) { + *params = GL_FALSE; + } else { + glGetProgramiv(service_id_, pname, params); + } + break; default: glGetProgramiv(service_id_, pname, params); break; @@ -280,7 +300,7 @@ void ProgramManager::ProgramInfo::DetachShader( bool ProgramManager::ProgramInfo::CanLink() const { for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { - if (!attached_shaders_[ii]) { + if (!attached_shaders_[ii] || !attached_shaders_[ii]->IsValid()) { return false; } } diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h index 77cb39d..995caa2 100644 --- a/gpu/command_buffer/service/program_manager.h +++ b/gpu/command_buffer/service/program_manager.h @@ -88,6 +88,9 @@ class ProgramManager { // Updates the program info after a successful link. void Update(); + // Updates the program log info. + void UpdateLogInfo(); + const AttribInfoVector& GetAttribInfos() const { return attrib_infos_; } @@ -140,6 +143,14 @@ class ProgramManager { bool CanLink() const; + const std::string& log_info() const { + return log_info_; + } + + void set_log_info(const std::string& str) { + log_info_ = str; + } + private: friend class base::RefCounted<ProgramInfo>; friend class ProgramManager; @@ -180,6 +191,9 @@ class ProgramManager { // This is true if glLinkProgram was successful. bool valid_; + + // Log info + std::string log_info_; }; ProgramManager() { } diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc index 2d8f22a..a3a47d9 100644 --- a/gpu/command_buffer/service/program_manager_unittest.cc +++ b/gpu/command_buffer/service/program_manager_unittest.cc @@ -48,6 +48,7 @@ TEST_F(ProgramManagerTest, Basic) { ASSERT_TRUE(info1 != NULL); EXPECT_EQ(kService1Id, info1->service_id()); EXPECT_FALSE(info1->CanLink()); + EXPECT_STREQ("", info1->log_info().c_str()); GLuint client_id = 0; EXPECT_TRUE(manager_.GetClientId(info1->service_id(), &client_id)); EXPECT_EQ(kClient1Id, client_id); @@ -135,6 +136,14 @@ class ProgramManagerWithShaderTest : public testing::Test { GLuint service_id) { InSequence s; EXPECT_CALL(*gl_, + GetProgramiv(service_id, GL_INFO_LOG_LENGTH, _)) + .WillOnce(SetArgumentPointee<2>(0)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + GetProgramInfoLog(service_id, _, _, _)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _)) .WillOnce(SetArgumentPointee<2>(num_attribs)) .RetiresOnSaturation(); @@ -373,10 +382,12 @@ TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) { kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER); ShaderManager::ShaderInfo* vshader = shader_manager.GetShaderInfo( kVShaderClientId); + vshader->SetStatus(true, ""); shader_manager.CreateShaderInfo( kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER); ShaderManager::ShaderInfo* fshader = shader_manager.GetShaderInfo( kFShaderClientId); + fshader->SetStatus(true, ""); program_info->AttachShader(vshader); EXPECT_FALSE(program_info->CanLink()); program_info->AttachShader(fshader); @@ -387,6 +398,18 @@ TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) { EXPECT_TRUE(program_info->CanLink()); program_info->DetachShader(fshader); EXPECT_FALSE(program_info->CanLink()); + program_info->AttachShader(vshader); + EXPECT_FALSE(program_info->CanLink()); + program_info->AttachShader(fshader); + EXPECT_TRUE(program_info->CanLink()); + vshader->SetStatus(false, ""); + EXPECT_FALSE(program_info->CanLink()); + vshader->SetStatus(true, ""); + EXPECT_TRUE(program_info->CanLink()); + fshader->SetStatus(false, ""); + EXPECT_FALSE(program_info->CanLink()); + fshader->SetStatus(true, ""); + EXPECT_TRUE(program_info->CanLink()); } TEST_F(ProgramManagerWithShaderTest, GetUniformLocation) { diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h index 3391ff6..b0bcfa2 100644 --- a/gpu/command_buffer/service/shader_manager.h +++ b/gpu/command_buffer/service/shader_manager.h @@ -31,7 +31,7 @@ class ShaderManager { explicit ShaderInfo(GLuint service_id, GLenum shader_type) : service_id_(service_id), shader_type_(shader_type), - translation_valid_(true) { + valid_(false) { } void Update(const std::string& source) { @@ -50,17 +50,17 @@ class ShaderManager { return source_; } - void SetTranslationStatus(bool valid, const std::string& log) { - translation_valid_ = valid; - translation_log_ = log; + void SetStatus(bool valid, const std::string& log) { + valid_ = valid; + log_info_ = log; } - const std::string& translation_log() const { - return translation_log_; + const std::string& log_info() const { + return log_info_; } - bool translation_valid() const { - return translation_valid_; + bool IsValid() const { + return valid_; } bool IsDeleted() const { @@ -81,14 +81,14 @@ class ShaderManager { // Type of shader - GL_VERTEX_SHADER or GL_FRAGMENT_SHADER. GLenum shader_type_; - // True if translation succeeded. - bool translation_valid_; + // True if compilation succeeded. + bool valid_; // The shader source as passed to glShaderSource. std::string source_; // The shader translation log. - std::string translation_log_; + std::string log_info_; }; ShaderManager() { diff --git a/gpu/command_buffer/service/shader_manager_unittest.cc b/gpu/command_buffer/service/shader_manager_unittest.cc index 12ec9e4..e93a65ef 100644 --- a/gpu/command_buffer/service/shader_manager_unittest.cc +++ b/gpu/command_buffer/service/shader_manager_unittest.cc @@ -37,7 +37,12 @@ TEST_F(ShaderManagerTest, Basic) { EXPECT_EQ(kService1Id, info1->service_id()); // Check if the shader has correct type. EXPECT_EQ(kShader1Type, info1->shader_type()); - EXPECT_EQ(true, info1->translation_valid()); + EXPECT_FALSE(info1->IsValid()); + EXPECT_STREQ("", info1->log_info().c_str()); + const char* kLog = "foo"; + info1->SetStatus(true, kLog); + EXPECT_TRUE(info1->IsValid()); + EXPECT_STREQ(kLog, info1->log_info().c_str()); // Check we can set its source. info1->Update(kClient1Source); EXPECT_STREQ(kClient1Source.c_str(), info1->source().c_str()); |