summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-12 00:51:34 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-12 00:51:34 +0000
commitf57bb2865fa146140d27e64c68148b79724f2f35 (patch)
tree03becedc67abf8a12fb1970ccaa7b3bbca06b6b7 /gpu/command_buffer/service
parent339d6dd4d356d062365a9a1a1aaf17f42d5349d3 (diff)
downloadchromium_src-f57bb2865fa146140d27e64c68148b79724f2f35.zip
chromium_src-f57bb2865fa146140d27e64c68148b79724f2f35.tar.gz
chromium_src-f57bb2865fa146140d27e64c68148b79724f2f35.tar.bz2
Use the shader translator to correct bad type information
returned by OpenGL drivers. TEST=unit tests, ran OpenGL ES 2.0 conformance tests and ran WebGL conformance test. Things that used to fail now pass. BUG=none Review URL: http://codereview.chromium.org/4829001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65882 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer/service')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc9
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc4
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc4
-rw-r--r--gpu/command_buffer/service/mocks.h24
-rw-r--r--gpu/command_buffer/service/program_manager.cc44
-rw-r--r--gpu/command_buffer/service/program_manager.h4
-rw-r--r--gpu/command_buffer/service/program_manager_unittest.cc119
-rw-r--r--gpu/command_buffer/service/shader_manager.cc27
-rw-r--r--gpu/command_buffer/service/shader_manager.h18
-rw-r--r--gpu/command_buffer/service/shader_manager_unittest.cc76
-rw-r--r--gpu/command_buffer/service/shader_translator.cc4
-rw-r--r--gpu/command_buffer/service/shader_translator.h56
12 files changed, 339 insertions, 50 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 110ea12..4b76497 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -4084,12 +4084,13 @@ void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
// Translate GL ES 2.0 shader to Desktop GL shader and pass that to
// glShaderSource and then glCompileShader.
const char* shader_src = info->source().c_str();
+ ShaderTranslator* translator = NULL;
if (use_shader_translator_) {
- ShaderTranslator* translator = info->shader_type() == GL_VERTEX_SHADER ?
+ translator = info->shader_type() == GL_VERTEX_SHADER ?
vertex_translator_.get() : fragment_translator_.get();
if (!translator->Translate(shader_src)) {
- info->SetStatus(false, translator->info_log());
+ info->SetStatus(false, translator->info_log(), NULL);
return;
}
shader_src = translator->translated_shader();
@@ -4100,7 +4101,7 @@ void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
GLint status = GL_FALSE;
glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
if (status) {
- info->SetStatus(true, "");
+ info->SetStatus(true, "", translator);
} else {
// We cannot reach here if we are using the shader translator.
// All invalid shaders must be rejected by the translator.
@@ -4114,7 +4115,7 @@ void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
DCHECK(max_len == 0 || len < max_len);
DCHECK(len ==0 || temp[len] == '\0');
- info->SetStatus(false, std::string(temp.get(), len));
+ info->SetStatus(false, std::string(temp.get(), len), NULL);
}
};
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 8ea4d27..925e28f 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
@@ -43,8 +43,8 @@ void GLES2DecoderTestBase::SpecializedSetup<LinkProgram, 0>(bool /* valid */) {
DoCreateShader(
GL_FRAGMENT_SHADER, kClientFragmentShaderId, kServiceFragmentShaderId);
- GetShaderInfo(kClientVertexShaderId)->SetStatus(true, "");
- GetShaderInfo(kClientFragmentShaderId)->SetStatus(true, "");
+ GetShaderInfo(kClientVertexShaderId)->SetStatus(true, "", NULL);
+ GetShaderInfo(kClientFragmentShaderId)->SetStatus(true, "", NULL);
InSequence dummy;
EXPECT_CALL(*gl_,
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 de3a528..e253a73 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -566,8 +566,8 @@ 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, "");
+ GetShaderInfo(vertex_shader_client_id)->SetStatus(true, "", NULL);
+ GetShaderInfo(fragment_shader_client_id)->SetStatus(true, "", NULL);
AttachShader attach_cmd;
attach_cmd.Init(program_client_id, vertex_shader_client_id);
diff --git a/gpu/command_buffer/service/mocks.h b/gpu/command_buffer/service/mocks.h
index 647fead..8c84547 100644
--- a/gpu/command_buffer/service/mocks.h
+++ b/gpu/command_buffer/service/mocks.h
@@ -4,9 +4,8 @@
// This file contains definitions for mock objects, used for testing.
-// TODO: This file "manually" defines some mock objects. Using gMock
-// would be definitely preferable, unfortunately it doesn't work on Windows
-// yet.
+// TODO(apatrick): This file "manually" defines some mock objects. Using gMock
+// would be definitely preferable, unfortunately it doesn't work on Windows yet.
#ifndef GPU_COMMAND_BUFFER_SERVICE_MOCKS_H_
#define GPU_COMMAND_BUFFER_SERVICE_MOCKS_H_
@@ -16,6 +15,7 @@
#include "base/logging.h"
#include "gpu/command_buffer/service/cmd_parser.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
+#include "gpu/command_buffer/service/shader_translator.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace gpu {
@@ -77,6 +77,24 @@ class AsyncAPIMock : public AsyncAPIInterface {
CommandBufferEngine *engine_;
};
+namespace gles2 {
+
+class MockShaderTranslator : public ShaderTranslatorInterface {
+ public:
+ virtual ~MockShaderTranslator() { }
+
+ MOCK_METHOD3(Init, bool(
+ ShShaderType shader_type,
+ ShShaderSpec shader_spec,
+ const ShBuiltInResources* resources));
+ MOCK_METHOD1(Translate, bool(const char* shader));
+ MOCK_CONST_METHOD0(translated_shader, const char*());
+ MOCK_CONST_METHOD0(info_log, const char*());
+ MOCK_CONST_METHOD0(attrib_map, const VariableMap&());
+ MOCK_CONST_METHOD0(uniform_map, const VariableMap&());
+};
+
+} // namespace gles2
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_MOCKS_H_
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index c94bd9b..596c8c9 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -27,7 +27,6 @@ static int ShaderTypeToIndex(GLenum shader_type) {
}
}
-
ProgramManager::ProgramInfo::UniformInfo::UniformInfo(GLsizei _size,
GLenum _type,
const std::string& _name)
@@ -92,13 +91,14 @@ void ProgramManager::ProgramInfo::Update() {
DCHECK(max_len == 0 || length < max_len);
DCHECK(length == 0 || name_buffer[length] == '\0');
if (!IsInvalidPrefix(name_buffer.get(), length)) {
+ std::string name;
+ GetCorrectedVariableInfo(false, name_buffer.get(), &name, &size, &type);
// TODO(gman): Should we check for error?
GLint location = glGetAttribLocation(service_id_, name_buffer.get());
if (location > max_location) {
max_location = location;
}
- attrib_infos_.push_back(
- VertexAttribInfo(size, type, name_buffer.get(), location));
+ attrib_infos_.push_back(VertexAttribInfo(size, type, name, location));
max_attrib_name_length_ = std::max(max_attrib_name_length_, length);
}
}
@@ -131,8 +131,9 @@ void ProgramManager::ProgramInfo::Update() {
// TODO(gman): Should we check for error?
if (!IsInvalidPrefix(name_buffer.get(), length)) {
GLint location = glGetUniformLocation(service_id_, name_buffer.get());
- const UniformInfo* info =
- AddUniformInfo(size, type, location, name_buffer.get());
+ std::string name;
+ GetCorrectedVariableInfo(true, name_buffer.get(), &name, &size, &type);
+ const UniformInfo* info = AddUniformInfo(size, type, location, name);
for (size_t jj = 0; jj < info->element_locations.size(); ++jj) {
if (info->element_locations[jj] > max_location) {
max_location = info->element_locations[jj];
@@ -221,6 +222,39 @@ bool ProgramManager::ProgramInfo::GetUniformTypeByLocation(
return false;
}
+// Note: This is only valid to call right after a program has been linked
+// successfully.
+void ProgramManager::ProgramInfo::GetCorrectedVariableInfo(
+ bool use_uniforms,
+ const std::string& name, std::string* corrected_name,
+ GLsizei* size, GLenum* type) const {
+ DCHECK(corrected_name);
+ DCHECK(size);
+ DCHECK(type);
+ const char* kArraySpec = "[0]";
+ for (int jj = 0; jj < 2; ++jj) {
+ std::string test_name(name + ((jj == 1) ? kArraySpec : ""));
+ for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
+ ShaderManager::ShaderInfo* shader_info = attached_shaders_[ii].get();
+ if (shader_info) {
+ const ShaderManager::ShaderInfo::VariableInfo* variable_info =
+ use_uniforms ? shader_info->GetUniformInfo(test_name) :
+ shader_info->GetAttribInfo(test_name);
+ // Note: There is an assuption here that if an attrib is defined in more
+ // than 1 attached shader their types and sizes match. Should we check
+ // for that case?
+ if (variable_info) {
+ *corrected_name = test_name;
+ *type = variable_info->type;
+ *size = variable_info->size;
+ return;
+ }
+ }
+ }
+ }
+ *corrected_name = name;
+}
+
const ProgramManager::ProgramInfo::UniformInfo*
ProgramManager::ProgramInfo::AddUniformInfo(
GLsizei size, GLenum type, GLint location, const std::string& name) {
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index 7fb6fa4..53893b3 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -156,6 +156,10 @@ class ProgramManager {
const UniformInfo* AddUniformInfo(
GLsizei size, GLenum type, GLint location, const std::string& name);
+ void GetCorrectedVariableInfo(
+ bool use_uniforms, const std::string& name, std::string* corrected_name,
+ GLsizei* size, GLenum* type) const;
+
GLsizei max_attrib_name_length_;
// Attrib by index.
diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc
index 1f66fd6..7f4fa21 100644
--- a/gpu/command_buffer/service/program_manager_unittest.cc
+++ b/gpu/command_buffer/service/program_manager_unittest.cc
@@ -10,6 +10,7 @@
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "gpu/command_buffer/common/gl_mock.h"
+#include "gpu/command_buffer/service/mocks.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::gfx::MockGLInterface;
@@ -19,6 +20,7 @@ using ::testing::InSequence;
using ::testing::MatcherCast;
using ::testing::Pointee;
using ::testing::Return;
+using ::testing::ReturnRef;
using ::testing::SetArrayArgument;
using ::testing::SetArgumentPointee;
using ::testing::StrEq;
@@ -124,7 +126,8 @@ class ProgramManagerWithShaderTest : public testing::Test {
static const char* kUniform1Name;
static const char* kUniform2Name;
- static const char* kUniform3Name;
+ static const char* kUniform3BadName;
+ static const char* kUniform3GoodName;
static const GLint kUniform1Size = 1;
static const GLint kUniform2Size = 3;
static const GLint kUniform3Size = 2;
@@ -322,7 +325,7 @@ ProgramManagerWithShaderTest::UniformInfo
ProgramManagerWithShaderTest::kUniforms[] = {
{ kUniform1Name, kUniform1Size, kUniform1Type, kUniform1Location, },
{ kUniform2Name, kUniform2Size, kUniform2Type, kUniform2Location, },
- { kUniform3Name, kUniform3Size, kUniform3Type, kUniform3Location, },
+ { kUniform3BadName, kUniform3Size, kUniform3Type, kUniform3Location, },
};
const size_t ProgramManagerWithShaderTest::kNumUniforms =
@@ -335,7 +338,8 @@ const char* ProgramManagerWithShaderTest::kUniform1Name = "uniform1";
// Correctly has array spec.
const char* ProgramManagerWithShaderTest::kUniform2Name = "uniform2[0]";
// Incorrectly missing array spec.
-const char* ProgramManagerWithShaderTest::kUniform3Name = "uniform3";
+const char* ProgramManagerWithShaderTest::kUniform3BadName = "uniform3";
+const char* ProgramManagerWithShaderTest::kUniform3GoodName = "uniform3[0]";
TEST_F(ProgramManagerWithShaderTest, GetAttribInfos) {
const ProgramManager::ProgramInfo* program_info =
@@ -399,12 +403,11 @@ TEST_F(ProgramManagerWithShaderTest, GetUniformInfo) {
info = program_info->GetUniformInfo(2);
// We emulate certain OpenGL drivers by supplying the name without
// the array spec. Our implementation should correctly add the required spec.
- const std::string expected_name(std::string(kUniform3Name) + "[0]");
ASSERT_TRUE(info != NULL);
EXPECT_EQ(kUniform3Size, info->size);
EXPECT_EQ(kUniform3Type, info->type);
EXPECT_EQ(kUniform3Location, info->element_locations[0]);
- EXPECT_STREQ(expected_name.c_str(), info->name.c_str());
+ EXPECT_STREQ(kUniform3GoodName, info->name.c_str());
EXPECT_TRUE(program_info->GetUniformInfo(kInvalidIndex) == NULL);
}
@@ -422,12 +425,12 @@ TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) {
kVShaderClientId, kVShaderServiceId, GL_VERTEX_SHADER);
ShaderManager::ShaderInfo* vshader = shader_manager.GetShaderInfo(
kVShaderClientId);
- vshader->SetStatus(true, "");
+ vshader->SetStatus(true, "", NULL);
shader_manager.CreateShaderInfo(
kFShaderClientId, kFShaderServiceId, GL_FRAGMENT_SHADER);
ShaderManager::ShaderInfo* fshader = shader_manager.GetShaderInfo(
kFShaderClientId);
- fshader->SetStatus(true, "");
+ fshader->SetStatus(true, "", NULL);
EXPECT_TRUE(program_info->AttachShader(vshader));
EXPECT_FALSE(program_info->CanLink());
EXPECT_TRUE(program_info->AttachShader(fshader));
@@ -442,13 +445,13 @@ TEST_F(ProgramManagerWithShaderTest, AttachDetachShader) {
EXPECT_FALSE(program_info->CanLink());
EXPECT_TRUE(program_info->AttachShader(fshader));
EXPECT_TRUE(program_info->CanLink());
- vshader->SetStatus(false, "");
+ vshader->SetStatus(false, "", NULL);
EXPECT_FALSE(program_info->CanLink());
- vshader->SetStatus(true, "");
+ vshader->SetStatus(true, "", NULL);
EXPECT_TRUE(program_info->CanLink());
- fshader->SetStatus(false, "");
+ fshader->SetStatus(false, "", NULL);
EXPECT_FALSE(program_info->CanLink());
- fshader->SetStatus(true, "");
+ fshader->SetStatus(true, "", NULL);
EXPECT_TRUE(program_info->CanLink());
shader_manager.Destroy(false);
}
@@ -459,13 +462,15 @@ TEST_F(ProgramManagerWithShaderTest, GetUniformLocation) {
ASSERT_TRUE(program_info != NULL);
EXPECT_EQ(kUniform1Location, program_info->GetUniformLocation(kUniform1Name));
EXPECT_EQ(kUniform2Location, program_info->GetUniformLocation(kUniform2Name));
- EXPECT_EQ(kUniform3Location, program_info->GetUniformLocation(kUniform3Name));
+ EXPECT_EQ(kUniform3Location, program_info->GetUniformLocation(
+ kUniform3BadName));
// Check we can get uniform2 as "uniform2" even though the name is
// "uniform2[0]"
EXPECT_EQ(kUniform2Location, program_info->GetUniformLocation("uniform2"));
// Check we can get uniform3 as "uniform3[0]" even though we simulated GL
// returning "uniform3"
- EXPECT_EQ(kUniform3Location, program_info->GetUniformLocation("uniform3[0]"));
+ EXPECT_EQ(kUniform3Location, program_info->GetUniformLocation(
+ kUniform3GoodName));
// Check that we can get the locations of the array elements > 1
EXPECT_EQ(kUniform2Location + 2,
program_info->GetUniformLocation("uniform2[1]"));
@@ -501,7 +506,7 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsGLUnderscoreUniform) {
static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
{ kUniform1Name, kUniform1Size, kUniform1Type, kUniform1Location, },
{ kUniform2Name, kUniform2Size, kUniform2Type, kUniform2Location, },
- { kUniform3Name, kUniform3Size, kUniform3Type, kUniform3Location, },
+ { kUniform3BadName, kUniform3Size, kUniform3Type, kUniform3Location, },
};
const size_t kNumUniforms = arraysize(kUniforms);
static const GLuint kClientProgramId = 1234;
@@ -523,7 +528,91 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsGLUnderscoreUniform) {
// as the "gl_" uniform we skipped.
// +4u is to account for "gl_" and NULL terminator.
program_info->GetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH, &value);
- EXPECT_EQ(strlen(kUniform3Name) + 4u, static_cast<size_t>(value));
+ EXPECT_EQ(strlen(kUniform3BadName) + 4u, static_cast<size_t>(value));
+}
+
+// Some GL drivers incorrectly return the wrong type. For example they return
+// GL_FLOAT_VEC2 when they should return GL_FLOAT_MAT2. Check we handle this.
+TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) {
+ const GLuint kShaderClientId = 999;
+ const GLuint kShaderServiceId = 998;
+ static GLenum kAttrib2BadType = GL_FLOAT_VEC2;
+ static GLenum kAttrib2GoodType = GL_FLOAT_MAT2;
+ static GLenum kUniform2BadType = GL_FLOAT_VEC3;
+ static GLenum kUniform2GoodType = GL_FLOAT_MAT3;
+ MockShaderTranslator shader_translator;
+ ShaderTranslator::VariableMap attrib_map;
+ ShaderTranslator::VariableMap uniform_map;
+ attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo(
+ kAttrib1Type, kAttrib1Size);
+ attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo(
+ kAttrib2GoodType, kAttrib2Size);
+ attrib_map[kAttrib3Name] = ShaderTranslatorInterface::VariableInfo(
+ kAttrib3Type, kAttrib3Size);
+ uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo(
+ kUniform1Type, kUniform1Size);
+ uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo(
+ kUniform2GoodType, kUniform2Size);
+ uniform_map[kUniform3GoodName] = ShaderTranslatorInterface::VariableInfo(
+ kUniform3Type, kUniform3Size);
+ EXPECT_CALL(shader_translator, attrib_map())
+ .WillRepeatedly(ReturnRef(attrib_map));
+ EXPECT_CALL(shader_translator, uniform_map())
+ .WillRepeatedly(ReturnRef(uniform_map));
+ ShaderManager shader_manager;
+ shader_manager.CreateShaderInfo(
+ kShaderClientId, kShaderServiceId, GL_FRAGMENT_SHADER);
+ ShaderManager::ShaderInfo* shader_info =
+ shader_manager.GetShaderInfo(kShaderClientId);
+ shader_info->SetStatus(true, "", &shader_translator);
+ static ProgramManagerWithShaderTest::AttribInfo kAttribs[] = {
+ { kAttrib1Name, kAttrib1Size, kAttrib1Type, kAttrib1Location, },
+ { kAttrib2Name, kAttrib2Size, kAttrib2BadType, kAttrib2Location, },
+ { kAttrib3Name, kAttrib3Size, kAttrib3Type, kAttrib3Location, },
+ };
+ static ProgramManagerWithShaderTest::UniformInfo kUniforms[] = {
+ { kUniform1Name, kUniform1Size, kUniform1Type, kUniform1Location, },
+ { kUniform2Name, kUniform2Size, kUniform2BadType, kUniform2Location, },
+ { kUniform3BadName, kUniform3Size, kUniform3Type, kUniform3Location, },
+ };
+ const size_t kNumAttribs= arraysize(kAttribs);
+ const size_t kNumUniforms = arraysize(kUniforms);
+ static const GLuint kClientProgramId = 1234;
+ static const GLuint kServiceProgramId = 5679;
+ SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
+ kServiceProgramId);
+ manager_.CreateProgramInfo(kClientProgramId, kServiceProgramId);
+ ProgramManager::ProgramInfo* program_info =
+ manager_.GetProgramInfo(kClientProgramId);
+ ASSERT_TRUE(program_info != NULL);
+ EXPECT_TRUE(program_info->AttachShader(shader_info));
+ program_info->Update();
+ // Check that we got the good type, not the bad.
+ // Check Attribs
+ for (unsigned index = 0; index < kNumAttribs; ++index) {
+ const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
+ program_info->GetAttribInfo(index);
+ ASSERT_TRUE(attrib_info != NULL);
+ ShaderTranslator::VariableMap::const_iterator it = attrib_map.find(
+ attrib_info->name);
+ ASSERT_TRUE(it != attrib_map.end());
+ EXPECT_EQ(it->first, attrib_info->name);
+ EXPECT_EQ(static_cast<GLenum>(it->second.type), attrib_info->type);
+ EXPECT_EQ(it->second.size, attrib_info->size);
+ }
+ // Check Uniforms
+ for (unsigned index = 0; index < kNumUniforms; ++index) {
+ const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
+ program_info->GetUniformInfo(index);
+ ASSERT_TRUE(uniform_info != NULL);
+ ShaderTranslator::VariableMap::const_iterator it = uniform_map.find(
+ uniform_info->name);
+ ASSERT_TRUE(it != uniform_map.end());
+ EXPECT_EQ(it->first, uniform_info->name);
+ EXPECT_EQ(static_cast<GLenum>(it->second.type), uniform_info->type);
+ EXPECT_EQ(it->second.size, uniform_info->size);
+ }
+ shader_manager.Destroy(false);
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc
index 2f82ea4..794c75e 100644
--- a/gpu/command_buffer/service/shader_manager.cc
+++ b/gpu/command_buffer/service/shader_manager.cc
@@ -8,6 +8,33 @@
namespace gpu {
namespace gles2 {
+void ShaderManager::ShaderInfo::SetStatus(
+ bool valid, const std::string& log, ShaderTranslatorInterface* translator) {
+ valid_ = valid;
+ log_info_ = log;
+ if (translator && valid) {
+ attrib_map_ = translator->attrib_map();
+ uniform_map_ = translator->uniform_map();
+ } else {
+ attrib_map_.clear();
+ uniform_map_.clear();
+ }
+}
+
+const ShaderManager::ShaderInfo::VariableInfo*
+ ShaderManager::ShaderInfo::GetAttribInfo(
+ const std::string& name) const {
+ VariableMap::const_iterator it = attrib_map_.find(name);
+ return it != attrib_map_.end() ? &it->second : NULL;
+}
+
+const ShaderManager::ShaderInfo::VariableInfo*
+ ShaderManager::ShaderInfo::GetUniformInfo(
+ const std::string& name) const {
+ VariableMap::const_iterator it = uniform_map_.find(name);
+ return it != uniform_map_.end() ? &it->second : NULL;
+}
+
ShaderManager::ShaderManager() {}
ShaderManager::~ShaderManager() {
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h
index e056a3e..0b173c3 100644
--- a/gpu/command_buffer/service/shader_manager.h
+++ b/gpu/command_buffer/service/shader_manager.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/ref_counted.h"
#include "gpu/command_buffer/service/gl_utils.h"
+#include "gpu/command_buffer/service/shader_translator.h"
namespace gpu {
namespace gles2 {
@@ -27,6 +28,7 @@ class ShaderManager {
class ShaderInfo : public base::RefCounted<ShaderInfo> {
public:
typedef scoped_refptr<ShaderInfo> Ref;
+ typedef ShaderTranslator::VariableInfo VariableInfo;
explicit ShaderInfo(GLuint service_id, GLenum shader_type)
: service_id_(service_id),
@@ -50,10 +52,12 @@ class ShaderManager {
return source_;
}
- void SetStatus(bool valid, const std::string& log) {
- valid_ = valid;
- log_info_ = log;
- }
+ void SetStatus(
+ bool valid, const std::string& log,
+ ShaderTranslatorInterface* translator);
+
+ const VariableInfo* GetAttribInfo(const std::string& name) const;
+ const VariableInfo* GetUniformInfo(const std::string& name) const;
const std::string& log_info() const {
return log_info_;
@@ -68,6 +72,8 @@ class ShaderManager {
}
private:
+ typedef ShaderTranslator::VariableMap VariableMap;
+
friend class base::RefCounted<ShaderInfo>;
friend class ShaderManager;
~ShaderInfo() { }
@@ -89,6 +95,10 @@ class ShaderManager {
// The shader translation log.
std::string log_info_;
+
+ // The type info when the shader was last compiled.
+ VariableMap attrib_map_;
+ VariableMap uniform_map_;
};
ShaderManager();
diff --git a/gpu/command_buffer/service/shader_manager_unittest.cc b/gpu/command_buffer/service/shader_manager_unittest.cc
index 8deace2..c069257 100644
--- a/gpu/command_buffer/service/shader_manager_unittest.cc
+++ b/gpu/command_buffer/service/shader_manager_unittest.cc
@@ -6,8 +6,12 @@
#include "base/scoped_ptr.h"
#include "gpu/command_buffer/common/gl_mock.h"
+#include "gpu/command_buffer/service/mocks.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::Return;
+using ::testing::ReturnRef;
+
namespace gpu {
namespace gles2 {
@@ -53,7 +57,7 @@ TEST_F(ShaderManagerTest, Basic) {
EXPECT_FALSE(info1->IsValid());
EXPECT_STREQ("", info1->log_info().c_str());
const char* kLog = "foo";
- info1->SetStatus(true, kLog);
+ info1->SetStatus(true, kLog, NULL);
EXPECT_TRUE(info1->IsValid());
EXPECT_STREQ(kLog, info1->log_info().c_str());
// Check we can set its source.
@@ -86,6 +90,76 @@ TEST_F(ShaderManagerTest, Destroy) {
ASSERT_TRUE(info1 == NULL);
}
+TEST_F(ShaderManagerTest, GetInfo) {
+ const GLuint kClient1Id = 1;
+ const GLuint kService1Id = 11;
+ const GLenum kShader1Type = GL_VERTEX_SHADER;
+ const GLenum kAttrib1Type = GL_FLOAT_VEC2;
+ const GLsizei kAttrib1Size = 2;
+ const char* kAttrib1Name = "attr1";
+ const GLenum kAttrib2Type = GL_FLOAT_VEC3;
+ const GLsizei kAttrib2Size = 4;
+ const char* kAttrib2Name = "attr2";
+ const GLenum kUniform1Type = GL_FLOAT_MAT2;
+ const GLsizei kUniform1Size = 3;
+ const char* kUniform1Name = "uni1";
+ const GLenum kUniform2Type = GL_FLOAT_MAT3;
+ const GLsizei kUniform2Size = 5;
+ const char* kUniform2Name = "uni2";
+ MockShaderTranslator shader_translator;
+ ShaderTranslator::VariableMap attrib_map;
+ attrib_map[kAttrib1Name] = ShaderTranslatorInterface::VariableInfo(
+ kAttrib1Type, kAttrib1Size);
+ attrib_map[kAttrib2Name] = ShaderTranslatorInterface::VariableInfo(
+ kAttrib2Type, kAttrib2Size);
+ ShaderTranslator::VariableMap uniform_map;
+ uniform_map[kUniform1Name] = ShaderTranslatorInterface::VariableInfo(
+ kUniform1Type, kUniform1Size);
+ uniform_map[kUniform2Name] = ShaderTranslatorInterface::VariableInfo(
+ kUniform2Type, kUniform2Size);
+ EXPECT_CALL(shader_translator, attrib_map())
+ .WillRepeatedly(ReturnRef(attrib_map));
+ EXPECT_CALL(shader_translator, uniform_map())
+ .WillRepeatedly(ReturnRef(uniform_map));
+ // Check we can create shader.
+ manager_.CreateShaderInfo(kClient1Id, kService1Id, kShader1Type);
+ // Check shader got created.
+ ShaderManager::ShaderInfo* info1 = manager_.GetShaderInfo(kClient1Id);
+ // Set Status
+ info1->SetStatus(true, "", &shader_translator);
+ // Check attrib and uniform infos got copied.
+ for (ShaderTranslator::VariableMap::const_iterator it = attrib_map.begin();
+ it != attrib_map.end(); ++it) {
+ const ShaderManager::ShaderInfo::VariableInfo* variable_info =
+ info1->GetAttribInfo(it->first);
+ ASSERT_TRUE(variable_info != NULL);
+ EXPECT_EQ(it->second.type, variable_info->type);
+ EXPECT_EQ(it->second.size, variable_info->size);
+ }
+ for (ShaderTranslator::VariableMap::const_iterator it = uniform_map.begin();
+ it != uniform_map.end(); ++it) {
+ const ShaderManager::ShaderInfo::VariableInfo* variable_info =
+ info1->GetUniformInfo(it->first);
+ ASSERT_TRUE(variable_info != NULL);
+ EXPECT_EQ(it->second.type, variable_info->type);
+ EXPECT_EQ(it->second.size, variable_info->size);
+ }
+ // Check attrib and uniform get cleared.
+ info1->SetStatus(true, "", NULL);
+ for (ShaderTranslator::VariableMap::const_iterator it = attrib_map.begin();
+ it != attrib_map.end(); ++it) {
+ const ShaderManager::ShaderInfo::VariableInfo* variable_info =
+ info1->GetAttribInfo(it->first);
+ EXPECT_TRUE(variable_info == NULL);
+ }
+ for (ShaderTranslator::VariableMap::const_iterator it = uniform_map.begin();
+ it != uniform_map.end(); ++it) {
+ const ShaderManager::ShaderInfo::VariableInfo* variable_info =
+ info1->GetUniformInfo(it->first);
+ ASSERT_TRUE(variable_info == NULL);
+ }
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc
index 1b5ab6d..551ae14 100644
--- a/gpu/command_buffer/service/shader_translator.cc
+++ b/gpu/command_buffer/service/shader_translator.cc
@@ -53,9 +53,7 @@ void GetVariableInfo(ShHandle compiler, ShShaderInfo var_type,
default: NOTREACHED();
}
- ShaderTranslator::VariableInfo info = {0};
- info.type = type;
- info.size = size;
+ ShaderTranslator::VariableInfo info(type, size);
(*var_map)[name.get()] = info;
}
}
diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h
index 5054972..852ee5f 100644
--- a/gpu/command_buffer/service/shader_translator.h
+++ b/gpu/command_buffer/service/shader_translator.h
@@ -16,35 +16,69 @@ namespace gpu {
namespace gles2 {
// Translates GLSL ES 2.0 shader to desktop GLSL shader.
-class ShaderTranslator {
+class ShaderTranslatorInterface {
public:
- ShaderTranslator();
- ~ShaderTranslator();
+ virtual ~ShaderTranslatorInterface() { }
// Initializes the translator.
// Must be called once before using the translator object.
- bool Init(ShShaderType shader_type,
- ShShaderSpec shader_spec,
- const ShBuiltInResources* resources);
+ virtual bool Init(
+ ShShaderType shader_type,
+ ShShaderSpec shader_spec,
+ const ShBuiltInResources* resources) = 0;
+
// Translates the given shader source.
// Returns true if translation is successful, false otherwise.
- bool Translate(const char* shader);
+ virtual bool Translate(const char* shader) = 0;
// The following functions return results from the last translation.
// The results are NULL/empty if the translation was unsuccessful.
// A valid info-log is always returned irrespective of whether translation
// was successful or not.
- const char* translated_shader() { return translated_shader_.get(); }
- const char* info_log() { return info_log_.get(); }
+ virtual const char* translated_shader() const = 0;
+ virtual const char* info_log() const = 0;
struct VariableInfo {
+ VariableInfo()
+ : type(0),
+ size(0) {
+ }
+ VariableInfo(int _type, int _size)
+ : type(_type),
+ size(_size) {
+ }
int type;
int size;
};
// Mapping between variable name and info.
typedef std::map<std::string, VariableInfo> VariableMap;
- const VariableMap& attrib_map() { return attrib_map_; }
- const VariableMap& uniform_map() { return uniform_map_; }
+ virtual const VariableMap& attrib_map() const = 0;
+ virtual const VariableMap& uniform_map() const = 0;
+};
+
+// Implementation of ShaderTranslatorInterface
+class ShaderTranslator : public ShaderTranslatorInterface {
+ public:
+ ShaderTranslator();
+ ~ShaderTranslator();
+
+ // Overridden from ShaderTranslatorInterface.
+ virtual bool Init(
+ ShShaderType shader_type,
+ ShShaderSpec shader_spec,
+ const ShBuiltInResources* resources);
+
+ // Overridden from ShaderTranslatorInterface.
+ virtual bool Translate(const char* shader);
+
+ // Overridden from ShaderTranslatorInterface.
+ virtual const char* translated_shader() const {
+ return translated_shader_.get(); }
+ virtual const char* info_log() const { return info_log_.get(); }
+
+ // Overridden from ShaderTranslatorInterface.
+ virtual const VariableMap& attrib_map() const { return attrib_map_; }
+ virtual const VariableMap& uniform_map() const { return uniform_map_; }
private:
void ClearResults();