gl_virtual_contexts_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. // Copyright 2014 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 "base/memory/raw_ptr.h"
  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 "testing/gmock/include/gmock/gmock.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. #define SHADER(Src) #Src
  15. namespace gpu {
  16. class GLVirtualContextsTest
  17. : public testing::TestWithParam<GpuDriverBugWorkarounds> {
  18. protected:
  19. static const int kSize0 = 4;
  20. static const int kSize1 = 8;
  21. static const int kSize2 = 16;
  22. void SetUp() override {
  23. GpuDriverBugWorkarounds workarounds = GetParam();
  24. GLManager::Options options;
  25. options.context_type = CONTEXT_TYPE_OPENGLES3;
  26. options.size = gfx::Size(kSize0, kSize0);
  27. gl_real_.InitializeWithWorkarounds(options, workarounds);
  28. // If the gl_real context is not initialised, switch to ES2 context type
  29. // and re-initialise
  30. if (!gl_real_.IsInitialized()) {
  31. gl_real_.Reset(); // Must reset object before initializing again
  32. options.context_type = CONTEXT_TYPE_OPENGLES2;
  33. gl_real_.InitializeWithWorkarounds(options, workarounds);
  34. }
  35. gl_real_shared_.InitializeWithWorkarounds(options, workarounds);
  36. options.virtual_manager = &gl_real_shared_;
  37. options.size = gfx::Size(kSize1, kSize1);
  38. gl1_.InitializeWithWorkarounds(options, workarounds);
  39. options.size = gfx::Size(kSize2, kSize2);
  40. gl2_.InitializeWithWorkarounds(options, workarounds);
  41. }
  42. void TearDown() override {
  43. gl1_.Destroy();
  44. gl2_.Destroy();
  45. gl_real_shared_.Destroy();
  46. gl_real_.Destroy();
  47. }
  48. GLuint SetupColoredVertexProgram() {
  49. static const char* v_shader_str = SHADER(
  50. attribute vec4 a_position;
  51. attribute vec4 a_color;
  52. varying vec4 v_color;
  53. void main()
  54. {
  55. gl_Position = a_position;
  56. v_color = a_color;
  57. }
  58. );
  59. static const char* f_shader_str = SHADER(
  60. precision mediump float;
  61. varying vec4 v_color;
  62. void main()
  63. {
  64. gl_FragColor = v_color;
  65. }
  66. );
  67. GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
  68. glUseProgram(program);
  69. return program;
  70. }
  71. void SetUpColoredUnitQuad(const GLfloat* color) {
  72. GLuint program1 = SetupColoredVertexProgram();
  73. GLuint position_loc1 = glGetAttribLocation(program1, "a_position");
  74. GLuint color_loc1 = glGetAttribLocation(program1, "a_color");
  75. GLTestHelper::SetupUnitQuad(position_loc1);
  76. GLTestHelper::SetupColorsForUnitQuad(color_loc1, color, GL_STATIC_DRAW);
  77. }
  78. GLManager gl_real_;
  79. GLManager gl_real_shared_;
  80. GLManager gl1_;
  81. GLManager gl2_;
  82. };
  83. constexpr GLfloat kFloatRed[4] = {
  84. 1.0f, 0.0f, 0.0f, 1.0f,
  85. };
  86. constexpr GLfloat kFloatGreen[4] = {
  87. 0.0f, 1.0f, 0.0f, 1.0f,
  88. };
  89. constexpr uint8_t kExpectedRed[4] = {
  90. 255, 0, 0, 255,
  91. };
  92. constexpr uint8_t kExpectedGreen[4] = {
  93. 0, 255, 0, 255,
  94. };
  95. namespace {
  96. void SetupSimpleShader(const uint8_t* color) {
  97. static const char* v_shader_str = SHADER(
  98. attribute vec4 a_Position;
  99. void main()
  100. {
  101. gl_Position = a_Position;
  102. }
  103. );
  104. static const char* f_shader_str = SHADER(
  105. precision mediump float;
  106. uniform vec4 u_color;
  107. void main()
  108. {
  109. gl_FragColor = u_color;
  110. }
  111. );
  112. GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
  113. glUseProgram(program);
  114. GLuint position_loc = glGetAttribLocation(program, "a_Position");
  115. GLTestHelper::SetupUnitQuad(position_loc);
  116. GLuint color_loc = glGetUniformLocation(program, "u_color");
  117. glUniform4f(
  118. color_loc,
  119. color[0] / 255.0f,
  120. color[1] / 255.0f,
  121. color[2] / 255.0f,
  122. color[3] / 255.0f);
  123. }
  124. void TestDraw(int size) {
  125. uint8_t expected_clear[] = {
  126. 127, 0, 255, 0,
  127. };
  128. glClearColor(0.5f, 0.0f, 1.0f, 0.0f);
  129. glClear(GL_COLOR_BUFFER_BIT);
  130. EXPECT_TRUE(
  131. GLTestHelper::CheckPixels(0, 0, size, size, 1, expected_clear, nullptr));
  132. glDrawArrays(GL_TRIANGLES, 0, 6);
  133. }
  134. } // anonymous namespace
  135. // http://crbug.com/281565
  136. TEST_P(GLVirtualContextsTest, Basic) {
  137. struct TestInfo {
  138. int size;
  139. uint8_t color[4];
  140. raw_ptr<GLManager> manager;
  141. };
  142. const int kNumTests = 3;
  143. TestInfo tests[] = {
  144. { kSize0, { 255, 0, 0, 0, }, &gl_real_, },
  145. { kSize1, { 0, 255, 0, 0, }, &gl1_, },
  146. { kSize2, { 0, 0, 255, 0, }, &gl2_, },
  147. };
  148. for (int ii = 0; ii < kNumTests; ++ii) {
  149. const TestInfo& test = tests[ii];
  150. GLManager* gl_manager = test.manager;
  151. gl_manager->MakeCurrent();
  152. SetupSimpleShader(test.color);
  153. }
  154. for (int ii = 0; ii < kNumTests; ++ii) {
  155. const TestInfo& test = tests[ii];
  156. GLManager* gl_manager = test.manager;
  157. gl_manager->MakeCurrent();
  158. TestDraw(test.size);
  159. }
  160. for (int ii = 0; ii < kNumTests; ++ii) {
  161. const TestInfo& test = tests[ii];
  162. GLManager* gl_manager = test.manager;
  163. gl_manager->MakeCurrent();
  164. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, test.size, test.size, 0,
  165. test.color, nullptr));
  166. }
  167. for (int ii = 0; ii < kNumTests; ++ii) {
  168. const TestInfo& test = tests[ii];
  169. GLManager* gl_manager = test.manager;
  170. gl_manager->MakeCurrent();
  171. GLTestHelper::CheckGLError("no errors", __LINE__);
  172. }
  173. }
  174. // http://crbug.com/363407
  175. TEST_P(GLVirtualContextsTest, VertexArrayObjectRestore) {
  176. GLuint vao1 = 0, vao2 = 0;
  177. gl1_.MakeCurrent();
  178. // Set up red quad in vao1.
  179. glGenVertexArraysOES(1, &vao1);
  180. glBindVertexArrayOES(vao1);
  181. SetUpColoredUnitQuad(kFloatRed);
  182. glFinish();
  183. gl2_.MakeCurrent();
  184. // Set up green quad in vao2.
  185. glGenVertexArraysOES(1, &vao2);
  186. glBindVertexArrayOES(vao2);
  187. SetUpColoredUnitQuad(kFloatGreen);
  188. glFinish();
  189. gl1_.MakeCurrent();
  190. // Test to ensure that vao1 is still the active VAO for this context.
  191. glDrawArrays(GL_TRIANGLES, 0, 6);
  192. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, kSize1, kSize1, 0, kExpectedRed,
  193. nullptr));
  194. glFinish();
  195. GLTestHelper::CheckGLError("no errors", __LINE__);
  196. gl2_.MakeCurrent();
  197. // Test to ensure that vao2 is still the active VAO for this context.
  198. glDrawArrays(GL_TRIANGLES, 0, 6);
  199. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, kSize2, kSize2, 0, kExpectedGreen,
  200. nullptr));
  201. glFinish();
  202. GLTestHelper::CheckGLError("no errors", __LINE__);
  203. }
  204. // http://crbug.com/363407
  205. TEST_P(GLVirtualContextsTest, VertexArrayObjectRestoreRebind) {
  206. GLuint vao1 = 0, vao2 = 0;
  207. gl1_.MakeCurrent();
  208. // Set up red quad in vao1.
  209. glGenVertexArraysOES(1, &vao1);
  210. glBindVertexArrayOES(vao1);
  211. SetUpColoredUnitQuad(kFloatRed);
  212. glFinish();
  213. gl2_.MakeCurrent();
  214. // Set up green quad in new vao2.
  215. glGenVertexArraysOES(1, &vao2);
  216. glBindVertexArrayOES(vao2);
  217. SetUpColoredUnitQuad(kFloatGreen);
  218. glFinish();
  219. gl1_.MakeCurrent();
  220. // Test to ensure that vao1 hasn't been corrupted after rebinding.
  221. // Bind 0 is required so that bind vao1 is not optimized away in the service.
  222. glBindVertexArrayOES(0);
  223. glBindVertexArrayOES(vao1);
  224. glDrawArrays(GL_TRIANGLES, 0, 6);
  225. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, kSize1, kSize1, 0, kExpectedRed,
  226. nullptr));
  227. glFinish();
  228. GLTestHelper::CheckGLError("no errors", __LINE__);
  229. gl2_.MakeCurrent();
  230. // Test to ensure that vao1 hasn't been corrupted after rebinding.
  231. // Bind 0 is required so that bind vao2 is not optimized away in the service.
  232. glBindVertexArrayOES(0);
  233. glBindVertexArrayOES(vao2);
  234. glDrawArrays(GL_TRIANGLES, 0, 6);
  235. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, kSize2, kSize2, 0, kExpectedGreen,
  236. nullptr));
  237. glFinish();
  238. GLTestHelper::CheckGLError("no errors", __LINE__);
  239. }
  240. // http://crbug.com/363407
  241. TEST_P(GLVirtualContextsTest, VertexArrayObjectRestoreDefault) {
  242. gl1_.MakeCurrent();
  243. // Set up red quad in default VAO.
  244. SetUpColoredUnitQuad(kFloatRed);
  245. glFinish();
  246. gl2_.MakeCurrent();
  247. // Set up green quad in default VAO.
  248. SetUpColoredUnitQuad(kFloatGreen);
  249. glFinish();
  250. // Gen & bind a non-default VAO.
  251. GLuint vao;
  252. glGenVertexArraysOES(1, &vao);
  253. glBindVertexArrayOES(vao);
  254. glFinish();
  255. gl1_.MakeCurrent();
  256. // Test to ensure that default VAO on gl1_ is still valid.
  257. glDrawArrays(GL_TRIANGLES, 0, 6);
  258. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, kSize1, kSize1, 0, kExpectedRed,
  259. nullptr));
  260. glFinish();
  261. gl2_.MakeCurrent();
  262. // Test to ensure that default VAO on gl2_ is still valid.
  263. // This tests that a default VAO is restored even when it's not currently
  264. // bound during the context switch.
  265. glBindVertexArrayOES(0);
  266. glDrawArrays(GL_TRIANGLES, 0, 6);
  267. EXPECT_TRUE(GLTestHelper::CheckPixels(0, 0, kSize2, kSize2, 0, kExpectedGreen,
  268. nullptr));
  269. glFinish();
  270. GLTestHelper::CheckGLError("no errors", __LINE__);
  271. }
  272. TEST_P(GLVirtualContextsTest, VirtualQueries) {
  273. const GLenum query_targets[] = {
  274. GL_ANY_SAMPLES_PASSED_EXT,
  275. GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
  276. GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM,
  277. GL_COMMANDS_COMPLETED_CHROMIUM,
  278. GL_COMMANDS_ISSUED_CHROMIUM,
  279. GL_GET_ERROR_QUERY_CHROMIUM,
  280. GL_LATENCY_QUERY_CHROMIUM,
  281. GL_TIME_ELAPSED_EXT,
  282. };
  283. for (GLenum query_target : query_targets) {
  284. GLuint query1 = 0;
  285. gl1_.MakeCurrent();
  286. glGenQueriesEXT(1, &query1);
  287. glBeginQueryEXT(query_target, query1);
  288. const GLenum begin_error = glGetError();
  289. if (GL_INVALID_OPERATION == begin_error) {
  290. // Not supported, simply skip.
  291. glDeleteQueriesEXT(1, &query1);
  292. continue;
  293. }
  294. ASSERT_TRUE(GL_NO_ERROR == begin_error);
  295. GLuint query2 = 0;
  296. gl2_.MakeCurrent();
  297. glGenQueriesEXT(1, &query2);
  298. glBeginQueryEXT(query_target, query2);
  299. EXPECT_TRUE(GL_NO_ERROR == glGetError())
  300. << "Virtualized Query " << query_target << " failed.";
  301. gl1_.MakeCurrent();
  302. glEndQueryEXT(query_target);
  303. glFinish();
  304. GLuint query1_available = 0;
  305. glGetQueryObjectuivEXT(query1, GL_QUERY_RESULT_AVAILABLE_EXT,
  306. &query1_available);
  307. EXPECT_TRUE(query1_available);
  308. glDeleteQueriesEXT(1, &query1);
  309. GLTestHelper::CheckGLError("no errors", __LINE__);
  310. gl2_.MakeCurrent();
  311. glEndQueryEXT(query_target);
  312. glFinish();
  313. GLuint query2_available = 0;
  314. glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT,
  315. &query2_available);
  316. EXPECT_TRUE(query2_available);
  317. glDeleteQueriesEXT(1, &query2);
  318. GLTestHelper::CheckGLError("no errors", __LINE__);
  319. }
  320. }
  321. // http://crbug.com/930327
  322. TEST_P(GLVirtualContextsTest, Texture2DArrayAnd3DRestore) {
  323. // This test should only be run for ES3 or higher context
  324. // So if the current version is ES2, do not run this test
  325. if (gl1_.GetContextType() == CONTEXT_TYPE_OPENGLES2)
  326. return;
  327. // Context 1
  328. gl1_.MakeCurrent();
  329. GLuint tex1_2d_array = 0, tex1_3d = 0;
  330. glActiveTexture(GL_TEXTURE0);
  331. // 2d array texture
  332. glGenTextures(1, &tex1_2d_array);
  333. glBindTexture(GL_TEXTURE_2D_ARRAY, tex1_2d_array);
  334. glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  335. // 3d texture
  336. glGenTextures(1, &tex1_3d);
  337. glBindTexture(GL_TEXTURE_3D, tex1_3d);
  338. glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,
  339. GL_NEAREST_MIPMAP_NEAREST);
  340. glFinish();
  341. // switch to context 2
  342. gl2_.MakeCurrent();
  343. GLuint tex2_2d_array = 0, tex2_3d = 0;
  344. glActiveTexture(GL_TEXTURE0);
  345. // 2d array texture
  346. glGenTextures(1, &tex2_2d_array);
  347. glBindTexture(GL_TEXTURE_2D_ARRAY, tex2_2d_array);
  348. glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  349. // 3d texture
  350. glGenTextures(1, &tex2_3d);
  351. glBindTexture(GL_TEXTURE_3D, tex2_3d);
  352. glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,
  353. GL_LINEAR_MIPMAP_LINEAR);
  354. glFinish();
  355. // switch back to context1
  356. gl1_.MakeCurrent();
  357. // get the texture parameters which were programmed earlier for context1
  358. GLint tex_2d_array_params = 0, tex_3d_params = 0;
  359. glGetTexParameteriv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
  360. &tex_2d_array_params);
  361. glGetTexParameteriv(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, &tex_3d_params);
  362. // Do checks to make sure texture params are restored correctly after context
  363. // switching
  364. EXPECT_EQ(GL_NEAREST, tex_2d_array_params);
  365. EXPECT_EQ(GL_NEAREST_MIPMAP_NEAREST, tex_3d_params);
  366. GLTestHelper::CheckGLError("no errors", __LINE__);
  367. }
  368. static const GpuDriverBugWorkarounds workarounds_cases[] = {
  369. // No extra workarounds.
  370. GpuDriverBugWorkarounds(),
  371. #if BUILDFLAG(IS_ANDROID)
  372. // Regression tests for https://crbug.com/768324
  373. //
  374. // TODO(kainino): The #if is added because this case does not pass on Mac
  375. // or Linux. My guess is that this workaround requires the backing context
  376. // to be OpenGL ES (not OpenGL Core Profile).
  377. GpuDriverBugWorkarounds({
  378. USE_CLIENT_SIDE_ARRAYS_FOR_STREAM_BUFFERS,
  379. }),
  380. #endif
  381. };
  382. INSTANTIATE_TEST_SUITE_P(WithWorkarounds,
  383. GLVirtualContextsTest,
  384. ::testing::ValuesIn(workarounds_cases));
  385. } // namespace gpu