OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <GLES2/gl2.h> |
| 6 #include <GLES2/gl2ext.h> |
| 7 #include <GLES2/gl2extchromium.h> |
| 8 #include <GLES3/gl3.h> |
| 9 |
| 10 #include "base/command_line.h" |
| 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "gpu/command_buffer/service/gpu_switches.h" |
| 13 #include "gpu/command_buffer/tests/gl_manager.h" |
| 14 #include "gpu/command_buffer/tests/gl_test_utils.h" |
| 15 #include "testing/gmock/include/gmock/gmock.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "ui/gl/gl_switches.h" |
| 18 |
| 19 #define SHADER(Src) #Src |
| 20 #define BFE_SHADER(Src) "#extension GL_EXT_blend_func_extended : require\n" #Src |
| 21 |
| 22 namespace { |
| 23 // Partial implementation of weight function for GLES 2 blend equation that |
| 24 // is dual-source aware. |
| 25 template <int factor, int index> |
| 26 float Weight(float /*dst*/[4], float src[4], float src1[4]) { |
| 27 if (factor == GL_SRC_COLOR) |
| 28 return src[index]; |
| 29 if (factor == GL_SRC_ALPHA) |
| 30 return src[3]; |
| 31 if (factor == GL_SRC1_COLOR_EXT) |
| 32 return src1[index]; |
| 33 if (factor == GL_SRC1_ALPHA_EXT) |
| 34 return src1[3]; |
| 35 if (factor == GL_ONE_MINUS_SRC1_COLOR_EXT) |
| 36 return 1.0f - src1[index]; |
| 37 if (factor == GL_ONE_MINUS_SRC1_ALPHA_EXT) |
| 38 return 1.0f - src1[3]; |
| 39 return 0.0f; |
| 40 } |
| 41 |
| 42 // Implementation of GLES 2 blend equation that is dual-source aware. |
| 43 template <int RGBs, int RGBd, int As, int Ad> |
| 44 void BlendEquationFuncAdd(float dst[4], |
| 45 float src[4], |
| 46 float src1[4], |
| 47 uint8 result[4]) { |
| 48 float r[4]; |
| 49 r[0] = src[0] * Weight<RGBs, 0>(dst, src, src1) + |
| 50 dst[0] * Weight<RGBd, 0>(dst, src, src1); |
| 51 r[1] = src[1] * Weight<RGBs, 1>(dst, src, src1) + |
| 52 dst[1] * Weight<RGBd, 1>(dst, src, src1); |
| 53 r[2] = src[2] * Weight<RGBs, 2>(dst, src, src1) + |
| 54 dst[2] * Weight<RGBd, 2>(dst, src, src1); |
| 55 r[3] = src[3] * Weight<As, 3>(dst, src, src1) + |
| 56 dst[3] * Weight<Ad, 3>(dst, src, src1); |
| 57 for (int i = 0; i < 4; ++i) { |
| 58 result[i] = static_cast<uint8>( |
| 59 std::floor(std::max(0.0f, std::min(1.0f, r[i])) * 255.0f)); |
| 60 } |
| 61 } |
| 62 |
| 63 } // namespace |
| 64 |
| 65 namespace gpu { |
| 66 |
| 67 class EXTBlendFuncExtendedTest : public testing::Test { |
| 68 public: |
| 69 protected: |
| 70 void SetUp() override { gl_.Initialize(GLManager::Options()); } |
| 71 |
| 72 void TearDown() override { gl_.Destroy(); } |
| 73 bool IsApplicable() const { |
| 74 return GLTestHelper::HasExtension("GL_EXT_blend_func_extended"); |
| 75 } |
| 76 GLManager gl_; |
| 77 }; |
| 78 |
| 79 TEST_F(EXTBlendFuncExtendedTest, TestMaxDualSourceDrawBuffers) { |
| 80 if (!IsApplicable()) |
| 81 return; |
| 82 |
| 83 GLint maxDualSourceDrawBuffers = 0; |
| 84 glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers); |
| 85 EXPECT_GT(maxDualSourceDrawBuffers, 0); |
| 86 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 87 } |
| 88 |
| 89 class EXTBlendFuncExtendedDrawTest : public testing::TestWithParam<bool> { |
| 90 public: |
| 91 static const GLsizei kWidth = 100; |
| 92 static const GLsizei kHeight = 100; |
| 93 EXTBlendFuncExtendedDrawTest() : program_(0) {} |
| 94 |
| 95 protected: |
| 96 void SetUp() override { |
| 97 GLManager::Options options; |
| 98 options.size = gfx::Size(kWidth, kHeight); |
| 99 options.force_shader_name_hashing = GetParam(); |
| 100 base::CommandLine command_line(*base::CommandLine::ForCurrentProcess()); |
| 101 gl_.InitializeWithCommandLine(options, &command_line); |
| 102 } |
| 103 |
| 104 bool IsApplicable() const { |
| 105 return GLTestHelper::HasExtension("GL_EXT_blend_func_extended"); |
| 106 } |
| 107 |
| 108 virtual const char* GetVertexShader() { |
| 109 // clang-format off |
| 110 static const char* kVertexShader = |
| 111 SHADER( |
| 112 attribute vec4 position; |
| 113 void main() { |
| 114 gl_Position = position; |
| 115 }); |
| 116 // clang-format on |
| 117 return kVertexShader; |
| 118 } |
| 119 |
| 120 void CreateProgramWithFragmentShader(const char* fragment_shader_str) { |
| 121 GLuint vertex_shader = |
| 122 GLTestHelper::LoadShader(GL_VERTEX_SHADER, GetVertexShader()); |
| 123 GLuint fragment_shader = |
| 124 GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, fragment_shader_str); |
| 125 ASSERT_NE(0u, vertex_shader); |
| 126 ASSERT_NE(0u, fragment_shader); |
| 127 program_ = glCreateProgram(); |
| 128 ASSERT_NE(0u, program_); |
| 129 glAttachShader(program_, vertex_shader); |
| 130 glAttachShader(program_, fragment_shader); |
| 131 glDeleteShader(vertex_shader); |
| 132 glDeleteShader(fragment_shader); |
| 133 } |
| 134 |
| 135 testing::AssertionResult LinkProgram() { |
| 136 glLinkProgram(program_); |
| 137 GLint linked = 0; |
| 138 glGetProgramiv(program_, GL_LINK_STATUS, &linked); |
| 139 if (linked == 0) { |
| 140 char buffer[1024]; |
| 141 GLsizei length = 0; |
| 142 glGetProgramInfoLog(program_, sizeof(buffer), &length, buffer); |
| 143 std::string log(buffer, length); |
| 144 return testing::AssertionFailure() << "Error linking program: " << log; |
| 145 } |
| 146 glUseProgram(program_); |
| 147 position_loc_ = glGetAttribLocation(program_, "position"); |
| 148 src_loc_ = glGetUniformLocation(program_, "src"); |
| 149 src1_loc_ = glGetUniformLocation(program_, "src1"); |
| 150 return testing::AssertionSuccess(); |
| 151 } |
| 152 |
| 153 void TearDown() override { |
| 154 if (program_ != 0) |
| 155 glDeleteProgram(program_); |
| 156 gl_.Destroy(); |
| 157 } |
| 158 |
| 159 void DrawAndVerify() { |
| 160 float kDst[4] = {0.5f, 0.5f, 0.5f, 0.5f}; |
| 161 float kSrc[4] = {1.0f, 1.0f, 1.0f, 1.0f}; |
| 162 float kSrc1[4] = {0.3f, 0.6f, 0.9f, 0.7f}; |
| 163 |
| 164 glUniform4f(src_loc_, kSrc[0], kSrc[1], kSrc[2], kSrc[3]); |
| 165 glUniform4f(src1_loc_, kSrc1[0], kSrc1[1], kSrc1[2], kSrc1[3]); |
| 166 |
| 167 GLTestHelper::SetupUnitQuad(position_loc_); |
| 168 |
| 169 glEnable(GL_BLEND); |
| 170 glBlendEquation(GL_FUNC_ADD); |
| 171 glBlendFuncSeparate(GL_SRC1_COLOR_EXT, GL_SRC_ALPHA, |
| 172 GL_ONE_MINUS_SRC1_COLOR_EXT, |
| 173 GL_ONE_MINUS_SRC1_ALPHA_EXT); |
| 174 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 175 |
| 176 // Draw one triangle (bottom left half). |
| 177 glViewport(0, 0, kWidth, kHeight); |
| 178 glClearColor(kDst[0], kDst[1], kDst[2], kDst[3]); |
| 179 glClear(GL_COLOR_BUFFER_BIT); |
| 180 glDrawArrays(GL_TRIANGLES, 0, 6); |
| 181 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 182 // Verify. |
| 183 uint8 color[4]; |
| 184 BlendEquationFuncAdd<GL_SRC1_COLOR_EXT, GL_SRC_ALPHA, |
| 185 GL_ONE_MINUS_SRC1_COLOR_EXT, |
| 186 GL_ONE_MINUS_SRC1_ALPHA_EXT>(kDst, kSrc, kSrc1, color); |
| 187 |
| 188 EXPECT_TRUE(GLTestHelper::CheckPixels(kWidth / 4, (3 * kHeight) / 4, 1, 1, |
| 189 1, color)); |
| 190 EXPECT_TRUE(GLTestHelper::CheckPixels(kWidth - 1, 0, 1, 1, 1, color)); |
| 191 } |
| 192 |
| 193 protected: |
| 194 GLuint program_; |
| 195 GLuint position_loc_; |
| 196 GLuint src_loc_; |
| 197 GLuint src1_loc_; |
| 198 GLManager gl_; |
| 199 }; |
| 200 |
| 201 TEST_P(EXTBlendFuncExtendedDrawTest, ESSL1FragColor) { |
| 202 if (!IsApplicable()) |
| 203 return; |
| 204 // clang-format off |
| 205 static const char* kFragColorShader = |
| 206 BFE_SHADER( |
| 207 precision mediump float; |
| 208 uniform vec4 src; |
| 209 uniform vec4 src1; |
| 210 void main() { |
| 211 gl_FragColor = src; |
| 212 gl_SecondaryFragColorEXT = src1; |
| 213 }); |
| 214 // clang-format on |
| 215 CreateProgramWithFragmentShader(kFragColorShader); |
| 216 LinkProgram(); |
| 217 DrawAndVerify(); |
| 218 } |
| 219 |
| 220 TEST_P(EXTBlendFuncExtendedDrawTest, ESSL1FragData) { |
| 221 if (!IsApplicable()) |
| 222 return; |
| 223 // clang-format off |
| 224 static const char* kFragDataShader = |
| 225 BFE_SHADER( |
| 226 precision mediump float; |
| 227 uniform vec4 src; |
| 228 uniform vec4 src1; |
| 229 void main() { |
| 230 gl_FragData[0] = src; |
| 231 gl_SecondaryFragDataEXT[0] = src1; |
| 232 }); |
| 233 // clang-format on |
| 234 CreateProgramWithFragmentShader(kFragDataShader); |
| 235 LinkProgram(); |
| 236 DrawAndVerify(); |
| 237 } |
| 238 |
| 239 class EXTBlendFuncExtendedES3DrawTest : public EXTBlendFuncExtendedDrawTest { |
| 240 protected: |
| 241 void SetUp() override { |
| 242 GLManager::Options options; |
| 243 options.size = gfx::Size(kWidth, kHeight); |
| 244 options.context_type = gles2::CONTEXT_TYPE_OPENGLES3; |
| 245 options.force_shader_name_hashing = GetParam(); |
| 246 base::CommandLine command_line(*base::CommandLine::ForCurrentProcess()); |
| 247 command_line.AppendSwitch(switches::kEnableUnsafeES3APIs); |
| 248 gl_.InitializeWithCommandLine(options, &command_line); |
| 249 } |
| 250 bool IsApplicable() const { |
| 251 return gl_.IsInitialized() && EXTBlendFuncExtendedDrawTest::IsApplicable(); |
| 252 } |
| 253 const char* GetVertexShader() override { |
| 254 // clang-format off |
| 255 static const char* kVertexShader = |
| 256 "#version 300 es\n" |
| 257 SHADER( |
| 258 in vec4 position; |
| 259 void main() { |
| 260 gl_Position = position; |
| 261 }); |
| 262 // clang-format on |
| 263 return kVertexShader; |
| 264 } |
| 265 }; |
| 266 |
| 267 TEST_P(EXTBlendFuncExtendedES3DrawTest, ESSL3Var) { |
| 268 if (!IsApplicable()) |
| 269 return; |
| 270 // clang-format off |
| 271 static const char* kFragColorShader = |
| 272 "#version 300 es\n" |
| 273 BFE_SHADER( |
| 274 precision mediump float; |
| 275 uniform vec4 src; |
| 276 uniform vec4 src1; |
| 277 out vec4 FragColor; |
| 278 out vec4 SecondaryFragColor; |
| 279 void main() { |
| 280 FragColor = src; |
| 281 SecondaryFragColor = src1; |
| 282 }); |
| 283 // clang-format on |
| 284 CreateProgramWithFragmentShader(kFragColorShader); |
| 285 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor"); |
| 286 LinkProgram(); |
| 287 DrawAndVerify(); |
| 288 } |
| 289 |
| 290 TEST_P(EXTBlendFuncExtendedES3DrawTest, ESSL3BindArrayWithSimpleName) { |
| 291 if (!IsApplicable()) |
| 292 return; |
| 293 // clang-format off |
| 294 static const char* kFragDataShader = |
| 295 "#version 300 es\n" |
| 296 BFE_SHADER( |
| 297 precision mediump float; |
| 298 uniform vec4 src; |
| 299 uniform vec4 src1; |
| 300 out vec4 FragData[1]; |
| 301 out vec4 SecondaryFragData[1]; |
| 302 void main() { |
| 303 FragData[0] = src; |
| 304 SecondaryFragData[0] = src1; |
| 305 }); |
| 306 // clang-format on |
| 307 CreateProgramWithFragmentShader(kFragDataShader); |
| 308 glBindFragDataLocationEXT(program_, 0, "FragData"); |
| 309 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData"); |
| 310 LinkProgram(); |
| 311 DrawAndVerify(); |
| 312 } |
| 313 |
| 314 TEST_P(EXTBlendFuncExtendedES3DrawTest, ESSL3BindSimpleVarAsArrayNoBind) { |
| 315 if (!IsApplicable()) |
| 316 return; |
| 317 // clang-format off |
| 318 static const char* kFragDataShader = |
| 319 "#version 300 es\n" |
| 320 BFE_SHADER( |
| 321 precision mediump float; |
| 322 uniform vec4 src; |
| 323 uniform vec4 src1; |
| 324 out vec4 FragData; |
| 325 out vec4 SecondaryFragData; |
| 326 void main() { |
| 327 FragData = src; |
| 328 SecondaryFragData = src1; |
| 329 }); |
| 330 // clang-format on |
| 331 CreateProgramWithFragmentShader(kFragDataShader); |
| 332 glBindFragDataLocationEXT(program_, 0, "FragData[0]"); |
| 333 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData[0]"); |
| 334 // Does not fail, since FragData[0] and SecondaryFragData[0] do not exist. |
| 335 EXPECT_TRUE(LinkProgram()); |
| 336 |
| 337 EXPECT_EQ(-1, glGetFragDataLocation(program_, "FragData[0]")); |
| 338 EXPECT_EQ(0, glGetFragDataLocation(program_, "FragData")); |
| 339 EXPECT_EQ(1, glGetFragDataLocation(program_, "SecondaryFragData")); |
| 340 // Did not bind index. |
| 341 EXPECT_EQ(0, glGetFragDataIndexEXT(program_, "SecondaryFragData")); |
| 342 |
| 343 glBindFragDataLocationEXT(program_, 0, "FragData"); |
| 344 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData"); |
| 345 EXPECT_TRUE(LinkProgram()); |
| 346 DrawAndVerify(); |
| 347 } |
| 348 |
| 349 TEST_P(EXTBlendFuncExtendedES3DrawTest, ESSL3BindArrayAsArray) { |
| 350 if (!IsApplicable()) |
| 351 return; |
| 352 // clang-format off |
| 353 static const char* kFragDataShader = |
| 354 "#version 300 es\n" |
| 355 BFE_SHADER( |
| 356 precision mediump float; |
| 357 uniform vec4 src; |
| 358 uniform vec4 src1; |
| 359 out vec4 FragData[1]; |
| 360 out vec4 SecondaryFragData[1]; |
| 361 void main() { |
| 362 FragData[0] = src; |
| 363 SecondaryFragData[0] = src1; |
| 364 }); |
| 365 // clang-format on |
| 366 CreateProgramWithFragmentShader(kFragDataShader); |
| 367 glBindFragDataLocationEXT(program_, 0, "FragData[0]"); |
| 368 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData[0]"); |
| 369 LinkProgram(); |
| 370 DrawAndVerify(); |
| 371 } |
| 372 |
| 373 TEST_P(EXTBlendFuncExtendedES3DrawTest, ES3Getters) { |
| 374 if (!IsApplicable()) |
| 375 return; |
| 376 // clang-format off |
| 377 static const char* kFragColorShader = |
| 378 "#version 300 es\n" |
| 379 BFE_SHADER( |
| 380 precision mediump float; |
| 381 uniform vec4 src; |
| 382 uniform vec4 src1; |
| 383 out vec4 FragColor; |
| 384 out vec4 SecondaryFragColor; |
| 385 void main() { |
| 386 FragColor = src; |
| 387 SecondaryFragColor = src1; |
| 388 }); |
| 389 // clang-format on |
| 390 CreateProgramWithFragmentShader(kFragColorShader); |
| 391 glBindFragDataLocationEXT(program_, 0, "FragColor"); |
| 392 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor"); |
| 393 |
| 394 // Getters return GL error before linking. |
| 395 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 396 GLint location = glGetFragDataLocation(program_, "FragColor"); |
| 397 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); |
| 398 GLint index = glGetFragDataIndexEXT(program_, "FragColor"); |
| 399 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); |
| 400 location = glGetFragDataLocation(program_, "SecondaryFragColor"); |
| 401 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); |
| 402 index = glGetFragDataIndexEXT(program_, "SecondaryFragColor"); |
| 403 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); |
| 404 LinkProgram(); |
| 405 |
| 406 // Getters return location and index after linking. Run twice to confirm that |
| 407 // setters do not affect the getters until next link. |
| 408 for (int i = 0; i < 2; ++i) { |
| 409 SCOPED_TRACE(testing::Message() << "Testing getters after link, iteration " |
| 410 << i); |
| 411 |
| 412 location = glGetFragDataLocation(program_, "FragColor"); |
| 413 EXPECT_EQ(0, location); |
| 414 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 415 index = glGetFragDataIndexEXT(program_, "FragColor"); |
| 416 EXPECT_EQ(0, index); |
| 417 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 418 location = glGetFragDataLocation(program_, "SecondaryFragColor"); |
| 419 EXPECT_EQ(0, location); |
| 420 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 421 index = glGetFragDataIndexEXT(program_, "SecondaryFragColor"); |
| 422 EXPECT_EQ(1, index); |
| 423 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 424 |
| 425 // The calls should not affect the getters until re-linking. |
| 426 glBindFragDataLocationEXT(program_, 0, "SecondaryFragColor"); |
| 427 glBindFragDataLocationIndexedEXT(program_, 0, 1, "FragColor"); |
| 428 } |
| 429 |
| 430 LinkProgram(); |
| 431 |
| 432 location = glGetFragDataLocation(program_, "FragColor"); |
| 433 EXPECT_EQ(0, location); |
| 434 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 435 index = glGetFragDataIndexEXT(program_, "FragColor"); |
| 436 EXPECT_EQ(1, index); |
| 437 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 438 location = glGetFragDataLocation(program_, "SecondaryFragColor"); |
| 439 EXPECT_EQ(0, location); |
| 440 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 441 index = glGetFragDataIndexEXT(program_, "SecondaryFragColor"); |
| 442 EXPECT_EQ(0, index); |
| 443 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 444 |
| 445 // Unknown colors return location -1, index -1. |
| 446 location = glGetFragDataLocation(program_, "UnknownColor"); |
| 447 EXPECT_EQ(-1, location); |
| 448 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 449 index = glGetFragDataIndexEXT(program_, "UnknownColor"); |
| 450 EXPECT_EQ(-1, index); |
| 451 |
| 452 // Reset the settings and verify that the driver gets them correct. |
| 453 glBindFragDataLocationEXT(program_, 0, "FragColor"); |
| 454 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor"); |
| 455 LinkProgram(); |
| 456 DrawAndVerify(); |
| 457 } |
| 458 |
| 459 // Test that tests glBindFragDataLocationEXT, glBindFragDataLocationIndexedEXT, |
| 460 // glGetFragDataLocation, glGetFragDataIndexEXT work correctly with |
| 461 // GLSL array output variables. The output variable can be bound by |
| 462 // referring to the variable name with or without the first element array |
| 463 // accessor. The getters can query location of the individual elements in |
| 464 // the array. The test does not actually use the base test drawing, |
| 465 // since the drivers at the time of writing do not support multiple |
| 466 // buffers and dual source blending. |
| 467 TEST_P(EXTBlendFuncExtendedES3DrawTest, ES3GettersArray) { |
| 468 if (!IsApplicable()) |
| 469 return; |
| 470 const GLint kTestArraySize = 2; |
| 471 const GLint kFragData0Location = 2; |
| 472 const GLint kFragData1Location = 1; |
| 473 const GLint kUnusedLocation = 5; |
| 474 |
| 475 // The test binds kTestArraySize -sized array to location 1 for test purposes. |
| 476 // The GL_MAX_DRAW_BUFFERS must be > kTestArraySize, since an |
| 477 // array will be bound to continuous locations, starting from the first |
| 478 // location. |
| 479 GLint maxDrawBuffers = 0; |
| 480 glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers); |
| 481 EXPECT_LT(kTestArraySize, maxDrawBuffers); |
| 482 |
| 483 // clang-format off |
| 484 static const char* kFragColorShader = |
| 485 "#version 300 es\n" |
| 486 BFE_SHADER( |
| 487 precision mediump float; |
| 488 uniform vec4 src; |
| 489 uniform vec4 src1; |
| 490 out vec4 FragData[2]; |
| 491 void main() { |
| 492 FragData[0] = src; |
| 493 FragData[1] = src1; |
| 494 }); |
| 495 // clang-format on |
| 496 CreateProgramWithFragmentShader(kFragColorShader); |
| 497 |
| 498 for (int testcase = 0; testcase < 4; ++testcase) { |
| 499 if (testcase == 0) { |
| 500 glBindFragDataLocationEXT(program_, kUnusedLocation, "FragData[0]"); |
| 501 glBindFragDataLocationEXT(program_, kFragData0Location, "FragData"); |
| 502 glBindFragDataLocationEXT(program_, kFragData1Location, "FragData[1]"); |
| 503 } else if (testcase == 1) { |
| 504 glBindFragDataLocationEXT(program_, kUnusedLocation, "FragData"); |
| 505 glBindFragDataLocationEXT(program_, kFragData0Location, "FragData[0]"); |
| 506 glBindFragDataLocationEXT(program_, kFragData1Location, "FragData[1]"); |
| 507 } else if (testcase == 2) { |
| 508 glBindFragDataLocationIndexedEXT(program_, kUnusedLocation, 0, |
| 509 "FragData[0]"); |
| 510 glBindFragDataLocationIndexedEXT(program_, kFragData0Location, 0, |
| 511 "FragData"); |
| 512 glBindFragDataLocationIndexedEXT(program_, kFragData1Location, 0, |
| 513 "FragData[1]"); |
| 514 } else if (testcase == 3) { |
| 515 glBindFragDataLocationIndexedEXT(program_, kUnusedLocation, 0, |
| 516 "FragData"); |
| 517 glBindFragDataLocationIndexedEXT(program_, kFragData0Location, 0, |
| 518 "FragData[0]"); |
| 519 glBindFragDataLocationIndexedEXT(program_, kFragData1Location, 0, |
| 520 "FragData[1]"); |
| 521 } |
| 522 |
| 523 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 524 LinkProgram(); |
| 525 EXPECT_EQ(kFragData0Location, glGetFragDataLocation(program_, "FragData")); |
| 526 EXPECT_EQ(0, glGetFragDataIndexEXT(program_, "FragData")); |
| 527 EXPECT_EQ(kFragData0Location, |
| 528 glGetFragDataLocation(program_, "FragData[0]")); |
| 529 EXPECT_EQ(0, glGetFragDataIndexEXT(program_, "FragData[0]")); |
| 530 EXPECT_EQ(kFragData1Location, |
| 531 glGetFragDataLocation(program_, "FragData[1]")); |
| 532 EXPECT_EQ(0, glGetFragDataIndexEXT(program_, "FragData[1]")); |
| 533 |
| 534 // Index bigger than the GLSL variable array length does not find anything. |
| 535 EXPECT_EQ(-1, glGetFragDataLocation(program_, "FragData[3]")); |
| 536 } |
| 537 } |
| 538 |
| 539 // Test that tests glBindFragDataLocationEXT, glBindFragDataLocationIndexedEXT |
| 540 // conflicts |
| 541 // with GLSL output variables. |
| 542 TEST_P(EXTBlendFuncExtendedES3DrawTest, ES3Conflicts) { |
| 543 if (!IsApplicable()) |
| 544 return; |
| 545 const GLint kTestArraySize = 2; |
| 546 const GLint kColorName0Location = 0; |
| 547 const GLint kColorName1Location = 1; |
| 548 GLint maxDrawBuffers = 0; |
| 549 glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers); |
| 550 EXPECT_LT(kTestArraySize, maxDrawBuffers); |
| 551 |
| 552 // clang-format off |
| 553 static const char* kFragColorShader = |
| 554 "#version 300 es\n" |
| 555 BFE_SHADER( |
| 556 precision mediump float; |
| 557 uniform vec4 src; |
| 558 uniform vec4 src1; |
| 559 out vec4 FragData0; |
| 560 out vec4 FragData1; |
| 561 void main() { |
| 562 FragData0 = src; |
| 563 FragData1 = src1; |
| 564 }); |
| 565 // clang-format on |
| 566 CreateProgramWithFragmentShader(kFragColorShader); |
| 567 |
| 568 glBindFragDataLocationEXT(program_, kColorName0Location, "FragData0"); |
| 569 glBindFragDataLocationEXT(program_, kColorName0Location, "FragData1"); |
| 570 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 571 EXPECT_FALSE(LinkProgram()); |
| 572 |
| 573 glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 0, |
| 574 "FragData0"); |
| 575 glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 0, |
| 576 "FragData1"); |
| 577 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 578 EXPECT_FALSE(LinkProgram()); |
| 579 |
| 580 glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 1, |
| 581 "FragData0"); |
| 582 glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 1, |
| 583 "FragData1"); |
| 584 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 585 EXPECT_FALSE(LinkProgram()); |
| 586 |
| 587 // Test that correct binding actually works. |
| 588 glBindFragDataLocationEXT(program_, kColorName0Location, "FragData0"); |
| 589 glBindFragDataLocationEXT(program_, kColorName1Location, "FragData1"); |
| 590 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 591 EXPECT_TRUE(LinkProgram()); |
| 592 |
| 593 glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 0, |
| 594 "FragData0"); |
| 595 glBindFragDataLocationIndexedEXT(program_, kColorName0Location, 1, |
| 596 "FragData1"); |
| 597 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 598 EXPECT_TRUE(LinkProgram()); |
| 599 } |
| 600 |
| 601 // Test that tests glBindFragDataLocationEXT conflicts |
| 602 // with GLSL array output variables. |
| 603 TEST_P(EXTBlendFuncExtendedES3DrawTest, ES3ConflictsArray) { |
| 604 if (!IsApplicable()) |
| 605 return; |
| 606 const GLint kTestArraySize = 2; |
| 607 const GLint kColorName0Location = 0; |
| 608 const GLint kColorName1Location = 1; |
| 609 const GLint kUnusedLocation = 5; |
| 610 GLint maxDrawBuffers = 0; |
| 611 glGetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers); |
| 612 EXPECT_LT(kTestArraySize, maxDrawBuffers); |
| 613 |
| 614 // clang-format off |
| 615 static const char* kFragColorShader = |
| 616 "#version 300 es\n" |
| 617 BFE_SHADER( |
| 618 precision mediump float; |
| 619 uniform vec4 src; |
| 620 uniform vec4 src1; |
| 621 out vec4 FragData[2]; |
| 622 void main() { |
| 623 FragData[0] = src; |
| 624 FragData[1] = src1; |
| 625 }); |
| 626 // clang-format on |
| 627 CreateProgramWithFragmentShader(kFragColorShader); |
| 628 |
| 629 glBindFragDataLocationEXT(program_, kColorName1Location, "FragData"); |
| 630 glBindFragDataLocationEXT(program_, kColorName1Location, "FragData[1]"); |
| 631 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 632 EXPECT_FALSE(LinkProgram()); |
| 633 glBindFragDataLocationEXT(program_, kUnusedLocation, "FragData"); |
| 634 glBindFragDataLocationEXT(program_, kColorName1Location, "FragData[0]"); |
| 635 glBindFragDataLocationEXT(program_, kColorName1Location, "FragData[1]"); |
| 636 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 637 EXPECT_FALSE(LinkProgram()); |
| 638 // Test that binding actually works. |
| 639 glBindFragDataLocationEXT(program_, kColorName0Location, "FragData[0]"); |
| 640 glBindFragDataLocationEXT(program_, kColorName1Location, "FragData[1]"); |
| 641 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 642 EXPECT_TRUE(LinkProgram()); |
| 643 } |
| 644 |
| 645 INSTANTIATE_TEST_CASE_P(TranslatorVariants, |
| 646 EXTBlendFuncExtendedDrawTest, |
| 647 ::testing::Bool()); |
| 648 |
| 649 INSTANTIATE_TEST_CASE_P(TranslatorVariants, |
| 650 EXTBlendFuncExtendedES3DrawTest, |
| 651 ::testing::Bool()); |
| 652 |
| 653 } // namespace gpu |
OLD | NEW |