gl_ext_multisample_compatibility_unittest.cc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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 <stdint.h>
  8. #include <memory>
  9. #include "build/build_config.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/gtest/include/gtest/gtest.h"
  14. #include "ui/gl/gl_context.h"
  15. #define SHADER0(Src) #Src
  16. namespace gpu {
  17. class EXTMultisampleCompatibilityTest : public testing::Test {
  18. public:
  19. protected:
  20. static const GLuint kWidth = 100;
  21. static const GLuint kHeight = 100;
  22. void SetUp() override { gl_.Initialize(GLManager::Options()); }
  23. void TearDown() override { gl_.Destroy(); }
  24. void PrepareForDraw() {
  25. static const char* v_shader_str = SHADER0(
  26. attribute vec4 a_Position; void main() { gl_Position = a_Position; });
  27. static const char* f_shader_str =
  28. SHADER0(precision mediump float; uniform vec4 color;
  29. void main() { gl_FragColor = color; });
  30. GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
  31. glUseProgram(program);
  32. GLuint position_loc = glGetAttribLocation(program, "a_Position");
  33. color_loc_ = glGetUniformLocation(program, "color");
  34. GLuint vbo = 0;
  35. glGenBuffers(1, &vbo);
  36. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  37. static float vertices[] = {
  38. 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
  39. -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
  40. };
  41. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  42. glEnableVertexAttribArray(position_loc);
  43. glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
  44. // Create a sample buffer.
  45. GLsizei num_samples = 4, max_samples = 0;
  46. glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
  47. num_samples = std::min(num_samples, max_samples);
  48. GLuint sample_rb;
  49. glGenRenderbuffers(1, &sample_rb);
  50. glBindRenderbuffer(GL_RENDERBUFFER, sample_rb);
  51. glRenderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, num_samples,
  52. GL_RGBA8_OES, kWidth, kHeight);
  53. GLint param = 0;
  54. glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
  55. &param);
  56. EXPECT_GE(param, num_samples);
  57. glGenFramebuffers(1, &sample_fbo_);
  58. glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo_);
  59. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
  60. GL_RENDERBUFFER, sample_rb);
  61. EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
  62. glCheckFramebufferStatus(GL_FRAMEBUFFER));
  63. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  64. // Create another FBO to resolve the multisample buffer into.
  65. GLuint resolve_tex;
  66. glGenTextures(1, &resolve_tex);
  67. glBindTexture(GL_TEXTURE_2D, resolve_tex);
  68. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA,
  69. GL_UNSIGNED_BYTE, nullptr);
  70. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  71. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  72. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  73. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  74. glGenFramebuffers(1, &resolve_fbo_);
  75. glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo_);
  76. glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
  77. resolve_tex, 0);
  78. EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
  79. glCheckFramebufferStatus(GL_FRAMEBUFFER));
  80. glViewport(0, 0, kWidth, kHeight);
  81. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  82. glEnable(GL_BLEND);
  83. glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo_);
  84. glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  85. glClear(GL_COLOR_BUFFER_BIT);
  86. }
  87. void PrepareForVerify() {
  88. // Resolve.
  89. glBindFramebuffer(GL_READ_FRAMEBUFFER, sample_fbo_);
  90. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo_);
  91. glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
  92. glClear(GL_COLOR_BUFFER_BIT);
  93. glBlitFramebufferCHROMIUM(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
  94. GL_COLOR_BUFFER_BIT, GL_NEAREST);
  95. glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo_);
  96. }
  97. bool IsApplicable() const {
  98. return GLTestHelper::HasExtension("GL_EXT_multisample_compatibility") &&
  99. GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample") &&
  100. GLTestHelper::HasExtension("GL_OES_rgb8_rgba8") &&
  101. !GPUTestBotConfig::CurrentConfigMatches("AMD");
  102. }
  103. GLuint sample_fbo_;
  104. GLuint resolve_fbo_;
  105. GLuint color_loc_;
  106. GLManager gl_;
  107. };
  108. TEST_F(EXTMultisampleCompatibilityTest, TestSimple) {
  109. if (!IsApplicable()) {
  110. return;
  111. }
  112. EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
  113. glDisable(GL_MULTISAMPLE_EXT);
  114. EXPECT_FALSE(glIsEnabled(GL_MULTISAMPLE_EXT));
  115. glEnable(GL_MULTISAMPLE_EXT);
  116. EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
  117. EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
  118. glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
  119. EXPECT_TRUE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
  120. glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
  121. EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
  122. EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
  123. }
  124. TEST_F(EXTMultisampleCompatibilityTest, DrawAndResolve) {
  125. // Test that disabling GL_MULTISAMPLE_EXT is handled correctly.
  126. if (!IsApplicable()) {
  127. return;
  128. }
  129. // TODO(crbug.com/1144270) Fails on Mac Mini 8.1
  130. if (GPUTestBotConfig::CurrentConfigMatches("Mac Intel 0x3e9b"))
  131. return;
  132. static const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
  133. static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
  134. static const float kRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
  135. // Different drivers seem to behave differently with respect to resulting
  136. // values. These might be due to different MSAA sample counts causing
  137. // different samples to hit. Other option is driver bugs. Just test that
  138. // disabling multisample causes a difference.
  139. std::unique_ptr<uint8_t[]> results[3];
  140. const GLint kResultSize = kWidth * kHeight * 4;
  141. for (int pass = 0; pass < 3; pass++) {
  142. PrepareForDraw();
  143. // Green: from top right to bottom left.
  144. glUniform4fv(color_loc_, 1, kGreen);
  145. glDrawArrays(GL_TRIANGLES, 0, 3);
  146. // Blue: from top left to bottom right.
  147. glUniform4fv(color_loc_, 1, kBlue);
  148. glDrawArrays(GL_TRIANGLES, 3, 3);
  149. // Red, with and without MSAA: from bottom left to top right.
  150. if (pass == 1) {
  151. glDisable(GL_MULTISAMPLE_EXT);
  152. }
  153. glUniform4fv(color_loc_, 1, kRed);
  154. glDrawArrays(GL_TRIANGLES, 6, 3);
  155. if (pass == 1) {
  156. glEnable(GL_MULTISAMPLE_EXT);
  157. }
  158. PrepareForVerify();
  159. results[pass].reset(new uint8_t[kResultSize]);
  160. memset(results[pass].get(), GLTestHelper::kCheckClearValue, kResultSize);
  161. glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
  162. results[pass].get());
  163. }
  164. EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
  165. // Verify that rendering is deterministic, so that the pass above does not
  166. // come from non-deterministic rendering.
  167. EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
  168. }
  169. TEST_F(EXTMultisampleCompatibilityTest, DrawAlphaOneAndResolve) {
  170. // Test that enabling GL_SAMPLE_ALPHA_TO_ONE_EXT affects rendering.
  171. if (!IsApplicable()) {
  172. return;
  173. }
  174. #if BUILDFLAG(IS_ANDROID)
  175. // TODO: Figure out why this fails on NVIDIA Shield. crbug.com/700060.
  176. std::string renderer(gl_.context()->GetGLRenderer());
  177. std::string version(gl_.context()->GetGLVersion());
  178. if (renderer.find("NVIDIA Tegra") != std::string::npos &&
  179. version.find("OpenGL ES 3.2 NVIDIA 361.00") != std::string::npos)
  180. return;
  181. #endif
  182. // SAMPLE_ALPHA_TO_ONE is specified to transform alpha values of
  183. // covered samples to 1.0. In order to detect it, we use non-1.0
  184. // alpha.
  185. static const float kBlue[] = {0.0f, 0.0f, 1.0f, 0.5f};
  186. static const float kGreen[] = {0.0f, 1.0f, 0.0f, 0.5f};
  187. static const float kRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
  188. // Different drivers seem to behave differently with respect to resulting
  189. // alpha value. These might be due to different MSAA sample counts causing
  190. // different samples to hit. Other option is driver bugs. Testing exact or
  191. // even approximate sample values is not that easy. Thus, just test
  192. // representative positions which have fractional pixels, inspecting that
  193. // normal rendering is different to SAMPLE_ALPHA_TO_ONE rendering.
  194. std::unique_ptr<uint8_t[]> results[3];
  195. const GLint kResultSize = kWidth * kHeight * 4;
  196. for (int pass = 0; pass < 3; ++pass) {
  197. PrepareForDraw();
  198. if (pass == 1) {
  199. glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
  200. }
  201. glEnable(GL_MULTISAMPLE_EXT);
  202. glUniform4fv(color_loc_, 1, kGreen);
  203. glDrawArrays(GL_TRIANGLES, 0, 3);
  204. glUniform4fv(color_loc_, 1, kBlue);
  205. glDrawArrays(GL_TRIANGLES, 3, 3);
  206. glDisable(GL_MULTISAMPLE_EXT);
  207. glUniform4fv(color_loc_, 1, kRed);
  208. glDrawArrays(GL_TRIANGLES, 6, 3);
  209. PrepareForVerify();
  210. results[pass].reset(new uint8_t[kResultSize]);
  211. memset(results[pass].get(), GLTestHelper::kCheckClearValue, kResultSize);
  212. glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
  213. results[pass].get());
  214. if (pass == 1) {
  215. glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
  216. }
  217. }
  218. EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
  219. // Verify that rendering is deterministic, so that the pass above does not
  220. // come from non-deterministic rendering.
  221. EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
  222. }
  223. } // namespace gpu