PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc

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