diff options
Diffstat (limited to 'contrib/SDL-3.2.8/test/testautomation_blit.c')
| -rw-r--r-- | contrib/SDL-3.2.8/test/testautomation_blit.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/test/testautomation_blit.c b/contrib/SDL-3.2.8/test/testautomation_blit.c new file mode 100644 index 0000000..a461005 --- /dev/null +++ b/contrib/SDL-3.2.8/test/testautomation_blit.c | |||
| @@ -0,0 +1,215 @@ | |||
| 1 | /** | ||
| 2 | * SDL_BlitSurface bit-perfect rendering test suite written by Isaac Aronson | ||
| 3 | */ | ||
| 4 | |||
| 5 | /* Suppress C4996 VS compiler warnings for unlink() */ | ||
| 6 | #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) | ||
| 7 | #define _CRT_SECURE_NO_DEPRECATE | ||
| 8 | #endif | ||
| 9 | #if defined(_MSC_VER) && !defined(_CRT_NONSTDC_NO_DEPRECATE) | ||
| 10 | #define _CRT_NONSTDC_NO_DEPRECATE | ||
| 11 | #endif | ||
| 12 | |||
| 13 | #include <stdio.h> | ||
| 14 | #ifndef _MSC_VER | ||
| 15 | #include <unistd.h> | ||
| 16 | #else | ||
| 17 | /* Suppress uint64 to uint32 conversion warning within the PRNG engine */ | ||
| 18 | #pragma warning( disable : 4244 ) | ||
| 19 | #endif | ||
| 20 | #include <sys/stat.h> | ||
| 21 | |||
| 22 | #include <SDL3/SDL.h> | ||
| 23 | #include <SDL3/SDL_test.h> | ||
| 24 | #include "testautomation_images.h" | ||
| 25 | |||
| 26 | /* ====== xoroshiro128+ PRNG engine for deterministic blit input ===== */ | ||
| 27 | Uint64 rotl(Uint64 x, int k) { return (x << k) | (x >> (-k & 63)); } | ||
| 28 | Uint64 next(Uint64 state[2]) { | ||
| 29 | Uint64 s0 = state[0], s1 = state[1]; | ||
| 30 | Uint64 result = rotl((s0 + s1) * 9, 29) + s0; | ||
| 31 | state[0] = s0 ^ rotl(s1, 29); | ||
| 32 | state[1] = s0 ^ s1 << 9; | ||
| 33 | return result; | ||
| 34 | } | ||
| 35 | static Uint64 rngState[2] = {1, 2}; | ||
| 36 | Uint32 getRandomUint32(void) { | ||
| 37 | return (Uint32)next(rngState); | ||
| 38 | } | ||
| 39 | /* ================= Test Case Helper Functions ================== */ | ||
| 40 | /* | ||
| 41 | * Resets PRNG state to initialize tests using PRNG | ||
| 42 | */ | ||
| 43 | void SDLCALL blitSetUp(void **arg) { | ||
| 44 | rngState[0] = 1; | ||
| 45 | rngState[1] = 2; | ||
| 46 | } | ||
| 47 | /* | ||
| 48 | * Fill buffer with stream of PRNG pixel data given size | ||
| 49 | */ | ||
| 50 | static Uint32 *fillNextRandomBuffer(Uint32 *buf, const int width, const int height) { | ||
| 51 | int i; | ||
| 52 | for (i = 0; i < width * height; i++) { | ||
| 53 | buf[i] = getRandomUint32(); | ||
| 54 | } | ||
| 55 | return buf; | ||
| 56 | } | ||
| 57 | /* | ||
| 58 | * Generates a stream of PRNG pixel data given length | ||
| 59 | */ | ||
| 60 | static Uint32 *getNextRandomBuffer(const int width, const int height) { | ||
| 61 | Uint32* buf = SDL_malloc(sizeof(Uint32) * width * height); | ||
| 62 | fillNextRandomBuffer(buf, width, height); | ||
| 63 | return buf; | ||
| 64 | } | ||
| 65 | /* | ||
| 66 | * Generates a 800 x 600 surface of PRNG pixel data | ||
| 67 | */ | ||
| 68 | SDL_Surface* getRandomSVGASurface(Uint32 *pixels, SDL_PixelFormat format) { | ||
| 69 | return SDL_CreateSurfaceFrom(800, 600, format, pixels, 800 * 4); | ||
| 70 | } | ||
| 71 | /* | ||
| 72 | * Calculates the FNV-1a hash of input pixel data | ||
| 73 | */ | ||
| 74 | Uint32 FNVHash(Uint32* buf, int length) { | ||
| 75 | const Uint32 fnv_prime = 0x811C9DC5; | ||
| 76 | Uint32 hash = 0; | ||
| 77 | int i; | ||
| 78 | |||
| 79 | for (i = 0; i < length; buf++, i++) | ||
| 80 | { | ||
| 81 | hash *= fnv_prime; | ||
| 82 | hash ^= (*buf); | ||
| 83 | } | ||
| 84 | |||
| 85 | return hash; | ||
| 86 | } | ||
| 87 | /* | ||
| 88 | * Wraps the FNV-1a hash for an input surface's pixels | ||
| 89 | */ | ||
| 90 | Uint32 hashSurfacePixels(SDL_Surface * surface) { | ||
| 91 | Uint64 buffer_size = surface->w * surface->h; | ||
| 92 | return FNVHash(surface->pixels, buffer_size); | ||
| 93 | } | ||
| 94 | /* ================= Test Case Implementation ================== */ | ||
| 95 | /** | ||
| 96 | * Tests rendering a rainbow gradient background onto a blank surface, then rendering a sprite with complex geometry and | ||
| 97 | * transparency on top of said surface, and comparing the result to known accurate renders with a hash. | ||
| 98 | */ | ||
| 99 | static int SDLCALL blit_testExampleApplicationRender(void *arg) { | ||
| 100 | const int width = 32; | ||
| 101 | const int height = 32; | ||
| 102 | const Uint32 correct_hash = 0xe345d7a7; | ||
| 103 | SDL_Surface* dest_surface = SDL_CreateSurface(width, height, SDL_PIXELFORMAT_ARGB8888); | ||
| 104 | SDL_Surface* rainbow_background = SDLTest_ImageBlendingBackground(); | ||
| 105 | SDL_Surface* gearbrain_sprite = SDLTest_ImageBlendingSprite(); | ||
| 106 | // Blit background into "screen" | ||
| 107 | SDL_BlitSurface(rainbow_background, NULL, dest_surface, NULL); | ||
| 108 | // Blit example game sprite onto "screen" | ||
| 109 | SDL_BlitSurface(gearbrain_sprite, NULL, dest_surface, NULL); | ||
| 110 | // Check result | ||
| 111 | const Uint32 hash = hashSurfacePixels(dest_surface); | ||
| 112 | SDLTest_AssertCheck(hash == correct_hash, | ||
| 113 | "Should render identically, expected hash 0x%" SDL_PRIx32 ", got 0x%" SDL_PRIx32, | ||
| 114 | correct_hash, hash); | ||
| 115 | // Clean up | ||
| 116 | SDL_DestroySurface(rainbow_background); | ||
| 117 | SDL_DestroySurface(gearbrain_sprite); | ||
| 118 | SDL_DestroySurface(dest_surface); | ||
| 119 | return TEST_COMPLETED; | ||
| 120 | } | ||
| 121 | /** | ||
| 122 | * Tests rendering PRNG noise onto a surface of PRNG noise, while also testing color shift operations between the | ||
| 123 | * different source and destination pixel formats, without an alpha shuffle, at SVGA resolution. Compares to known | ||
| 124 | * accurate renders with a hash. | ||
| 125 | */ | ||
| 126 | static int SDLCALL blit_testRandomToRandomSVGA(void *arg) { | ||
| 127 | const int width = 800; | ||
| 128 | const int height = 600; | ||
| 129 | const Uint32 correct_hash = 0x42140c5f; | ||
| 130 | // Allocate random buffers | ||
| 131 | Uint32 *dest_pixels = getNextRandomBuffer(width, height); | ||
| 132 | Uint32 *src_pixels = getNextRandomBuffer(width, height); | ||
| 133 | // Create surfaces of different pixel formats | ||
| 134 | SDL_Surface* dest_surface = getRandomSVGASurface(dest_pixels, SDL_PIXELFORMAT_BGRA8888); | ||
| 135 | SDL_Surface* src_surface = getRandomSVGASurface(src_pixels, SDL_PIXELFORMAT_RGBA8888); | ||
| 136 | // Blit surfaces | ||
| 137 | SDL_BlitSurface(src_surface, NULL, dest_surface, NULL); | ||
| 138 | // Check result | ||
| 139 | const Uint32 hash = hashSurfacePixels(dest_surface); | ||
| 140 | SDLTest_AssertCheck(hash == correct_hash, | ||
| 141 | "Should render identically, expected hash 0x%" SDL_PRIx32 ", got 0x%" SDL_PRIx32, | ||
| 142 | correct_hash, hash); | ||
| 143 | // Clean up | ||
| 144 | SDL_DestroySurface(dest_surface); | ||
| 145 | SDL_DestroySurface(src_surface); | ||
| 146 | SDL_free(dest_pixels); | ||
| 147 | SDL_free(src_pixels); | ||
| 148 | return TEST_COMPLETED; | ||
| 149 | } | ||
| 150 | /** | ||
| 151 | * Tests rendering small chunks of 15 by 15px PRNG noise onto an initially blank SVGA surface, while also testing color | ||
| 152 | * shift operations between the different source and destination pixel formats, including an alpha shuffle. Compares to | ||
| 153 | * known accurate renders with a hash. | ||
| 154 | */ | ||
| 155 | static int SDLCALL blit_testRandomToRandomSVGAMultipleIterations(void *arg) { | ||
| 156 | const int width = 800; | ||
| 157 | const int height = 600; | ||
| 158 | const int blit_width = 15; | ||
| 159 | const int blit_height = 15; | ||
| 160 | int i; | ||
| 161 | const Uint32 correct_hash = 0x5d26be78; | ||
| 162 | Uint32 *buf = SDL_malloc(blit_width * blit_height * sizeof(Uint32)); | ||
| 163 | // Create blank source surface | ||
| 164 | SDL_Surface *sourceSurface = SDL_CreateSurface(blit_width, blit_height, SDL_PIXELFORMAT_RGBA8888); | ||
| 165 | // Create blank destination surface | ||
| 166 | SDL_Surface* dest_surface = SDL_CreateSurface(width, height, SDL_PIXELFORMAT_ABGR8888); | ||
| 167 | |||
| 168 | // Perform 250k random blits into random areas of the blank surface | ||
| 169 | for (i = 0; i < 250000; i++) { | ||
| 170 | fillNextRandomBuffer(buf, blit_width, blit_height); | ||
| 171 | SDL_LockSurface(sourceSurface); | ||
| 172 | SDL_memcpy(sourceSurface->pixels, buf, blit_width * blit_height * sizeof(Uint32)); | ||
| 173 | SDL_UnlockSurface(sourceSurface); | ||
| 174 | |||
| 175 | SDL_Rect dest_rect; | ||
| 176 | int location = (int)getRandomUint32(); | ||
| 177 | dest_rect.x = location % (width - 15 - 1); | ||
| 178 | dest_rect.y = location % (height - 15 - 1); | ||
| 179 | |||
| 180 | SDL_BlitSurface(sourceSurface, NULL, dest_surface, &dest_rect); | ||
| 181 | } | ||
| 182 | // Check result | ||
| 183 | const Uint32 hash = hashSurfacePixels(dest_surface); | ||
| 184 | // Clean up | ||
| 185 | SDL_DestroySurface(dest_surface); | ||
| 186 | SDLTest_AssertCheck(hash == correct_hash, | ||
| 187 | "Should render identically, expected hash 0x%" SDL_PRIx32 ", got 0x%" SDL_PRIx32, | ||
| 188 | correct_hash, hash); | ||
| 189 | SDL_DestroySurface(sourceSurface); | ||
| 190 | SDL_free(buf); | ||
| 191 | return TEST_COMPLETED; | ||
| 192 | } | ||
| 193 | |||
| 194 | static const SDLTest_TestCaseReference blitTest1 = { | ||
| 195 | blit_testExampleApplicationRender, "blit_testExampleApplicationRender", | ||
| 196 | "Test example application render.", TEST_ENABLED | ||
| 197 | }; | ||
| 198 | static const SDLTest_TestCaseReference blitTest2 = { | ||
| 199 | blit_testRandomToRandomSVGA, "blit_testRandomToRandomSVGA", | ||
| 200 | "Test SVGA noise render.", TEST_ENABLED | ||
| 201 | }; | ||
| 202 | static const SDLTest_TestCaseReference blitTest3 = { | ||
| 203 | blit_testRandomToRandomSVGAMultipleIterations, "blit_testRandomToRandomSVGAMultipleIterations", | ||
| 204 | "Test SVGA noise render (250k iterations).", TEST_ENABLED | ||
| 205 | }; | ||
| 206 | static const SDLTest_TestCaseReference *blitTests[] = { | ||
| 207 | &blitTest1, &blitTest2, &blitTest3, NULL | ||
| 208 | }; | ||
| 209 | |||
| 210 | SDLTest_TestSuiteReference blitTestSuite = { | ||
| 211 | "Blending", | ||
| 212 | blitSetUp, | ||
| 213 | blitTests, | ||
| 214 | NULL | ||
| 215 | }; | ||
