Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Unified Diff: gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc

Issue 1309743005: command_buffer: Implement EXT_blend_func_extended (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@new-05-path-fragment-input-gen
Patch Set: rebase Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/command_buffer/service/test_helper.cc ('k') | gpu/gpu.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc
diff --git a/gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc b/gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d2f01ab58c4ec09f4df7f7f4448dae569edafb89
--- /dev/null
+++ b/gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc
@@ -0,0 +1,653 @@
+// Copyright (c) 2015 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 <GLES2/gl2extchromium.h>
+#include <GLES3/gl3.h>
+
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
+#include "gpu/command_buffer/service/gpu_switches.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"
+#include "ui/gl/gl_switches.h"
+
+#define SHADER(Src) #Src
+#define BFE_SHADER(Src) "#extension GL_EXT_blend_func_extended : require\n" #Src
+
+namespace {
+// Partial implementation of weight function for GLES 2 blend equation that
+// is dual-source aware.
+template <int factor, int index>
+float Weight(float /*dst*/[4], float src[4], float src1[4]) {
+ if (factor == GL_SRC_COLOR)
+ return src[index];
+ if (factor == GL_SRC_ALPHA)
+ return src[3];
+ if (factor == GL_SRC1_COLOR_EXT)
+ return src1[index];
+ if (factor == GL_SRC1_ALPHA_EXT)
+ return src1[3];
+ if (factor == GL_ONE_MINUS_SRC1_COLOR_EXT)
+ return 1.0f - src1[index];
+ if (factor == GL_ONE_MINUS_SRC1_ALPHA_EXT)
+ return 1.0f - src1[3];
+ return 0.0f;
+}
+
+// Implementation of GLES 2 blend equation that is dual-source aware.
+template <int RGBs, int RGBd, int As, int Ad>
+void BlendEquationFuncAdd(float dst[4],
+ float src[4],
+ float src1[4],
+ uint8 result[4]) {
+ float r[4];
+ r[0] = src[0] * Weight<RGBs, 0>(dst, src, src1) +
+ dst[0] * Weight<RGBd, 0>(dst, src, src1);
+ r[1] = src[1] * Weight<RGBs, 1>(dst, src, src1) +
+ dst[1] * Weight<RGBd, 1>(dst, src, src1);
+ r[2] = src[2] * Weight<RGBs, 2>(dst, src, src1) +
+ dst[2] * Weight<RGBd, 2>(dst, src, src1);
+ r[3] = src[3] * Weight<As, 3>(dst, src, src1) +
+ dst[3] * Weight<Ad, 3>(dst, src, src1);
+ for (int i = 0; i < 4; ++i) {
+ result[i] = static_cast<uint8>(
+ std::floor(std::max(0.0f, std::min(1.0f, r[i])) * 255.0f));
+ }
+}
+
+} // namespace
+
+namespace gpu {
+
+class EXTBlendFuncExtendedTest : public testing::Test {
+ public:
+ protected:
+ void SetUp() override { gl_.Initialize(GLManager::Options()); }
+
+ void TearDown() override { gl_.Destroy(); }
+ bool IsApplicable() const {
+ return GLTestHelper::HasExtension("GL_EXT_blend_func_extended");
+ }
+ GLManager gl_;
+};
+
+TEST_F(EXTBlendFuncExtendedTest, TestMaxDualSourceDrawBuffers) {
+ if (!IsApplicable())
+ return;
+
+ GLint maxDualSourceDrawBuffers = 0;
+ glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers);
+ EXPECT_GT(maxDualSourceDrawBuffers, 0);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+class EXTBlendFuncExtendedDrawTest : public testing::TestWithParam<bool> {
+ public:
+ static const GLsizei kWidth = 100;
+ static const GLsizei kHeight = 100;
+ EXTBlendFuncExtendedDrawTest() : program_(0) {}
+
+ protected:
+ void SetUp() override {
+ GLManager::Options options;
+ options.size = gfx::Size(kWidth, kHeight);
+ options.force_shader_name_hashing = GetParam();
+ base::CommandLine command_line(*base::CommandLine::ForCurrentProcess());
+ gl_.InitializeWithCommandLine(options, &command_line);
+ }
+
+ bool IsApplicable() const {
+ return GLTestHelper::HasExtension("GL_EXT_blend_func_extended");
+ }
+
+ virtual const char* GetVertexShader() {
+ // clang-format off
+ static const char* kVertexShader =
+ SHADER(
+ attribute vec4 position;
+ void main() {
+ gl_Position = position;
+ });
+ // clang-format on
+ return kVertexShader;
+ }
+
+ void CreateProgramWithFragmentShader(const char* fragment_shader_str) {
+ GLuint vertex_shader =
+ GLTestHelper::LoadShader(GL_VERTEX_SHADER, GetVertexShader());
+ GLuint fragment_shader =
+ GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, fragment_shader_str);
+ ASSERT_NE(0u, vertex_shader);
+ ASSERT_NE(0u, fragment_shader);
+ program_ = glCreateProgram();
+ ASSERT_NE(0u, program_);
+ glAttachShader(program_, vertex_shader);
+ glAttachShader(program_, fragment_shader);
+ glDeleteShader(vertex_shader);
+ glDeleteShader(fragment_shader);
+ }
+
+ testing::AssertionResult LinkProgram() {
+ glLinkProgram(program_);
+ GLint linked = 0;
+ glGetProgramiv(program_, GL_LINK_STATUS, &linked);
+ if (linked == 0) {
+ char buffer[1024];
+ GLsizei length = 0;
+ glGetProgramInfoLog(program_, sizeof(buffer), &length, buffer);
+ std::string log(buffer, length);
+ return testing::AssertionFailure() << "Error linking program: " << log;
+ }
+ glUseProgram(program_);
+ position_loc_ = glGetAttribLocation(program_, "position");
+ src_loc_ = glGetUniformLocation(program_, "src");
+ src1_loc_ = glGetUniformLocation(program_, "src1");
+ return testing::AssertionSuccess();
+ }
+
+ void TearDown() override {
+ if (program_ != 0)
+ glDeleteProgram(program_);
+ gl_.Destroy();
+ }
+
+ void DrawAndVerify() {
+ float kDst[4] = {0.5f, 0.5f, 0.5f, 0.5f};
+ float kSrc[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ float kSrc1[4] = {0.3f, 0.6f, 0.9f, 0.7f};
+
+ glUniform4f(src_loc_, kSrc[0], kSrc[1], kSrc[2], kSrc[3]);
+ glUniform4f(src1_loc_, kSrc1[0], kSrc1[1], kSrc1[2], kSrc1[3]);
+
+ GLTestHelper::SetupUnitQuad(position_loc_);
+
+ glEnable(GL_BLEND);
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFuncSeparate(GL_SRC1_COLOR_EXT, GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC1_COLOR_EXT,
+ GL_ONE_MINUS_SRC1_ALPHA_EXT);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ // Draw one triangle (bottom left half).
+ glViewport(0, 0, kWidth, kHeight);
+ glClearColor(kDst[0], kDst[1], kDst[2], kDst[3]);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ // Verify.
+ uint8 color[4];
+ BlendEquationFuncAdd<GL_SRC1_COLOR_EXT, GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC1_COLOR_EXT,
+ GL_ONE_MINUS_SRC1_ALPHA_EXT>(kDst, kSrc, kSrc1, color);
+
+ EXPECT_TRUE(GLTestHelper::CheckPixels(kWidth / 4, (3 * kHeight) / 4, 1, 1,
+ 1, color));
+ EXPECT_TRUE(GLTestHelper::CheckPixels(kWidth - 1, 0, 1, 1, 1, color));
+ }
+
+ protected:
+ GLuint program_;
+ GLuint position_loc_;
+ GLuint src_loc_;
+ GLuint src1_loc_;
+ GLManager gl_;
+};
+
+TEST_P(EXTBlendFuncExtendedDrawTest, ESSL1FragColor) {
+ if (!IsApplicable())
+ return;
+ // clang-format off
+ static const char* kFragColorShader =
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ void main() {
+ gl_FragColor = src;
+ gl_SecondaryFragColorEXT = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragColorShader);
+ LinkProgram();
+ DrawAndVerify();
+}
+
+TEST_P(EXTBlendFuncExtendedDrawTest, ESSL1FragData) {
+ if (!IsApplicable())
+ return;
+ // clang-format off
+ static const char* kFragDataShader =
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ void main() {
+ gl_FragData[0] = src;
+ gl_SecondaryFragDataEXT[0] = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragDataShader);
+ LinkProgram();
+ DrawAndVerify();
+}
+
+class EXTBlendFuncExtendedES3DrawTest : public EXTBlendFuncExtendedDrawTest {
+ protected:
+ void SetUp() override {
+ GLManager::Options options;
+ options.size = gfx::Size(kWidth, kHeight);
+ options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
+ options.force_shader_name_hashing = GetParam();
+ base::CommandLine command_line(*base::CommandLine::ForCurrentProcess());
+ command_line.AppendSwitch(switches::kEnableUnsafeES3APIs);
+ gl_.InitializeWithCommandLine(options, &command_line);
+ }
+ bool IsApplicable() const {
+ return gl_.IsInitialized() && EXTBlendFuncExtendedDrawTest::IsApplicable();
+ }
+ const char* GetVertexShader() override {
+ // clang-format off
+ static const char* kVertexShader =
+ "#version 300 es\n"
+ SHADER(
+ in vec4 position;
+ void main() {
+ gl_Position = position;
+ });
+ // clang-format on
+ return kVertexShader;
+ }
+};
+
+TEST_P(EXTBlendFuncExtendedES3DrawTest, ESSL3Var) {
+ if (!IsApplicable())
+ return;
+ // clang-format off
+ static const char* kFragColorShader =
+ "#version 300 es\n"
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ out vec4 FragColor;
+ out vec4 SecondaryFragColor;
+ void main() {
+ FragColor = src;
+ SecondaryFragColor = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragColorShader);
+ glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor");
+ LinkProgram();
+ DrawAndVerify();
+}
+
+TEST_P(EXTBlendFuncExtendedES3DrawTest, ESSL3BindArrayWithSimpleName) {
+ if (!IsApplicable())
+ return;
+ // clang-format off
+ static const char* kFragDataShader =
+ "#version 300 es\n"
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ out vec4 FragData[1];
+ out vec4 SecondaryFragData[1];
+ void main() {
+ FragData[0] = src;
+ SecondaryFragData[0] = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragDataShader);
+ glBindFragDataLocationEXT(program_, 0, "FragData");
+ glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData");
+ LinkProgram();
+ DrawAndVerify();
+}
+
+TEST_P(EXTBlendFuncExtendedES3DrawTest, ESSL3BindSimpleVarAsArrayNoBind) {
+ if (!IsApplicable())
+ return;
+ // clang-format off
+ static const char* kFragDataShader =
+ "#version 300 es\n"
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ out vec4 FragData;
+ out vec4 SecondaryFragData;
+ void main() {
+ FragData = src;
+ SecondaryFragData = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragDataShader);
+ glBindFragDataLocationEXT(program_, 0, "FragData[0]");
+ glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData[0]");
+ // Does not fail, since FragData[0] and SecondaryFragData[0] do not exist.
+ EXPECT_TRUE(LinkProgram());
+
+ EXPECT_EQ(-1, glGetFragDataLocation(program_, "FragData[0]"));
+ EXPECT_EQ(0, glGetFragDataLocation(program_, "FragData"));
+ EXPECT_EQ(1, glGetFragDataLocation(program_, "SecondaryFragData"));
+ // Did not bind index.
+ EXPECT_EQ(0, glGetFragDataIndexEXT(program_, "SecondaryFragData"));
+
+ glBindFragDataLocationEXT(program_, 0, "FragData");
+ glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData");
+ EXPECT_TRUE(LinkProgram());
+ DrawAndVerify();
+}
+
+TEST_P(EXTBlendFuncExtendedES3DrawTest, ESSL3BindArrayAsArray) {
+ if (!IsApplicable())
+ return;
+ // clang-format off
+ static const char* kFragDataShader =
+ "#version 300 es\n"
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ out vec4 FragData[1];
+ out vec4 SecondaryFragData[1];
+ void main() {
+ FragData[0] = src;
+ SecondaryFragData[0] = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragDataShader);
+ glBindFragDataLocationEXT(program_, 0, "FragData[0]");
+ glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData[0]");
+ LinkProgram();
+ DrawAndVerify();
+}
+
+TEST_P(EXTBlendFuncExtendedES3DrawTest, ES3Getters) {
+ if (!IsApplicable())
+ return;
+ // clang-format off
+ static const char* kFragColorShader =
+ "#version 300 es\n"
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ out vec4 FragColor;
+ out vec4 SecondaryFragColor;
+ void main() {
+ FragColor = src;
+ SecondaryFragColor = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragColorShader);
+ glBindFragDataLocationEXT(program_, 0, "FragColor");
+ glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor");
+
+ // Getters return GL error before linking.
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ GLint location = glGetFragDataLocation(program_, "FragColor");
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+ GLint index = glGetFragDataIndexEXT(program_, "FragColor");
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+ location = glGetFragDataLocation(program_, "SecondaryFragColor");
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+ index = glGetFragDataIndexEXT(program_, "SecondaryFragColor");
+ EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
+ LinkProgram();
+
+ // Getters return location and index after linking. Run twice to confirm that
+ // setters do not affect the getters until next link.
+ for (int i = 0; i < 2; ++i) {
+ SCOPED_TRACE(testing::Message() << "Testing getters after link, iteration "
+ << i);
+
+ location = glGetFragDataLocation(program_, "FragColor");
+ EXPECT_EQ(0, location);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ index = glGetFragDataIndexEXT(program_, "FragColor");
+ EXPECT_EQ(0, index);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ location = glGetFragDataLocation(program_, "SecondaryFragColor");
+ EXPECT_EQ(0, location);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ index = glGetFragDataIndexEXT(program_, "SecondaryFragColor");
+ EXPECT_EQ(1, index);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ // The calls should not affect the getters until re-linking.
+ glBindFragDataLocationEXT(program_, 0, "SecondaryFragColor");
+ glBindFragDataLocationIndexedEXT(program_, 0, 1, "FragColor");
+ }
+
+ LinkProgram();
+
+ location = glGetFragDataLocation(program_, "FragColor");
+ EXPECT_EQ(0, location);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ index = glGetFragDataIndexEXT(program_, "FragColor");
+ EXPECT_EQ(1, index);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ location = glGetFragDataLocation(program_, "SecondaryFragColor");
+ EXPECT_EQ(0, location);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ index = glGetFragDataIndexEXT(program_, "SecondaryFragColor");
+ EXPECT_EQ(0, index);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ // Unknown colors return location -1, index -1.
+ location = glGetFragDataLocation(program_, "UnknownColor");
+ EXPECT_EQ(-1, location);
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ index = glGetFragDataIndexEXT(program_, "UnknownColor");
+ EXPECT_EQ(-1, index);
+
+ // Reset the settings and verify that the driver gets them correct.
+ glBindFragDataLocationEXT(program_, 0, "FragColor");
+ glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor");
+ LinkProgram();
+ DrawAndVerify();
+}
+
+// Test that tests glBindFragDataLocationEXT, glBindFragDataLocationIndexedEXT,
+// glGetFragDataLocation, glGetFragDataIndexEXT work correctly with
+// GLSL array output variables. The output variable can be bound by
+// referring to the variable name with or without the first element array
+// accessor. The getters can query location of the individual elements in
+// the array. The test does not actually use the base test drawing,
+// since the drivers at the time of writing do not support multiple
+// buffers and dual source blending.
+TEST_P(EXTBlendFuncExtendedES3DrawTest, ES3GettersArray) {
+ if (!IsApplicable())
+ return;
+ const GLint kTestArraySize = 2;
+ const GLint kFragData0Location = 2;
+ const GLint kFragData1Location = 1;
+ const GLint kUnusedLocation = 5;
+
+ // The test binds kTestArraySize -sized array to location 1 for test purposes.
+ // The GL_MAX_DRAW_BUFFERS must be > kTestArraySize, since an
+ // array will be bound to continuous locations, starting from the first
+ // location.
+ GLint maxDrawBuffers = 0;
+ glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers);
+ EXPECT_LT(kTestArraySize, maxDrawBuffers);
+
+ // clang-format off
+ static const char* kFragColorShader =
+ "#version 300 es\n"
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ out vec4 FragData[2];
+ void main() {
+ FragData[0] = src;
+ FragData[1] = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragColorShader);
+
+ for (int testcase = 0; testcase < 4; ++testcase) {
+ if (testcase == 0) {
+ glBindFragDataLocationEXT(program_, kUnusedLocation, "FragData[0]");
+ glBindFragDataLocationEXT(program_, kFragData0Location, "FragData");
+ glBindFragDataLocationEXT(program_, kFragData1Location, "FragData[1]");
+ } else if (testcase == 1) {
+ glBindFragDataLocationEXT(program_, kUnusedLocation, "FragData");
+ glBindFragDataLocationEXT(program_, kFragData0Location, "FragData[0]");
+ glBindFragDataLocationEXT(program_, kFragData1Location, "FragData[1]");
+ } else if (testcase == 2) {
+ glBindFragDataLocationIndexedEXT(program_, kUnusedLocation, 0,
+ "FragData[0]");
+ glBindFragDataLocationIndexedEXT(program_, kFragData0Location, 0,
+ "FragData");
+ glBindFragDataLocationIndexedEXT(program_, kFragData1Location, 0,
+ "FragData[1]");
+ } else if (testcase == 3) {
+ glBindFragDataLocationIndexedEXT(program_, kUnusedLocation, 0,
+ "FragData");
+ glBindFragDataLocationIndexedEXT(program_, kFragData0Location, 0,
+ "FragData[0]");
+ glBindFragDataLocationIndexedEXT(program_, kFragData1Location, 0,
+ "FragData[1]");
+ }
+
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ LinkProgram();
+ EXPECT_EQ(kFragData0Location, glGetFragDataLocation(program_, "FragData"));
+ EXPECT_EQ(0, glGetFragDataIndexEXT(program_, "FragData"));
+ EXPECT_EQ(kFragData0Location,
+ glGetFragDataLocation(program_, "FragData[0]"));
+ EXPECT_EQ(0, glGetFragDataIndexEXT(program_, "FragData[0]"));
+ EXPECT_EQ(kFragData1Location,
+ glGetFragDataLocation(program_, "FragData[1]"));
+ EXPECT_EQ(0, glGetFragDataIndexEXT(program_, "FragData[1]"));
+
+ // Index bigger than the GLSL variable array length does not find anything.
+ EXPECT_EQ(-1, glGetFragDataLocation(program_, "FragData[3]"));
+ }
+}
+
+// Test that tests glBindFragDataLocationEXT, glBindFragDataLocationIndexedEXT
+// conflicts
+// with GLSL output variables.
+TEST_P(EXTBlendFuncExtendedES3DrawTest, ES3Conflicts) {
+ if (!IsApplicable())
+ return;
+ const GLint kTestArraySize = 2;
+ const GLint kColorName0Location = 0;
+ const GLint kColorName1Location = 1;
+ GLint maxDrawBuffers = 0;
+ glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers);
+ EXPECT_LT(kTestArraySize, maxDrawBuffers);
+
+ // clang-format off
+ static const char* kFragColorShader =
+ "#version 300 es\n"
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ out vec4 FragData0;
+ out vec4 FragData1;
+ void main() {
+ FragData0 = src;
+ FragData1 = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragColorShader);
+
+ glBindFragDataLocationEXT(program_, kColorName0Location, "FragData0");
+ glBindFragDataLocationEXT(program_, kColorName0Location, "FragData1");
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ EXPECT_FALSE(LinkProgram());
+
+ glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 0,
+ "FragData0");
+ glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 0,
+ "FragData1");
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ EXPECT_FALSE(LinkProgram());
+
+ glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 1,
+ "FragData0");
+ glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 1,
+ "FragData1");
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ EXPECT_FALSE(LinkProgram());
+
+ // Test that correct binding actually works.
+ glBindFragDataLocationEXT(program_, kColorName0Location, "FragData0");
+ glBindFragDataLocationEXT(program_, kColorName1Location, "FragData1");
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ EXPECT_TRUE(LinkProgram());
+
+ glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 0,
+ "FragData0");
+ glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 1,
+ "FragData1");
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ EXPECT_TRUE(LinkProgram());
+}
+
+// Test that tests glBindFragDataLocationEXT conflicts
+// with GLSL array output variables.
+TEST_P(EXTBlendFuncExtendedES3DrawTest, ES3ConflictsArray) {
+ if (!IsApplicable())
+ return;
+ const GLint kTestArraySize = 2;
+ const GLint kColorName0Location = 0;
+ const GLint kColorName1Location = 1;
+ const GLint kUnusedLocation = 5;
+ GLint maxDrawBuffers = 0;
+ glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers);
+ EXPECT_LT(kTestArraySize, maxDrawBuffers);
+
+ // clang-format off
+ static const char* kFragColorShader =
+ "#version 300 es\n"
+ BFE_SHADER(
+ precision mediump float;
+ uniform vec4 src;
+ uniform vec4 src1;
+ out vec4 FragData[2];
+ void main() {
+ FragData[0] = src;
+ FragData[1] = src1;
+ });
+ // clang-format on
+ CreateProgramWithFragmentShader(kFragColorShader);
+
+ glBindFragDataLocationEXT(program_, kColorName1Location, "FragData");
+ glBindFragDataLocationEXT(program_, kColorName1Location, "FragData[1]");
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ EXPECT_FALSE(LinkProgram());
+ glBindFragDataLocationEXT(program_, kUnusedLocation, "FragData");
+ glBindFragDataLocationEXT(program_, kColorName1Location, "FragData[0]");
+ glBindFragDataLocationEXT(program_, kColorName1Location, "FragData[1]");
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ EXPECT_FALSE(LinkProgram());
+ // Test that binding actually works.
+ glBindFragDataLocationEXT(program_, kColorName0Location, "FragData[0]");
+ glBindFragDataLocationEXT(program_, kColorName1Location, "FragData[1]");
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ EXPECT_TRUE(LinkProgram());
+}
+
+INSTANTIATE_TEST_CASE_P(TranslatorVariants,
+ EXTBlendFuncExtendedDrawTest,
+ ::testing::Bool());
+
+INSTANTIATE_TEST_CASE_P(TranslatorVariants,
+ EXTBlendFuncExtendedES3DrawTest,
+ ::testing::Bool());
+
+} // namespace gpu
« no previous file with comments | « gpu/command_buffer/service/test_helper.cc ('k') | gpu/gpu.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698