TestRender.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com>
  3. * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/DeprecatedString.h>
  8. #include <AK/LexicalPath.h>
  9. #include <LibCore/File.h>
  10. #include <LibGL/GL/gl.h>
  11. #include <LibGL/GLContext.h>
  12. #include <LibGfx/Bitmap.h>
  13. #include <LibGfx/ImageFormats/QOIWriter.h>
  14. #include <LibTest/TestCase.h>
  15. #ifdef AK_OS_SERENITY
  16. # define REFERENCE_IMAGE_DIR "/usr/Tests/LibGL/reference-images"
  17. #else
  18. # define REFERENCE_IMAGE_DIR "reference-images"
  19. #endif
  20. #define SAVE_OUTPUT false
  21. static NonnullOwnPtr<GL::GLContext> create_testing_context(int width, int height)
  22. {
  23. auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, { width, height }));
  24. auto context = MUST(GL::create_context(*bitmap));
  25. GL::make_context_current(context);
  26. return context;
  27. }
  28. static void expect_bitmap_equals_reference(Gfx::Bitmap const& bitmap, StringView test_name)
  29. {
  30. auto reference_filename = DeprecatedString::formatted("{}.qoi", test_name);
  31. if constexpr (SAVE_OUTPUT) {
  32. auto target_path = LexicalPath("/home/anon").append(reference_filename);
  33. auto qoi_buffer = MUST(Gfx::QOIWriter::encode(bitmap));
  34. auto qoi_output_stream = MUST(Core::File::open(target_path.string(), Core::File::OpenMode::Write));
  35. MUST(qoi_output_stream->write_until_depleted(qoi_buffer));
  36. }
  37. auto reference_image_path = DeprecatedString::formatted(REFERENCE_IMAGE_DIR "/{}", reference_filename);
  38. auto reference_bitmap = MUST(Gfx::Bitmap::load_from_file(reference_image_path));
  39. EXPECT_EQ(reference_bitmap->visually_equals(bitmap), true);
  40. }
  41. TEST_CASE(0001_simple_triangle)
  42. {
  43. auto context = create_testing_context(64, 64);
  44. glBegin(GL_TRIANGLES);
  45. glColor3f(1, 1, 1);
  46. glVertex2f(0, 1);
  47. glVertex2f(-1, -1);
  48. glVertex2f(1, -1);
  49. glEnd();
  50. EXPECT_EQ(glGetError(), 0u);
  51. context->present();
  52. expect_bitmap_equals_reference(context->frontbuffer(), "0001_simple_triangle"sv);
  53. }
  54. TEST_CASE(0002_quad_color_interpolation)
  55. {
  56. auto context = create_testing_context(64, 64);
  57. glBegin(GL_QUADS);
  58. glColor3f(1, 0, 0);
  59. glVertex2i(-1, -1);
  60. glColor3f(0, 1, 0);
  61. glVertex2i(1, -1);
  62. glColor3f(0, 0, 1);
  63. glVertex2i(1, 1);
  64. glColor3f(1, 0, 1);
  65. glVertex2i(-1, 1);
  66. glEnd();
  67. EXPECT_EQ(glGetError(), 0u);
  68. context->present();
  69. expect_bitmap_equals_reference(context->frontbuffer(), "0002_quad_color_interpolation"sv);
  70. }
  71. TEST_CASE(0003_rect_w_coordinate_regression)
  72. {
  73. auto context = create_testing_context(64, 64);
  74. glEnable(GL_DEPTH_TEST);
  75. glClear(GL_DEPTH_BUFFER_BIT);
  76. glColor3f(0, 1, 0);
  77. glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
  78. glBegin(GL_TRIANGLES);
  79. glColor3f(1, 0, 0);
  80. glVertex2i(-1, -1);
  81. glVertex2i(1, -1);
  82. glVertex2i(-1, 1);
  83. glEnd();
  84. EXPECT_EQ(glGetError(), 0u);
  85. context->present();
  86. expect_bitmap_equals_reference(context->frontbuffer(), "0003_rect_w_coordinate_regression"sv);
  87. }
  88. TEST_CASE(0004_points)
  89. {
  90. auto context = create_testing_context(64, 64);
  91. // Aliased points
  92. for (size_t i = 0; i < 3; ++i) {
  93. glPointSize(1.f + i);
  94. glBegin(GL_POINTS);
  95. glVertex2f(-.5f + i * .5f, .5f);
  96. glEnd();
  97. }
  98. // Anti-aliased points
  99. glEnable(GL_POINT_SMOOTH);
  100. glEnable(GL_BLEND);
  101. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  102. for (size_t i = 0; i < 3; ++i) {
  103. glPointSize(3.f - i);
  104. glBegin(GL_POINTS);
  105. glVertex2f(-.5f + i * .5f, -.5f);
  106. glEnd();
  107. }
  108. EXPECT_EQ(glGetError(), 0u);
  109. context->present();
  110. expect_bitmap_equals_reference(context->frontbuffer(), "0004_points"sv);
  111. }
  112. TEST_CASE(0005_lines_antialiased)
  113. {
  114. auto context = create_testing_context(64, 64);
  115. // Draw anti-aliased lines
  116. glEnable(GL_LINE_SMOOTH);
  117. glEnable(GL_BLEND);
  118. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  119. glBegin(GL_LINES);
  120. for (size_t i = 0; i < 6; ++i) {
  121. glVertex2f(-.9f, .25f - i * .1f);
  122. glVertex2f(.9f, .9f - i * .36f);
  123. }
  124. glEnd();
  125. EXPECT_EQ(glGetError(), 0u);
  126. context->present();
  127. expect_bitmap_equals_reference(context->frontbuffer(), "0005_lines"sv);
  128. }
  129. TEST_CASE(0006_test_rgb565_texture)
  130. {
  131. auto context = create_testing_context(64, 64);
  132. GLuint texture_id;
  133. glGenTextures(1, &texture_id);
  134. glBindTexture(GL_TEXTURE_2D, texture_id);
  135. u16 texture_data[] = { 0xF800, 0xC000, 0x8000, 0x07E0, 0x0600, 0x0400, 0x001F, 0x0018, 0x0010 };
  136. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  137. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 3, 3, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture_data);
  138. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  139. glEnable(GL_TEXTURE_2D);
  140. glBegin(GL_QUADS);
  141. glTexCoord2i(0, 0);
  142. glVertex2i(-1, 1);
  143. glTexCoord2i(0, 1);
  144. glVertex2i(-1, -1);
  145. glTexCoord2i(1, 1);
  146. glVertex2i(1, -1);
  147. glTexCoord2i(1, 0);
  148. glVertex2i(1, 1);
  149. glEnd();
  150. EXPECT_EQ(glGetError(), 0u);
  151. context->present();
  152. expect_bitmap_equals_reference(context->frontbuffer(), "0006_test_rgb565_texture"sv);
  153. }
  154. TEST_CASE(0007_test_rgba_to_rgb_texture)
  155. {
  156. auto context = create_testing_context(64, 64);
  157. GLuint texture_id;
  158. glGenTextures(1, &texture_id);
  159. glBindTexture(GL_TEXTURE_2D, texture_id);
  160. // Write RGBA data with A = 0 to an RGB texture
  161. u32 texture_data[] = { 0x00FF0000 };
  162. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texture_data);
  163. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  164. glEnable(GL_TEXTURE_2D);
  165. glBegin(GL_TRIANGLES);
  166. glTexCoord2i(0, 0);
  167. glVertex2i(-1, 1);
  168. glTexCoord2i(0, 1);
  169. glVertex2i(-1, -1);
  170. glTexCoord2i(1, 1);
  171. glVertex2i(1, -1);
  172. glEnd();
  173. EXPECT_EQ(glGetError(), 0u);
  174. context->present();
  175. expect_bitmap_equals_reference(context->frontbuffer(), "0007_test_rgba_to_rgb_texture"sv);
  176. }
  177. TEST_CASE(0008_test_pop_matrix_regression)
  178. {
  179. auto context = create_testing_context(64, 64);
  180. // Load identity matrix after popping
  181. glMatrixMode(GL_MODELVIEW);
  182. glTranslatef(10.f, 10.f, 10.f);
  183. glPushMatrix();
  184. glPopMatrix();
  185. glLoadIdentity();
  186. glBegin(GL_TRIANGLES);
  187. glColor3f(0.f, 1.f, 0.f);
  188. glVertex2f(.5f, -.5f);
  189. glVertex2f(.0f, .5f);
  190. glVertex2f(-.5f, -.5f);
  191. glEnd();
  192. EXPECT_EQ(glGetError(), 0u);
  193. context->present();
  194. expect_bitmap_equals_reference(context->frontbuffer(), "0008_test_pop_matrix_regression"sv);
  195. }
  196. TEST_CASE(0009_test_draw_elements_in_display_list)
  197. {
  198. auto context = create_testing_context(64, 64);
  199. glColor3f(0.f, 0.f, 1.f);
  200. glEnableClientState(GL_VERTEX_ARRAY);
  201. auto const list_index = glGenLists(1);
  202. glNewList(list_index, GL_COMPILE);
  203. float vertices[] = { 0.f, .5f, -.5f, -.5f, .5f, -.5f };
  204. glVertexPointer(2, GL_FLOAT, 0, &vertices);
  205. u8 indices[] = { 0, 1, 2 };
  206. glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, &indices);
  207. glEndList();
  208. // Modifying an index here should not have an effect
  209. indices[0] = 2;
  210. glCallList(list_index);
  211. EXPECT_EQ(glGetError(), 0u);
  212. context->present();
  213. expect_bitmap_equals_reference(context->frontbuffer(), "0009_test_draw_elements_in_display_list"sv);
  214. }
  215. TEST_CASE(0010_test_store_data_in_buffer)
  216. {
  217. auto context = create_testing_context(64, 64);
  218. glColor3f(1.f, 0.f, 0.f);
  219. glEnableClientState(GL_VERTEX_ARRAY);
  220. float vertices[] = { 0.f, .5f, -.5f, -.5f, .5f, -.5f };
  221. u8 indices[] = { 0, 1, 2 };
  222. GLuint buffers[2];
  223. glGenBuffers(2, buffers);
  224. glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
  225. glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), vertices, GL_STATIC_DRAW);
  226. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
  227. glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3, indices, GL_STATIC_DRAW);
  228. glVertexPointer(2, GL_FLOAT, 0, 0);
  229. glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, 0);
  230. glDeleteBuffers(2, buffers);
  231. EXPECT_EQ(glGetError(), 0u);
  232. context->present();
  233. expect_bitmap_equals_reference(context->frontbuffer(), "0010_test_store_data_in_buffer"sv);
  234. }
  235. TEST_CASE(0011_tex_env_combine_with_constant_color)
  236. {
  237. auto context = create_testing_context(64, 64);
  238. glEnable(GL_TEXTURE_2D);
  239. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
  240. glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
  241. glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
  242. float color[4] = { .3f, .5f, .7f, 1.f };
  243. glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
  244. glRecti(-1, -1, 1, 1);
  245. EXPECT_EQ(glGetError(), 0u);
  246. context->present();
  247. expect_bitmap_equals_reference(context->frontbuffer(), "0011_tex_env_combine_with_constant_color"sv);
  248. }