summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-23 19:32:00 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-23 19:32:00 +0000
commitc2a3caf176f7eae1d5d3c2f25f49515d32822b56 (patch)
treee0f0a5d8897b7bc5627d17d0873505276bcbc376 /gpu
parent18b1ff88a4e66e2e86a9359528e5981e945ec7cd (diff)
downloadchromium_src-c2a3caf176f7eae1d5d3c2f25f49515d32822b56.zip
chromium_src-c2a3caf176f7eae1d5d3c2f25f49515d32822b56.tar.gz
chromium_src-c2a3caf176f7eae1d5d3c2f25f49515d32822b56.tar.bz2
Work around NVidia's glLinkProgram bug
glLinkProgram is supposed to start using a linked program immediately if that program is the current program BUG=110263 Review URL: https://chromiumcodereview.appspot.com/11227045 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@163642 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc7
-rw-r--r--gpu/command_buffer/tests/gl_program_unittests.cc166
-rw-r--r--gpu/gpu.gyp1
3 files changed, 173 insertions, 1 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index f7e3ebc..662c21c 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -4747,7 +4747,12 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
fragment_translator,
feature_info_)) {
if (info == state_.current_program.get()) {
- program_manager()->ClearUniforms(info);
+ if (!feature_info_->feature_flags().disable_workarounds) {
+ if (feature_info_->feature_flags().is_nvidia) {
+ glUseProgram(info->service_id());
+ }
+ program_manager()->ClearUniforms(info);
+ }
}
}
};
diff --git a/gpu/command_buffer/tests/gl_program_unittests.cc b/gpu/command_buffer/tests/gl_program_unittests.cc
new file mode 100644
index 0000000..620987b
--- /dev/null
+++ b/gpu/command_buffer/tests/gl_program_unittests.cc
@@ -0,0 +1,166 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include "gpu/command_buffer/tests/gl_manager.h"
+#include "gpu/command_buffer/tests/gl_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define SHADER(Src) #Src
+
+namespace gpu {
+
+class GLProgramTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ gl_.Initialize(gfx::Size(4, 4));
+ }
+
+ virtual void TearDown() {
+ gl_.Destroy();
+ }
+
+ GLManager gl_;
+};
+
+TEST_F(GLProgramTest, GetSetUniform) {
+ static const char* v_shader_str = SHADER(
+ attribute vec4 a_vertex;
+ attribute vec3 a_normal;
+
+ uniform mat4 u_modelViewProjMatrix;
+
+ struct MyStruct
+ {
+ int x;
+ int y;
+ };
+
+ uniform MyStruct u_struct;
+ uniform float u_array[4];
+
+ varying vec3 v_normal;
+
+ void main()
+ {
+ v_normal = a_normal;
+ gl_Position = u_modelViewProjMatrix * a_vertex +
+ vec4(u_struct.x, u_struct.y, 0, 1) +
+ vec4(u_array[0], u_array[1], u_array[2], u_array[3]);
+ }
+ );
+ static const char* f_shader_str = SHADER(
+ varying mediump vec3 v_normal;
+
+ void main()
+ {
+ gl_FragColor = vec4(v_normal/2.0+vec3(0.5), 1);
+ }
+ );
+
+ // Load the program.
+ GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
+ glUseProgram(program);
+ // Relink program.
+ glLinkProgram(program);
+
+ // These tests will fail on NVidia if not worked around by
+ // command buffer.
+ GLint location_sx = glGetUniformLocation(program, "u_struct.x");
+ GLint location_array_0 = glGetUniformLocation(program, "u_array[0]");
+
+ glUniform1i(location_sx, 3);
+ glUniform1f(location_array_0, 123);
+
+ GLint int_value = 0;
+ GLfloat float_value = 0;
+
+ glGetUniformiv(program, location_sx, &int_value);
+ EXPECT_EQ(3, int_value);
+ glGetUniformfv(program, location_array_0, &float_value);
+ EXPECT_EQ(123.0f, float_value);
+
+ GLTestHelper::CheckGLError("no errors", __LINE__);
+}
+
+TEST_F(GLProgramTest, NewShaderInCurrentProgram) {
+ static const char* v_shader_str = SHADER(
+ attribute vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+ );
+ static const char* f_red_shader_str = SHADER(
+ void main()
+ {
+ gl_FragColor = vec4(1, 0, 0, 1);
+ }
+ );
+ static const char* f_blue_shader_str = SHADER(
+ void main()
+ {
+ gl_FragColor = vec4(0, 0, 1, 1);
+ }
+ );
+
+ // Load the program.
+ GLuint vs = GLTestHelper::LoadShader(GL_VERTEX_SHADER, v_shader_str);
+ GLuint fs = GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, f_red_shader_str);
+ GLuint program = GLTestHelper::SetupProgram(vs, fs);
+ glUseProgram(program);
+ glShaderSource(fs, 1, &f_blue_shader_str, NULL);
+ glCompileShader(fs);
+ glLinkProgram(program);
+ // We specifically don't call UseProgram again.
+ GLuint position_loc = glGetAttribLocation(program, "a_position");
+ GLTestHelper::SetupUnitQuad(position_loc);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ uint8 expected_color[] = { 0, 0, 255, 255, };
+ EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected_color));
+ GLTestHelper::CheckGLError("no errors", __LINE__);
+}
+
+TEST_F(GLProgramTest, UniformsInCurrentProgram) {
+ static const char* v_shader_str = SHADER(
+ attribute vec4 a_position;
+ void main()
+ {
+ gl_Position = a_position;
+ }
+ );
+ static const char* f_shader_str = SHADER(
+ precision mediump float;
+ uniform vec4 u_color;
+ void main()
+ {
+ gl_FragColor = u_color;;
+ }
+ );
+
+ // Load the program.
+ GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
+ glUseProgram(program);
+
+ // Relink.
+ glLinkProgram(program);
+
+ // This test will fail on NVidia Linux if not worked around.
+ GLint color_location = glGetUniformLocation(program, "u_color");
+ glUniform4f(color_location, 0.0f, 0.0f, 1.0f, 1.0f);
+
+ // We specifically don't call UseProgram again.
+ GLuint position_loc = glGetAttribLocation(program, "a_position");
+ GLTestHelper::SetupUnitQuad(position_loc);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ uint8 expected_color[] = { 0, 0, 255, 255, };
+ EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, 1, 1, 0, expected_color));
+ GLTestHelper::CheckGLError("no errors", __LINE__);
+}
+
+} // namespace gpu
+
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 83a7815..ce3fdec 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -250,6 +250,7 @@
'command_buffer/tests/gl_manager.cc',
'command_buffer/tests/gl_manager.h',
'command_buffer/tests/gl_pointcoord_unittest.cc',
+ 'command_buffer/tests/gl_program_unittests.cc',
'command_buffer/tests/gl_tests_main.cc',
'command_buffer/tests/gl_test_utils.cc',
'command_buffer/tests/gl_test_utils.h',