123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*
- * Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com>
- * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <AK/LexicalPath.h>
- #include <AK/String.h>
- #include <LibCore/FileStream.h>
- #include <LibGL/GL/gl.h>
- #include <LibGL/GLContext.h>
- #include <LibGfx/Bitmap.h>
- #include <LibGfx/QOIWriter.h>
- #include <LibTest/TestCase.h>
- #ifdef AK_OS_SERENITY
- # define REFERENCE_IMAGE_DIR "/usr/Tests/LibGL/reference-images"
- #else
- # define REFERENCE_IMAGE_DIR "reference-images"
- #endif
- #define SAVE_OUTPUT false
- static NonnullOwnPtr<GL::GLContext> create_testing_context(int width, int height)
- {
- auto bitmap = MUST(Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRx8888, { width, height }));
- auto context = MUST(GL::create_context(*bitmap));
- GL::make_context_current(context);
- return context;
- }
- static void expect_bitmap_equals_reference(Gfx::Bitmap const& bitmap, StringView test_name)
- {
- auto reference_filename = String::formatted("{}.qoi", test_name);
- if constexpr (SAVE_OUTPUT) {
- auto target_path = LexicalPath("/home/anon").append(reference_filename);
- auto qoi_buffer = Gfx::QOIWriter::encode(bitmap);
- auto qoi_output_stream = MUST(Core::OutputFileStream::open(target_path.string()));
- auto number_of_bytes_written = qoi_output_stream.write(qoi_buffer);
- qoi_output_stream.close();
- EXPECT_EQ(number_of_bytes_written, qoi_buffer.size());
- }
- auto reference_image_path = String::formatted(REFERENCE_IMAGE_DIR "/{}", reference_filename);
- auto reference_bitmap = MUST(Gfx::Bitmap::try_load_from_file(reference_image_path));
- EXPECT_EQ(reference_bitmap->visually_equals(bitmap), true);
- }
- TEST_CASE(0001_simple_triangle)
- {
- auto context = create_testing_context(64, 64);
- glBegin(GL_TRIANGLES);
- glColor3f(1, 1, 1);
- glVertex2f(0, 1);
- glVertex2f(-1, -1);
- glVertex2f(1, -1);
- glEnd();
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0001_simple_triangle"sv);
- }
- TEST_CASE(0002_quad_color_interpolation)
- {
- auto context = create_testing_context(64, 64);
- glBegin(GL_QUADS);
- glColor3f(1, 0, 0);
- glVertex2i(-1, -1);
- glColor3f(0, 1, 0);
- glVertex2i(1, -1);
- glColor3f(0, 0, 1);
- glVertex2i(1, 1);
- glColor3f(1, 0, 1);
- glVertex2i(-1, 1);
- glEnd();
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0002_quad_color_interpolation"sv);
- }
- TEST_CASE(0003_rect_w_coordinate_regression)
- {
- auto context = create_testing_context(64, 64);
- glEnable(GL_DEPTH_TEST);
- glClear(GL_DEPTH_BUFFER_BIT);
- glColor3f(0, 1, 0);
- glRectf(-0.5f, -0.5f, 0.5f, 0.5f);
- glBegin(GL_TRIANGLES);
- glColor3f(1, 0, 0);
- glVertex2i(-1, -1);
- glVertex2i(1, -1);
- glVertex2i(-1, 1);
- glEnd();
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0003_rect_w_coordinate_regression"sv);
- }
- TEST_CASE(0004_points)
- {
- auto context = create_testing_context(64, 64);
- // Aliased points
- for (size_t i = 0; i < 3; ++i) {
- glPointSize(1.f + i);
- glBegin(GL_POINTS);
- glVertex2f(-.5f + i * .5f, .5f);
- glEnd();
- }
- // Anti-aliased points
- glEnable(GL_POINT_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- for (size_t i = 0; i < 3; ++i) {
- glPointSize(3.f - i);
- glBegin(GL_POINTS);
- glVertex2f(-.5f + i * .5f, -.5f);
- glEnd();
- }
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0004_points"sv);
- }
- TEST_CASE(0005_lines_antialiased)
- {
- auto context = create_testing_context(64, 64);
- // Draw anti-aliased lines
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glBegin(GL_LINES);
- for (size_t i = 0; i < 6; ++i) {
- glVertex2f(-.9f, .25f - i * .1f);
- glVertex2f(.9f, .9f - i * .36f);
- }
- glEnd();
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0005_lines"sv);
- }
- TEST_CASE(0006_test_rgb565_texture)
- {
- auto context = create_testing_context(64, 64);
- GLuint texture_id;
- glGenTextures(1, &texture_id);
- glBindTexture(GL_TEXTURE_2D, texture_id);
- u16 texture_data[] = { 0xF800, 0xC000, 0x8000, 0x07E0, 0x0600, 0x0400, 0x001F, 0x0018, 0x0010 };
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 3, 3, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture_data);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glEnable(GL_TEXTURE_2D);
- glBegin(GL_QUADS);
- glTexCoord2i(0, 0);
- glVertex2i(-1, 1);
- glTexCoord2i(0, 1);
- glVertex2i(-1, -1);
- glTexCoord2i(1, 1);
- glVertex2i(1, -1);
- glTexCoord2i(1, 0);
- glVertex2i(1, 1);
- glEnd();
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0006_test_rgb565_texture"sv);
- }
- TEST_CASE(0007_test_rgba_to_rgb_texture)
- {
- auto context = create_testing_context(64, 64);
- GLuint texture_id;
- glGenTextures(1, &texture_id);
- glBindTexture(GL_TEXTURE_2D, texture_id);
- // Write RGBA data with A = 0 to an RGB texture
- u32 texture_data[] = { 0x00FF0000 };
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texture_data);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glEnable(GL_TEXTURE_2D);
- glBegin(GL_TRIANGLES);
- glTexCoord2i(0, 0);
- glVertex2i(-1, 1);
- glTexCoord2i(0, 1);
- glVertex2i(-1, -1);
- glTexCoord2i(1, 1);
- glVertex2i(1, -1);
- glEnd();
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0007_test_rgba_to_rgb_texture"sv);
- }
- TEST_CASE(0008_test_pop_matrix_regression)
- {
- auto context = create_testing_context(64, 64);
- // Load identity matrix after popping
- glMatrixMode(GL_MODELVIEW);
- glTranslatef(10.f, 10.f, 10.f);
- glPushMatrix();
- glPopMatrix();
- glLoadIdentity();
- glBegin(GL_TRIANGLES);
- glColor3f(0.f, 1.f, 0.f);
- glVertex2f(.5f, -.5f);
- glVertex2f(.0f, .5f);
- glVertex2f(-.5f, -.5f);
- glEnd();
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0008_test_pop_matrix_regression"sv);
- }
- TEST_CASE(0009_test_draw_elements_in_display_list)
- {
- auto context = create_testing_context(64, 64);
- glColor3f(0.f, 0.f, 1.f);
- glEnableClientState(GL_VERTEX_ARRAY);
- auto const list_index = glGenLists(1);
- glNewList(list_index, GL_COMPILE);
- float vertices[] = { 0.f, .5f, -.5f, -.5f, .5f, -.5f };
- glVertexPointer(2, GL_FLOAT, 0, &vertices);
- u8 indices[] = { 0, 1, 2 };
- glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, &indices);
- glEndList();
- // Modifying an index here should not have an effect
- indices[0] = 2;
- glCallList(list_index);
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0009_test_draw_elements_in_display_list"sv);
- }
- TEST_CASE(0010_test_store_data_in_buffer)
- {
- auto context = create_testing_context(64, 64);
- glColor3f(1.f, 0.f, 0.f);
- glEnableClientState(GL_VERTEX_ARRAY);
- float vertices[] = { 0.f, .5f, -.5f, -.5f, .5f, -.5f };
- u8 indices[] = { 0, 1, 2 };
- GLuint buffers[2];
- glGenBuffers(2, buffers);
- glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
- glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), vertices, GL_STATIC_DRAW);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3, indices, GL_STATIC_DRAW);
- glVertexPointer(2, GL_FLOAT, 0, 0);
- glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, 0);
- glDeleteBuffers(2, buffers);
- EXPECT_EQ(glGetError(), 0u);
- context->present();
- expect_bitmap_equals_reference(context->frontbuffer(), "0010_test_store_data_in_buffer"sv);
- }
|