diff --git a/libvisual/cmake/LVBuildTest.cmake b/libvisual/cmake/LVBuildTest.cmake index 2a704bebf..5452f8748 100644 --- a/libvisual/cmake/LVBuildTest.cmake +++ b/libvisual/cmake/LVBuildTest.cmake @@ -33,7 +33,7 @@ FUNCTION(LV_BUILD_TEST TEST_NAME) TARGET_LINK_LIBRARIES(${TEST_NAME} PRIVATE - libvisual + test_common Threads::Threads ${PARSED_ARGS_LINK_LIBS} ) diff --git a/libvisual/tests/CMakeLists.txt b/libvisual/tests/CMakeLists.txt index 5ae774412..1300f1e9f 100644 --- a/libvisual/tests/CMakeLists.txt +++ b/libvisual/tests/CMakeLists.txt @@ -1,9 +1,15 @@ INCLUDE(LVBuildTest) -INCLUDE_DIRECTORIES( +ADD_LIBRARY(test_common STATIC + random.cpp +) + +TARGET_INCLUDE_DIRECTORIES(test_common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ) +TARGET_LINK_LIBRARIES(test_common PUBLIC libvisual) + ADD_SUBDIRECTORY(audio_test) ADD_SUBDIRECTORY(video_test) ADD_SUBDIRECTORY(time_test) diff --git a/libvisual/tests/random.cpp b/libvisual/tests/random.cpp new file mode 100644 index 000000000..47e58d064 --- /dev/null +++ b/libvisual/tests/random.cpp @@ -0,0 +1,32 @@ +#include "random.hpp" +#include + +namespace LV::Tests +{ + LV::VideoPtr create_random_video (int width, int height, VisVideoDepth depth) + { + std::random_device device {}; + std::uniform_int_distribution distrib {0, 255}; + + auto video {LV::Video::create (width, height, depth)}; + + auto bytes_per_pixel = video->get_bpp (); + auto pitch = video->get_pitch (); + + auto content_bytes_per_row = bytes_per_pixel * video->get_width (); + + auto pixel_row_ptr = static_cast(video->get_pixels ()); + + for (int y = 0; y < video->get_height (); y++) { + auto pixel = pixel_row_ptr; + for (int c = 0; c < content_bytes_per_row; c++) { + *pixel = distrib (device); + pixel++; + } + + pixel_row_ptr += pitch; + } + + return video; + } +} // LV::Tests namespace diff --git a/libvisual/tests/random.hpp b/libvisual/tests/random.hpp new file mode 100644 index 000000000..c9893b3e8 --- /dev/null +++ b/libvisual/tests/random.hpp @@ -0,0 +1,12 @@ +#ifndef _LV_TESTS_VIDEO_RANDOM_HPP +#define _LV_TESTS_VIDEO_RANDOM_HPP + +#include + +namespace LV::Tests +{ + LV::VideoPtr create_random_video (int width, int height, VisVideoDepth depth); + +} // LV::Tests namespace + +#endif // defined(_LV_TESTS_VIDEO_COMMON_HPP) diff --git a/libvisual/tests/video_test/CMakeLists.txt b/libvisual/tests/video_test/CMakeLists.txt index 6f5244909..65cd4341a 100644 --- a/libvisual/tests/video_test/CMakeLists.txt +++ b/libvisual/tests/video_test/CMakeLists.txt @@ -2,6 +2,10 @@ LV_BUILD_TEST(video_check_test SOURCES video_check_test.cpp ) +LV_BUILD_TEST(video_blit_test + SOURCES video_blit_test.cpp +) + IF(HAVE_SDL) LV_BUILD_TEST(video_scale_test SOURCES video_scale_test.cpp diff --git a/libvisual/tests/video_test/video_blit_test.cpp b/libvisual/tests/video_test/video_blit_test.cpp new file mode 100644 index 000000000..5906747f9 --- /dev/null +++ b/libvisual/tests/video_test/video_blit_test.cpp @@ -0,0 +1,66 @@ +#include "test.h" +#include "random.hpp" +#include +#include + +namespace +{ + LV::VideoPtr clone_video (LV::VideoPtr const& source) + { + auto clone {LV::Video::create (source->get_width (), source->get_height (), source->get_depth ())}; + + assert (clone->get_pitch () == source->get_pitch ()); + std::size_t buffer_size = static_cast (clone->get_pitch () * clone->get_width ()); + + visual_mem_copy (clone->get_pixels (), source->get_pixels (), buffer_size); + + return clone; + } + + void test_blit_overlay_alphasrc () + { + // Check that blit_overlay_alphasrc results are within +/- 1 of exact computation for each colour channel. The + // errors largely arise from the use of 256 instead of 255 as divisor for performance reasons. + + int const test_width = 31; + int const test_height = 31; + + auto source = LV::Tests::create_random_video (test_width, test_height, VISUAL_VIDEO_DEPTH_32BIT); + source->set_compose_type (VISUAL_VIDEO_COMPOSE_TYPE_SRC); + + auto target = LV::Tests::create_random_video (test_width, test_height, VISUAL_VIDEO_DEPTH_32BIT); + + auto actual {clone_video (target)}; + actual->blit (source, 0, 0, true); + + for (int y = 0; y < test_height; y++) { + auto source_pixel = static_cast (source->get_pixel_ptr (y, 0)); + auto target_pixel = static_cast (target->get_pixel_ptr (y, 0)); + auto actual_pixel = static_cast (actual->get_pixel_ptr (y, 0)); + + for (int x = 0; x < test_width; x++) { + LV_TEST_ASSERT (actual_pixel[3] == target_pixel[3]); + + float source_alpha = static_cast (source_pixel[3]) / 255.0f; + uint8_t b = source_alpha * source_pixel[0] + (1.0f - source_alpha) * target_pixel[0]; + uint8_t g = source_alpha * source_pixel[1] + (1.0f - source_alpha) * target_pixel[1]; + uint8_t r = source_alpha * source_pixel[2] + (1.0f - source_alpha) * target_pixel[2]; + + LV_TEST_ASSERT (std::abs (static_cast (actual_pixel[0]) - static_cast (b)) <= 1); + LV_TEST_ASSERT (std::abs (static_cast (actual_pixel[1]) - static_cast (g)) <= 1); + LV_TEST_ASSERT (std::abs (static_cast (actual_pixel[2]) - static_cast (r)) <= 1); + + source_pixel += 4; + target_pixel += 4; + actual_pixel += 4; + } + } + } +} // anonymous namespace + +int main(int argc, char *argv[]) +{ + LV::System::init (argc, argv); + test_blit_overlay_alphasrc (); + LV::System::destroy (); +}