TestRender.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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/LexicalPath.h>
  8. #include <AK/String.h>
  9. #include <LibCore/FileStream.h>
  10. #include <LibGL/GL/gl.h>
  11. #include <LibGL/GLContext.h>
  12. #include <LibGfx/Bitmap.h>
  13. #include <LibGfx/QOIWriter.h>
  14. #include <LibTest/TestCase.h>
  15. #ifdef __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::try_create(Gfx::BitmapFormat::BGRx8888, { width, height }));
  24. auto context = MUST(GL::create_context(*bitmap));
  25. GL::make_context_current(context);
  26. // Assume some defaults for our testing contexts
  27. glFrontFace(GL_CCW);
  28. glCullFace(GL_BACK);
  29. glEnable(GL_CULL_FACE);
  30. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  31. glClear(GL_COLOR_BUFFER_BIT);
  32. return context;
  33. }
  34. static void expect_bitmap_equals_reference(Gfx::Bitmap const& bitmap, StringView test_name)
  35. {
  36. auto reference_filename = String::formatted("{}.qoi", test_name);
  37. if constexpr (SAVE_OUTPUT) {
  38. auto target_path = LexicalPath("/home/anon").append(reference_filename);
  39. auto qoi_buffer = Gfx::QOIWriter::encode(bitmap);
  40. auto qoi_output_stream = MUST(Core::OutputFileStream::open(target_path.string()));
  41. auto number_of_bytes_written = qoi_output_stream.write(qoi_buffer);
  42. qoi_output_stream.close();
  43. EXPECT_EQ(number_of_bytes_written, qoi_buffer.size());
  44. }
  45. auto reference_image_path = String::formatted(REFERENCE_IMAGE_DIR "/{}", reference_filename);
  46. auto reference_bitmap = MUST(Gfx::Bitmap::try_load_from_file(reference_image_path));
  47. EXPECT_EQ(reference_bitmap->visually_equals(bitmap), true);
  48. }
  49. TEST_CASE(0001_simple_triangle)
  50. {
  51. auto context = create_testing_context(64, 64);
  52. glBegin(GL_TRIANGLES);
  53. glColor3f(1, 1, 1);
  54. glVertex2f(0, 1);
  55. glVertex2f(-1, -1);
  56. glVertex2f(1, -1);
  57. glEnd();
  58. EXPECT_EQ(glGetError(), 0u);
  59. context->present();
  60. expect_bitmap_equals_reference(context->frontbuffer(), "0001_simple_triangle"sv);
  61. }
  62. TEST_CASE(0002_quad_color_interpolation)
  63. {
  64. auto context = create_testing_context(64, 64);
  65. glBegin(GL_QUADS);
  66. glColor3f(1, 0, 0);
  67. glVertex2i(-1, -1);
  68. glColor3f(0, 1, 0);
  69. glVertex2i(1, -1);
  70. glColor3f(0, 0, 1);
  71. glVertex2i(1, 1);
  72. glColor3f(1, 0, 1);
  73. glVertex2i(-1, 1);
  74. glEnd();
  75. EXPECT_EQ(glGetError(), 0u);
  76. context->present();
  77. expect_bitmap_equals_reference(context->frontbuffer(), "0002_quad_color_interpolation"sv);
  78. }
  79. TEST_CASE(0003_rect_w_coordinate_regression)
  80. {
  81. auto context = create_testing_context(64, 64);
  82. glEnable(GL_DEPTH_TEST);
  83. glClear(GL_DEPTH_BUFFER_BIT);
  84. glColor3f(0, 1, 0);
  85. glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
  86. glBegin(GL_TRIANGLES);
  87. glColor3f(1, 0, 0);
  88. glVertex2i(-1, -1);
  89. glVertex2i(1, -1);
  90. glVertex2i(-1, 1);
  91. glEnd();
  92. EXPECT_EQ(glGetError(), 0u);
  93. context->present();
  94. expect_bitmap_equals_reference(context->frontbuffer(), "0003_rect_w_coordinate_regression"sv);
  95. }
  96. TEST_CASE(0004_points)
  97. {
  98. auto context = create_testing_context(64, 64);
  99. // Aliased points
  100. for (size_t i = 0; i < 3; ++i) {
  101. glPointSize(1.f + i);
  102. glBegin(GL_POINTS);
  103. glVertex2f(-.5f + i * .5f, .5f);
  104. glEnd();
  105. }
  106. // Anti-aliased points
  107. glEnable(GL_POINT_SMOOTH);
  108. glEnable(GL_BLEND);
  109. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  110. for (size_t i = 0; i < 3; ++i) {
  111. glPointSize(3.f - i);
  112. glBegin(GL_POINTS);
  113. glVertex2f(-.5f + i * .5f, -.5f);
  114. glEnd();
  115. }
  116. EXPECT_EQ(glGetError(), 0u);
  117. context->present();
  118. expect_bitmap_equals_reference(context->frontbuffer(), "0004_points"sv);
  119. }
  120. TEST_CASE(0005_lines_antialiased)
  121. {
  122. auto context = create_testing_context(64, 64);
  123. // Draw anti-aliased lines
  124. glEnable(GL_LINE_SMOOTH);
  125. glEnable(GL_BLEND);
  126. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  127. glBegin(GL_LINES);
  128. for (size_t i = 0; i < 6; ++i) {
  129. glVertex2f(-.9f, .25f - i * .1f);
  130. glVertex2f(.9f, .9f - i * .36f);
  131. }
  132. glEnd();
  133. EXPECT_EQ(glGetError(), 0u);
  134. context->present();
  135. expect_bitmap_equals_reference(context->frontbuffer(), "0005_lines"sv);
  136. }
  137. TEST_CASE(0006_test_rgb565_texture)
  138. {
  139. auto context = create_testing_context(64, 64);
  140. GLuint texture_id;
  141. glGenTextures(1, &texture_id);
  142. glBindTexture(GL_TEXTURE_2D, texture_id);
  143. u16 texture_data[] = { 0xF800, 0xC000, 0x8000, 0x07E0, 0x0600, 0x0400, 0x001F, 0x0018, 0x0010 };
  144. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  145. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 3, 3, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture_data);
  146. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  147. glEnable(GL_TEXTURE_2D);
  148. glBegin(GL_QUADS);
  149. glTexCoord2i(0, 0);
  150. glVertex2i(-1, 1);
  151. glTexCoord2i(0, 1);
  152. glVertex2i(-1, -1);
  153. glTexCoord2i(1, 1);
  154. glVertex2i(1, -1);
  155. glTexCoord2i(1, 0);
  156. glVertex2i(1, 1);
  157. glEnd();
  158. EXPECT_EQ(glGetError(), 0u);
  159. context->present();
  160. expect_bitmap_equals_reference(context->frontbuffer(), "0006_test_rgb565_texture"sv);
  161. }
  162. TEST_CASE(0007_test_rgba_to_rgb_texture)
  163. {
  164. auto context = create_testing_context(64, 64);
  165. GLuint texture_id;
  166. glGenTextures(1, &texture_id);
  167. glBindTexture(GL_TEXTURE_2D, texture_id);
  168. // Write RGBA data with A = 0 to an RGB texture
  169. u32 texture_data[] = { 0x00FF0000 };
  170. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texture_data);
  171. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  172. glEnable(GL_TEXTURE_2D);
  173. glBegin(GL_TRIANGLES);
  174. glTexCoord2i(0, 0);
  175. glVertex2i(-1, 1);
  176. glTexCoord2i(0, 1);
  177. glVertex2i(-1, -1);
  178. glTexCoord2i(1, 1);
  179. glVertex2i(1, -1);
  180. glEnd();
  181. EXPECT_EQ(glGetError(), 0u);
  182. context->present();
  183. expect_bitmap_equals_reference(context->frontbuffer(), "0007_test_rgba_to_rgb_texture"sv);
  184. }
  185. TEST_CASE(0008_test_pop_matrix_regression)
  186. {
  187. auto context = create_testing_context(64, 64);
  188. // Load identity matrix after popping
  189. glMatrixMode(GL_MODELVIEW);
  190. glTranslatef(10.f, 10.f, 10.f);
  191. glPushMatrix();
  192. glPopMatrix();
  193. glLoadIdentity();
  194. glBegin(GL_TRIANGLES);
  195. glColor3f(0.f, 1.f, 0.f);
  196. glVertex2f(.5f, -.5f);
  197. glVertex2f(.0f, .5f);
  198. glVertex2f(-.5f, -.5f);
  199. glEnd();
  200. EXPECT_EQ(glGetError(), 0u);
  201. context->present();
  202. expect_bitmap_equals_reference(context->frontbuffer(), "0008_test_pop_matrix_regression"sv);
  203. }