SDL

Форк
0
/
testautomation_render.c 
1613 строк · 58.0 Кб
1
/**
2
 * Original code: automated SDL platform test written by Edgar Simo "bobbens"
3
 * Extended and extensively updated by aschiffler at ferzkopp dot net
4
 */
5
#include <SDL3/SDL.h>
6
#include <SDL3/SDL_test.h>
7
#include "testautomation_images.h"
8
#include "testautomation_suites.h"
9

10
/* ================= Test Case Implementation ================== */
11

12
#define TESTRENDER_SCREEN_W 80
13
#define TESTRENDER_SCREEN_H 60
14

15

16
#define RENDER_COMPARE_FORMAT SDL_PIXELFORMAT_ARGB8888
17
#define RENDER_COLOR_CLEAR  0xFF000000
18
#define RENDER_COLOR_GREEN  0xFF00FF00
19

20
#define ALLOWABLE_ERROR_OPAQUE  0
21
#define ALLOWABLE_ERROR_BLENDED 0
22

23
#define CHECK_FUNC(FUNC, PARAMS)    \
24
{                                   \
25
    int result = FUNC PARAMS;       \
26
    if (result != 0) {              \
27
        SDLTest_AssertCheck(result == 0, "Validate result from %s, expected: 0, got: %i, %s", #FUNC, result, SDL_GetError()); \
28
    }                               \
29
}
30

31
/* Test window and renderer */
32
static SDL_Window *window = NULL;
33
static SDL_Renderer *renderer = NULL;
34

35
/* Prototypes for helper functions */
36

37
static int clearScreen(void);
38
static void compare(SDL_Surface *reference, int allowable_error);
39
static void compare2x(SDL_Surface *reference, int allowable_error);
40
static SDL_Texture *loadTestFace(void);
41
static int hasDrawColor(void);
42
static int isSupported(int code);
43

44
/**
45
 * Create software renderer for tests
46
 */
47
static void InitCreateRenderer(void *arg)
48
{
49
    int width = 320, height = 240;
50
    const char *renderer_name = NULL;
51
    renderer = NULL;
52
    window = SDL_CreateWindow("render_testCreateRenderer", width, height, 0);
53
    SDLTest_AssertPass("SDL_CreateWindow()");
54
    SDLTest_AssertCheck(window != NULL, "Check SDL_CreateWindow result");
55
    if (window == NULL) {
56
        return;
57
    }
58

59
    renderer = SDL_CreateRenderer(window, renderer_name);
60
    SDLTest_AssertPass("SDL_CreateRenderer()");
61
    SDLTest_AssertCheck(renderer != NULL, "Check SDL_CreateRenderer result: %s", renderer != NULL ? "success" : SDL_GetError());
62
    if (renderer == NULL) {
63
        SDL_DestroyWindow(window);
64
        return;
65
    }
66
}
67

68
/**
69
 * Destroy renderer for tests
70
 */
71
static void CleanupDestroyRenderer(void *arg)
72
{
73
    if (renderer) {
74
        SDL_DestroyRenderer(renderer);
75
        renderer = NULL;
76
        SDLTest_AssertPass("SDL_DestroyRenderer()");
77
    }
78

79
    if (window) {
80
        SDL_DestroyWindow(window);
81
        window = NULL;
82
        SDLTest_AssertPass("SDL_DestroyWindow");
83
    }
84
}
85

86
/**
87
 * Tests call to SDL_GetNumRenderDrivers
88
 *
89
 * \sa SDL_GetNumRenderDrivers
90
 */
91
static int render_testGetNumRenderDrivers(void *arg)
92
{
93
    int n;
94
    n = SDL_GetNumRenderDrivers();
95
    SDLTest_AssertCheck(n >= 1, "Number of renderers >= 1, reported as %i", n);
96
    return TEST_COMPLETED;
97
}
98

99
/**
100
 * Tests the SDL primitives for rendering.
101
 *
102
 * \sa SDL_SetRenderDrawColor
103
 * \sa SDL_RenderFillRect
104
 * \sa SDL_RenderLine
105
 *
106
 */
107
static int render_testPrimitives(void *arg)
108
{
109
    int ret;
110
    int x, y;
111
    SDL_FRect rect;
112
    SDL_Surface *referenceSurface = NULL;
113
    int checkFailCount1;
114
    int checkFailCount2;
115

116
    /* Clear surface. */
117
    clearScreen();
118

119
    /* Need drawcolor or just skip test. */
120
    SDLTest_AssertCheck(hasDrawColor(), "hasDrawColor");
121

122
    /* Draw a rectangle. */
123
    rect.x = 40.0f;
124
    rect.y = 0.0f;
125
    rect.w = 40.0f;
126
    rect.h = 80.0f;
127

128
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 13, 73, 200, SDL_ALPHA_OPAQUE))
129
    CHECK_FUNC(SDL_RenderFillRect, (renderer, &rect))
130

131
    /* Draw a rectangle. */
132
    rect.x = 10.0f;
133
    rect.y = 10.0f;
134
    rect.w = 60.0f;
135
    rect.h = 40.0f;
136
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 200, 0, 100, SDL_ALPHA_OPAQUE))
137
    CHECK_FUNC(SDL_RenderFillRect, (renderer, &rect))
138

139
    /* Draw some points like so:
140
     * X.X.X.X..
141
     * .X.X.X.X.
142
     * X.X.X.X.. */
143
    checkFailCount1 = 0;
144
    checkFailCount2 = 0;
145
    for (y = 0; y < 3; y++) {
146
        for (x = y % 2; x < TESTRENDER_SCREEN_W; x += 2) {
147
            ret = SDL_SetRenderDrawColor(renderer, (Uint8)(x * y), (Uint8)(x * y / 2), (Uint8)(x * y / 3), SDL_ALPHA_OPAQUE);
148
            if (ret != 0) {
149
                checkFailCount1++;
150
            }
151

152
            ret = SDL_RenderPoint(renderer, (float)x, (float)y);
153
            if (ret != 0) {
154
                checkFailCount2++;
155
            }
156
        }
157
    }
158
    SDLTest_AssertCheck(checkFailCount1 == 0, "Validate results from calls to SDL_SetRenderDrawColor, expected: 0, got: %i", checkFailCount1);
159
    SDLTest_AssertCheck(checkFailCount2 == 0, "Validate results from calls to SDL_RenderPoint, expected: 0, got: %i", checkFailCount2);
160

161
    /* Draw some lines. */
162
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE))
163
    CHECK_FUNC(SDL_RenderLine, (renderer, 0.0f, 30.0f, TESTRENDER_SCREEN_W, 30.0f))
164
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 55, 55, 5, SDL_ALPHA_OPAQUE))
165
    CHECK_FUNC(SDL_RenderLine, (renderer, 40.0f, 30.0f, 40.0f, 60.0f))
166
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 5, 105, 105, SDL_ALPHA_OPAQUE))
167
    CHECK_FUNC(SDL_RenderLine, (renderer, 0.0f, 0.0f, 29.0f, 29.0f))
168
    CHECK_FUNC(SDL_RenderLine, (renderer, 29.0f, 30.0f, 0.0f, 59.0f))
169
    CHECK_FUNC(SDL_RenderLine, (renderer, 79.0f, 0.0f, 50.0f, 29.0f))
170
    CHECK_FUNC(SDL_RenderLine, (renderer, 79.0f, 59.0f, 50.0f, 30.0f))
171

172
    /* See if it's the same. */
173
    referenceSurface = SDLTest_ImagePrimitives();
174
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
175

176
    /* Make current */
177
    SDL_RenderPresent(renderer);
178

179
    /* Clean up. */
180
    SDL_DestroySurface(referenceSurface);
181
    referenceSurface = NULL;
182

183
    return TEST_COMPLETED;
184
}
185

186
/**
187
 * Tests the SDL primitives for rendering within a viewport.
188
 *
189
 * \sa SDL_SetRenderDrawColor
190
 * \sa SDL_RenderFillRect
191
 * \sa SDL_RenderLine
192
 *
193
 */
194
static int render_testPrimitivesWithViewport(void *arg)
195
{
196
    SDL_Rect viewport;
197
    SDL_Surface *surface;
198

199
    /* Clear surface. */
200
    clearScreen();
201

202
    viewport.x = 2;
203
    viewport.y = 2;
204
    viewport.w = 2;
205
    viewport.h = 2;
206
    CHECK_FUNC(SDL_SetRenderViewport, (renderer, &viewport));
207

208
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 255, 255, 255, SDL_ALPHA_OPAQUE))
209
    CHECK_FUNC(SDL_RenderLine, (renderer, 0.0f, 0.0f, 1.0f, 1.0f));
210

211
    viewport.x = 3;
212
    viewport.y = 3;
213
    viewport.w = 1;
214
    viewport.h = 1;
215
    CHECK_FUNC(SDL_SetRenderViewport, (renderer, &viewport));
216

217
    surface = SDL_RenderReadPixels(renderer, NULL);
218
    if (surface) {
219
        Uint8 r, g, b, a;
220
        CHECK_FUNC(SDL_ReadSurfacePixel, (surface, 0, 0, &r, &g, &b, &a));
221
        SDLTest_AssertCheck(r == 0xFF && g == 0xFF && b == 0xFF && a == 0xFF, "Validate diagonal line drawing with viewport, expected 0xFFFFFFFF, got 0x%.2x%.2x%.2x%.2x", r, g, b, a);
222
        SDL_DestroySurface(surface);
223
    } else {
224
        SDLTest_AssertCheck(surface != NULL, "Validate result from SDL_RenderReadPixels, got NULL, %s", SDL_GetError());
225
    }
226

227
    return TEST_COMPLETED;
228
}
229

230
/**
231
 * Tests some blitting routines.
232
 *
233
 * \sa SDL_RenderTexture
234
 * \sa SDL_DestroyTexture
235
 */
236
static int render_testBlit(void *arg)
237
{
238
    int ret;
239
    SDL_FRect rect;
240
    SDL_Texture *tface;
241
    SDL_Surface *referenceSurface = NULL;
242
    float tw, th;
243
    float i, j, ni, nj;
244
    int checkFailCount1;
245

246
    /* Clear surface. */
247
    clearScreen();
248

249
    /* Need drawcolor or just skip test. */
250
    SDLTest_AssertCheck(hasDrawColor(), "hasDrawColor)");
251

252
    /* Create face surface. */
253
    tface = loadTestFace();
254
    SDLTest_AssertCheck(tface != NULL, "Verify loadTestFace() result");
255
    if (tface == NULL) {
256
        return TEST_ABORTED;
257
    }
258

259
    /* Constant values. */
260
    CHECK_FUNC(SDL_GetTextureSize, (tface, &tw, &th))
261
    rect.w = tw;
262
    rect.h = th;
263
    ni = TESTRENDER_SCREEN_W - tw;
264
    nj = TESTRENDER_SCREEN_H - th;
265

266
    /* Loop blit. */
267
    checkFailCount1 = 0;
268
    for (j = 0; j <= nj; j += 4) {
269
        for (i = 0; i <= ni; i += 4) {
270
            /* Blitting. */
271
            rect.x = i;
272
            rect.y = j;
273
            ret = SDL_RenderTexture(renderer, tface, NULL, &rect);
274
            if (ret != 0) {
275
                checkFailCount1++;
276
            }
277
        }
278
    }
279
    SDLTest_AssertCheck(checkFailCount1 == 0, "Validate results from calls to SDL_RenderTexture, expected: 0, got: %i", checkFailCount1);
280

281
    /* See if it's the same */
282
    referenceSurface = SDLTest_ImageBlit();
283
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
284

285
    /* Make current */
286
    SDL_RenderPresent(renderer);
287

288
    /* Clean up. */
289
    SDL_DestroyTexture(tface);
290
    SDL_DestroySurface(referenceSurface);
291
    referenceSurface = NULL;
292

293
    return TEST_COMPLETED;
294
}
295

296
/**
297
 * Tests tiled blitting routines.
298
 */
299
static int render_testBlitTiled(void *arg)
300
{
301
    int ret;
302
    SDL_FRect rect;
303
    SDL_Texture *tface;
304
    SDL_Surface *referenceSurface = NULL;
305
    SDL_Surface *referenceSurface2x = NULL;
306

307
    /* Create face surface. */
308
    tface = loadTestFace();
309
    SDLTest_AssertCheck(tface != NULL, "Verify loadTestFace() result");
310
    if (tface == NULL) {
311
        return TEST_ABORTED;
312
    }
313
    SDL_SetTextureScaleMode(tface, SDL_SCALEMODE_NEAREST);  /* So 2x scaling is pixel perfect */
314

315
    /* Tiled blit - 1.0 scale */
316
    {
317
        /* Clear surface. */
318
        clearScreen();
319

320
        /* Tiled blit. */
321
        rect.x = 0.0f;
322
        rect.y = 0.0f;
323
        rect.w = (float)TESTRENDER_SCREEN_W;
324
        rect.h = (float)TESTRENDER_SCREEN_H;
325
        ret = SDL_RenderTextureTiled(renderer, tface, NULL, 1.0f, &rect);
326
        SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTextureTiled, expected: 0, got: %i", ret);
327

328
        /* See if it's the same */
329
        referenceSurface = SDLTest_ImageBlitTiled();
330
        compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
331

332
        /* Make current */
333
        SDL_RenderPresent(renderer);
334
    }
335

336
    /* Tiled blit - 2.0 scale */
337
    {
338
        /* Clear surface. */
339
        clearScreen();
340

341
        /* Tiled blit. */
342
        rect.x = 0.0f;
343
        rect.y = 0.0f;
344
        rect.w = (float)TESTRENDER_SCREEN_W * 2;
345
        rect.h = (float)TESTRENDER_SCREEN_H * 2;
346
        ret = SDL_RenderTextureTiled(renderer, tface, NULL, 2.0f, &rect);
347
        SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTextureTiled, expected: 0, got: %i", ret);
348

349
        /* See if it's the same */
350
        referenceSurface2x = SDL_CreateSurface(referenceSurface->w * 2, referenceSurface->h * 2, referenceSurface->format);
351
        SDL_BlitSurfaceScaled(referenceSurface, NULL, referenceSurface2x, NULL, SDL_SCALEMODE_NEAREST);
352
        SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_BlitSurfaceScaled, expected: 0, got: %i", ret);
353
        compare2x(referenceSurface2x, ALLOWABLE_ERROR_OPAQUE);
354

355
        /* Make current */
356
        SDL_RenderPresent(renderer);
357
    }
358

359
    /* Clean up. */
360
    SDL_DestroyTexture(tface);
361
    SDL_DestroySurface(referenceSurface);
362
    SDL_DestroySurface(referenceSurface2x);
363
    referenceSurface = NULL;
364

365
    return TEST_COMPLETED;
366
}
367

368
static const Uint8 COLOR_SEPARATION = 85;
369

370
static void Fill9GridReferenceSurface(SDL_Surface *surface, int left_width, int right_width, int top_height, int bottom_height)
371
{
372
    SDL_Rect rect;
373

374
    // Upper left
375
    rect.x = 0;
376
    rect.y = 0;
377
    rect.w = left_width;
378
    rect.h = top_height;
379
    SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 1 * COLOR_SEPARATION, 1 * COLOR_SEPARATION, 0));
380

381
    // Top
382
    rect.x = left_width;
383
    rect.y = 0;
384
    rect.w = surface->w - left_width - right_width;
385
    rect.h = top_height;
386
    SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 2 * COLOR_SEPARATION, 1 * COLOR_SEPARATION, 0));
387

388
    // Upper right
389
    rect.x = surface->w - right_width;
390
    rect.y = 0;
391
    rect.w = right_width;
392
    rect.h = top_height;
393
    SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 3 * COLOR_SEPARATION, 1 * COLOR_SEPARATION, 0));
394

395
    // Left
396
    rect.x = 0;
397
    rect.y = top_height;
398
    rect.w = left_width;
399
    rect.h = surface->h - top_height - bottom_height;
400
    SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 1 * COLOR_SEPARATION, 2 * COLOR_SEPARATION, 0));
401

402
    // Center
403
    rect.x = left_width;
404
    rect.y = top_height;
405
    rect.w = surface->w - right_width - left_width;
406
    rect.h = surface->h - top_height - bottom_height;
407
    SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 2 * COLOR_SEPARATION, 2 * COLOR_SEPARATION, 0));
408

409
    // Right
410
    rect.x = surface->w - right_width;
411
    rect.y = top_height;
412
    rect.w = right_width;
413
    rect.h = surface->h - top_height - bottom_height;
414
    SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 3 * COLOR_SEPARATION, 2 * COLOR_SEPARATION, 0));
415

416
    // Lower left
417
    rect.x = 0;
418
    rect.y = surface->h - bottom_height;
419
    rect.w = left_width;
420
    rect.h = bottom_height;
421
    SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 1 * COLOR_SEPARATION, 3 * COLOR_SEPARATION, 0));
422

423
    // Bottom
424
    rect.x = left_width;
425
    rect.y = surface->h - bottom_height;
426
    rect.w = surface->w - left_width - right_width;
427
    rect.h = bottom_height;
428
    SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 2 * COLOR_SEPARATION, 3 * COLOR_SEPARATION, 0));
429

430
    // Lower right
431
    rect.x = surface->w - right_width;
432
    rect.y = surface->h - bottom_height;
433
    rect.w = right_width;
434
    rect.h = bottom_height;
435
    SDL_FillSurfaceRect(surface, &rect, SDL_MapSurfaceRGB(surface, 3 * COLOR_SEPARATION, 3 * COLOR_SEPARATION, 0));
436
}
437

438
/**
439
 *  Tests 9-grid blitting.
440
 */
441
static int render_testBlit9Grid(void *arg)
442
{
443
    SDL_Surface *referenceSurface = NULL;
444
    SDL_Surface *source = NULL;
445
    SDL_Texture *texture;
446
    int x, y;
447
    SDL_FRect rect;
448
    int ret = 0;
449

450
    /* Create source surface */
451
    source = SDL_CreateSurface(3, 3, SDL_PIXELFORMAT_RGBA32);
452
    SDLTest_AssertCheck(source != NULL, "Verify source surface is not NULL");
453
    for (y = 0; y < 3; ++y) {
454
        for (x = 0; x < 3; ++x) {
455
            SDL_WriteSurfacePixel(source, x, y, (Uint8)((1 + x) * COLOR_SEPARATION), (Uint8)((1 + y) * COLOR_SEPARATION), 0, 255);
456
        }
457
    }
458
    texture = SDL_CreateTextureFromSurface(renderer, source);
459
    SDLTest_AssertCheck(texture != NULL, "Verify source texture is not NULL");
460
    ret = SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
461
    SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_SetTextureScaleMode, expected: 0, got: %i", ret);
462

463
    /* 9-grid blit - 1.0 scale */
464
    {
465
        SDLTest_Log("9-grid blit - 1.0 scale");
466
        /* Create reference surface */
467
        SDL_DestroySurface(referenceSurface);
468
        referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, SDL_PIXELFORMAT_RGBA32);
469
        SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
470
        Fill9GridReferenceSurface(referenceSurface, 1, 1, 1, 1);
471

472
        /* Clear surface. */
473
        clearScreen();
474

475
        /* Tiled blit. */
476
        rect.x = 0.0f;
477
        rect.y = 0.0f;
478
        rect.w = (float)TESTRENDER_SCREEN_W;
479
        rect.h = (float)TESTRENDER_SCREEN_H;
480
        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, &rect);
481
        SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTexture9Grid, expected: 0, got: %i", ret);
482

483
        /* See if it's the same */
484
        compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
485

486
        /* Make current */
487
        SDL_RenderPresent(renderer);
488
    }
489

490
    /* 9-grid blit - 2.0 scale */
491
    {
492
        SDLTest_Log("9-grid blit - 2.0 scale");
493
        /* Create reference surface */
494
        SDL_DestroySurface(referenceSurface);
495
        referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, SDL_PIXELFORMAT_RGBA32);
496
        SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
497
        Fill9GridReferenceSurface(referenceSurface, 2, 2, 2, 2);
498

499
        /* Clear surface. */
500
        clearScreen();
501

502
        /* Tiled blit. */
503
        rect.x = 0.0f;
504
        rect.y = 0.0f;
505
        rect.w = (float)TESTRENDER_SCREEN_W;
506
        rect.h = (float)TESTRENDER_SCREEN_H;
507
        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, &rect);
508
        SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTexture9Grid, expected: 0, got: %i", ret);
509

510
        /* See if it's the same */
511
        compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
512

513
        /* Make current */
514
        SDL_RenderPresent(renderer);
515
    }
516

517
    /* Clean up. */
518
    SDL_DestroySurface(source);
519
    SDL_DestroyTexture(texture);
520

521
    /* Create complex source surface */
522
    source = SDL_CreateSurface(5, 5, SDL_PIXELFORMAT_RGBA32);
523
    SDLTest_AssertCheck(source != NULL, "Verify source surface is not NULL");
524
    SDL_WriteSurfacePixel(source, 0, 0, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
525
    SDL_WriteSurfacePixel(source, 1, 0, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
526
    SDL_WriteSurfacePixel(source, 2, 0, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
527
    SDL_WriteSurfacePixel(source, 3, 0, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
528
    SDL_WriteSurfacePixel(source, 4, 0, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((1) * COLOR_SEPARATION), 0, 255);
529

530
    SDL_WriteSurfacePixel(source, 0, 1, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
531
    SDL_WriteSurfacePixel(source, 1, 1, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
532
    SDL_WriteSurfacePixel(source, 2, 1, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
533
    SDL_WriteSurfacePixel(source, 3, 1, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
534
    SDL_WriteSurfacePixel(source, 4, 1, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
535

536
    SDL_WriteSurfacePixel(source, 0, 2, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
537
    SDL_WriteSurfacePixel(source, 1, 2, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
538
    SDL_WriteSurfacePixel(source, 2, 2, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
539
    SDL_WriteSurfacePixel(source, 3, 2, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
540
    SDL_WriteSurfacePixel(source, 4, 2, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((2) * COLOR_SEPARATION), 0, 255);
541

542
    SDL_WriteSurfacePixel(source, 0, 3, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
543
    SDL_WriteSurfacePixel(source, 1, 3, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
544
    SDL_WriteSurfacePixel(source, 2, 3, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
545
    SDL_WriteSurfacePixel(source, 3, 3, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
546
    SDL_WriteSurfacePixel(source, 4, 3, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
547

548
    SDL_WriteSurfacePixel(source, 0, 4, (Uint8)((1) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
549
    SDL_WriteSurfacePixel(source, 1, 4, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
550
    SDL_WriteSurfacePixel(source, 2, 4, (Uint8)((2) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
551
    SDL_WriteSurfacePixel(source, 3, 4, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
552
    SDL_WriteSurfacePixel(source, 4, 4, (Uint8)((3) * COLOR_SEPARATION), (Uint8)((3) * COLOR_SEPARATION), 0, 255);
553

554
    texture = SDL_CreateTextureFromSurface(renderer, source);
555
    SDLTest_AssertCheck(texture != NULL, "Verify source texture is not NULL");
556
    ret = SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
557
    SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_SetTextureScaleMode, expected: 0, got: %i", ret);
558

559
    /* complex 9-grid blit - 1.0 scale */
560
    {
561
        SDLTest_Log("complex 9-grid blit - 1.0 scale");
562
        /* Create reference surface */
563
        SDL_DestroySurface(referenceSurface);
564
        referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, SDL_PIXELFORMAT_RGBA32);
565
        SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
566
        Fill9GridReferenceSurface(referenceSurface, 1, 2, 1, 2);
567

568
        /* Clear surface. */
569
        clearScreen();
570

571
        /* Tiled blit. */
572
        rect.x = 0.0f;
573
        rect.y = 0.0f;
574
        rect.w = (float)TESTRENDER_SCREEN_W;
575
        rect.h = (float)TESTRENDER_SCREEN_H;
576
        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 2.0f, 1.0f, 2.0f, 1.0f, &rect);
577
        SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTexture9Grid, expected: 0, got: %i", ret);
578

579
        /* See if it's the same */
580
        compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
581

582
        /* Make current */
583
        SDL_RenderPresent(renderer);
584
    }
585

586
    /* complex 9-grid blit - 2.0 scale */
587
    {
588
        SDLTest_Log("complex 9-grid blit - 2.0 scale");
589
        /* Create reference surface */
590
        SDL_DestroySurface(referenceSurface);
591
        referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, SDL_PIXELFORMAT_RGBA32);
592
        SDLTest_AssertCheck(referenceSurface != NULL, "Verify reference surface is not NULL");
593
        Fill9GridReferenceSurface(referenceSurface, 2, 4, 2, 4);
594

595
        /* Clear surface. */
596
        clearScreen();
597

598
        /* Tiled blit. */
599
        rect.x = 0.0f;
600
        rect.y = 0.0f;
601
        rect.w = (float)TESTRENDER_SCREEN_W;
602
        rect.h = (float)TESTRENDER_SCREEN_H;
603
        ret = SDL_RenderTexture9Grid(renderer, texture, NULL, 1.0f, 2.0f, 1.0f, 2.0f, 2.0f, &rect);
604
        SDLTest_AssertCheck(ret == 0, "Validate results from call to SDL_RenderTexture9Grid, expected: 0, got: %i", ret);
605

606
        /* See if it's the same */
607
        compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
608

609
        /* Make current */
610
        SDL_RenderPresent(renderer);
611
    }
612

613
    /* Clean up. */
614
    SDL_DestroySurface(referenceSurface);
615
    SDL_DestroySurface(source);
616
    SDL_DestroyTexture(texture);
617

618
    return TEST_COMPLETED;
619
}
620

621
/**
622
 * Blits doing color tests.
623
 *
624
 * \sa SDL_SetTextureColorMod
625
 * \sa SDL_RenderTexture
626
 * \sa SDL_DestroyTexture
627
 */
628
static int render_testBlitColor(void *arg)
629
{
630
    int ret;
631
    SDL_FRect rect;
632
    SDL_Texture *tface;
633
    SDL_Surface *referenceSurface = NULL;
634
    float tw, th;
635
    int i, j, ni, nj;
636
    int checkFailCount1;
637
    int checkFailCount2;
638

639
    /* Clear surface. */
640
    clearScreen();
641

642
    /* Create face surface. */
643
    tface = loadTestFace();
644
    SDLTest_AssertCheck(tface != NULL, "Verify loadTestFace() result");
645
    if (tface == NULL) {
646
        return TEST_ABORTED;
647
    }
648

649
    /* Constant values. */
650
    CHECK_FUNC(SDL_GetTextureSize, (tface, &tw, &th))
651
    rect.w = tw;
652
    rect.h = th;
653
    ni = TESTRENDER_SCREEN_W - (int)tw;
654
    nj = TESTRENDER_SCREEN_H - (int)th;
655

656
    /* Test blitting with color mod. */
657
    checkFailCount1 = 0;
658
    checkFailCount2 = 0;
659
    for (j = 0; j <= nj; j += 4) {
660
        for (i = 0; i <= ni; i += 4) {
661
            /* Set color mod. */
662
            ret = SDL_SetTextureColorMod(tface, (Uint8)((255 / nj) * j), (Uint8)((255 / ni) * i), (Uint8)((255 / nj) * j));
663
            if (ret != 0) {
664
                checkFailCount1++;
665
            }
666

667
            /* Blitting. */
668
            rect.x = (float)i;
669
            rect.y = (float)j;
670
            ret = SDL_RenderTexture(renderer, tface, NULL, &rect);
671
            if (ret != 0) {
672
                checkFailCount2++;
673
            }
674
        }
675
    }
676
    SDLTest_AssertCheck(checkFailCount1 == 0, "Validate results from calls to SDL_SetTextureColorMod, expected: 0, got: %i", checkFailCount1);
677
    SDLTest_AssertCheck(checkFailCount2 == 0, "Validate results from calls to SDL_RenderTexture, expected: 0, got: %i", checkFailCount2);
678

679
    /* See if it's the same. */
680
    referenceSurface = SDLTest_ImageBlitColor();
681
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
682

683
    /* Make current */
684
    SDL_RenderPresent(renderer);
685

686
    /* Clean up. */
687
    SDL_DestroyTexture(tface);
688
    SDL_DestroySurface(referenceSurface);
689
    referenceSurface = NULL;
690

691
    return TEST_COMPLETED;
692
}
693

694
typedef enum TestRenderOperation
695
{
696
    TEST_RENDER_POINT,
697
    TEST_RENDER_LINE,
698
    TEST_RENDER_RECT,
699
    TEST_RENDER_COPY_XRGB,
700
    TEST_RENDER_COPY_ARGB,
701
} TestRenderOperation;
702

703
/**
704
 * Helper that tests a specific operation and blend mode, -1 for color mod, -2 for alpha mod
705
 */
706
static void testBlendModeOperation(TestRenderOperation op, int mode, SDL_PixelFormat dst_format)
707
{
708
    /* Allow up to 2 delta from theoretical value to account for rounding error.
709
     * We allow 2 rounding errors because the software renderer breaks drawing operations into alpha multiplication and a separate blend operation.
710
     */
711
    const int MAXIMUM_ERROR = 2;
712
    int ret;
713
    SDL_Texture *src = NULL;
714
    SDL_Texture *dst;
715
    SDL_Surface *result;
716
    Uint8 srcR = 10, srcG = 128, srcB = 240, srcA = 100;
717
    Uint8 dstR = 128, dstG = 128, dstB = 128, dstA = 128;
718
    Uint8 expectedR, expectedG, expectedB, expectedA;
719
    Uint8 actualR, actualG, actualB, actualA;
720
    int deltaR, deltaG, deltaB, deltaA;
721
    const char *operation = "UNKNOWN";
722
    const char *mode_name = "UNKNOWN";
723

724
    /* Create dst surface */
725
    dst = SDL_CreateTexture(renderer, dst_format, SDL_TEXTUREACCESS_TARGET, 3, 3);
726
    SDLTest_AssertCheck(dst != NULL, "Verify dst surface is not NULL");
727
    if (dst == NULL) {
728
        return;
729
    }
730
    if (SDL_ISPIXELFORMAT_ALPHA(dst_format)) {
731
        SDL_BlendMode blendMode = SDL_BLENDMODE_NONE;
732
        ret = SDL_GetTextureBlendMode(dst, &blendMode);
733
        SDLTest_AssertCheck(ret == 0, "Verify result from SDL_GetTextureBlendMode(), expected: 0, got: %i", ret);
734
        SDLTest_AssertCheck(blendMode == SDL_BLENDMODE_BLEND, "Verify alpha texture blend mode, expected %d, got %" SDL_PRIu32, SDL_BLENDMODE_BLEND, blendMode);
735
    }
736

737
    /* Set as render target */
738
    SDL_SetRenderTarget(renderer, dst);
739

740
    /* Clear surface. */
741
    if (!SDL_ISPIXELFORMAT_ALPHA(dst_format)) {
742
        dstA = 255;
743
    }
744
    ret = SDL_SetRenderDrawColor(renderer, dstR, dstG, dstB, dstA);
745
    SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetRenderDrawColor(), expected: 0, got: %i", ret);
746
    ret = SDL_RenderClear(renderer);
747
    SDLTest_AssertPass("Call to SDL_RenderClear()");
748
    SDLTest_AssertCheck(ret == 0, "Verify result from SDL_RenderClear, expected: 0, got: %i", ret);
749

750
    if (op == TEST_RENDER_COPY_XRGB || op == TEST_RENDER_COPY_ARGB) {
751
        Uint8 pixels[4];
752

753
        /* Create src surface */
754
        src = SDL_CreateTexture(renderer, op == TEST_RENDER_COPY_XRGB ? SDL_PIXELFORMAT_RGBX32 : SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, 1, 1);
755
        SDLTest_AssertCheck(src != NULL, "Verify src surface is not NULL");
756
        if (src == NULL) {
757
            return;
758
        }
759

760
        /* Clear surface. */
761
        if (op == TEST_RENDER_COPY_XRGB) {
762
            srcA = 255;
763
        }
764
        pixels[0] = srcR;
765
        pixels[1] = srcG;
766
        pixels[2] = srcB;
767
        pixels[3] = srcA;
768
        SDL_UpdateTexture(src, NULL, pixels, sizeof(pixels));
769

770
        /* Set blend mode. */
771
        if (mode >= 0) {
772
            ret = SDL_SetTextureBlendMode(src, (SDL_BlendMode)mode);
773
            SDLTest_AssertPass("Call to SDL_SetTextureBlendMode()");
774
            SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetTextureBlendMode(..., %i), expected: 0, got: %i", mode, ret);
775
        } else {
776
            ret = SDL_SetTextureBlendMode(src, SDL_BLENDMODE_BLEND);
777
            SDLTest_AssertPass("Call to SDL_SetTextureBlendMode()");
778
            SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetTextureBlendMode(..., %i), expected: 0, got: %i", mode, ret);
779
        }
780
    } else {
781
        /* Set draw color */
782
        ret = SDL_SetRenderDrawColor(renderer, srcR, srcG, srcB, srcA);
783
        SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetRenderDrawColor(), expected: 0, got: %i", ret);
784

785
        /* Set blend mode. */
786
        if (mode >= 0) {
787
            ret = SDL_SetRenderDrawBlendMode(renderer, (SDL_BlendMode)mode);
788
            SDLTest_AssertPass("Call to SDL_SetRenderDrawBlendMode()");
789
            SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetRenderDrawBlendMode(..., %i), expected: 0, got: %i", mode, ret);
790
        } else {
791
            ret = SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
792
            SDLTest_AssertPass("Call to SDL_SetRenderDrawBlendMode()");
793
            SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetRenderDrawBlendMode(..., %i), expected: 0, got: %i", mode, ret);
794
        }
795
    }
796

797
    /* Test blend mode. */
798
#define FLOAT(X)    ((float)X / 255.0f)
799
    switch (mode) {
800
    case -1:
801
        mode_name = "color modulation";
802
        ret = SDL_SetTextureColorMod(src, srcR, srcG, srcB);
803
        SDLTest_AssertCheck(ret == 0, "Validate results from calls to SDL_SetTextureColorMod, expected: 0, got: %i", ret);
804
        expectedR = (Uint8)SDL_roundf(SDL_clamp((FLOAT(srcR) * FLOAT(srcR)) * FLOAT(srcA) + FLOAT(dstR) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
805
        expectedG = (Uint8)SDL_roundf(SDL_clamp((FLOAT(srcG) * FLOAT(srcG)) * FLOAT(srcA) + FLOAT(dstG) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
806
        expectedB = (Uint8)SDL_roundf(SDL_clamp((FLOAT(srcB) * FLOAT(srcB)) * FLOAT(srcA) + FLOAT(dstB) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
807
        expectedA = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcA) + FLOAT(dstA) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
808
        break;
809
    case -2:
810
        mode_name = "alpha modulation";
811
        ret = SDL_SetTextureAlphaMod(src, srcA);
812
        SDLTest_AssertCheck(ret == 0, "Validate results from calls to SDL_SetTextureAlphaMod, expected: 0, got: %i", ret);
813
        expectedR = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcR) * (FLOAT(srcA) * FLOAT(srcA)) + FLOAT(dstR) * (1.0f - (FLOAT(srcA) * FLOAT(srcA))), 0.0f, 1.0f) * 255.0f);
814
        expectedG = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcG) * (FLOAT(srcA) * FLOAT(srcA)) + FLOAT(dstG) * (1.0f - (FLOAT(srcA) * FLOAT(srcA))), 0.0f, 1.0f) * 255.0f);
815
        expectedB = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcB) * (FLOAT(srcA) * FLOAT(srcA)) + FLOAT(dstB) * (1.0f - (FLOAT(srcA) * FLOAT(srcA))), 0.0f, 1.0f) * 255.0f);
816
        expectedA = (Uint8)SDL_roundf(SDL_clamp((FLOAT(srcA) * FLOAT(srcA)) + FLOAT(dstA) * (1.0f - (FLOAT(srcA) * FLOAT(srcA))), 0.0f, 1.0f) * 255.0f);
817
        break;
818
    case SDL_BLENDMODE_NONE:
819
        mode_name = "SDL_BLENDMODE_NONE";
820
        expectedR = srcR;
821
        expectedG = srcG;
822
        expectedB = srcB;
823
        expectedA = SDL_ISPIXELFORMAT_ALPHA(dst_format) ? srcA : 255;
824
        break;
825
    case SDL_BLENDMODE_BLEND:
826
        mode_name = "SDL_BLENDMODE_BLEND";
827
        expectedR = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcR) * FLOAT(srcA) + FLOAT(dstR) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
828
        expectedG = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcG) * FLOAT(srcA) + FLOAT(dstG) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
829
        expectedB = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcB) * FLOAT(srcA) + FLOAT(dstB) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
830
        expectedA = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcA) + FLOAT(dstA) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
831
        break;
832
    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
833
        mode_name = "SDL_BLENDMODE_BLEND_PREMULTIPLIED";
834
        expectedR = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcR) + FLOAT(dstR) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
835
        expectedG = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcG) + FLOAT(dstG) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
836
        expectedB = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcB) + FLOAT(dstB) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
837
        expectedA = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcA) + FLOAT(dstA) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
838
        break;
839
    case SDL_BLENDMODE_ADD:
840
        mode_name = "SDL_BLENDMODE_ADD";
841
        expectedR = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcR) * FLOAT(srcA) + FLOAT(dstR), 0.0f, 1.0f) * 255.0f);
842
        expectedG = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcG) * FLOAT(srcA) + FLOAT(dstG), 0.0f, 1.0f) * 255.0f);
843
        expectedB = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcB) * FLOAT(srcA) + FLOAT(dstB), 0.0f, 1.0f) * 255.0f);
844
        expectedA = dstA;
845
        break;
846
    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
847
        mode_name = "SDL_BLENDMODE_ADD_PREMULTIPLIED";
848
        expectedR = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcR) + FLOAT(dstR), 0.0f, 1.0f) * 255.0f);
849
        expectedG = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcG) + FLOAT(dstG), 0.0f, 1.0f) * 255.0f);
850
        expectedB = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcB) + FLOAT(dstB), 0.0f, 1.0f) * 255.0f);
851
        expectedA = dstA;
852
        break;
853
    case SDL_BLENDMODE_MOD:
854
        mode_name = "SDL_BLENDMODE_MOD";
855
        expectedR = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcR) * FLOAT(dstR), 0.0f, 1.0f) * 255.0f);
856
        expectedG = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcG) * FLOAT(dstG), 0.0f, 1.0f) * 255.0f);
857
        expectedB = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcB) * FLOAT(dstB), 0.0f, 1.0f) * 255.0f);
858
        expectedA = dstA;
859
        break;
860
    case SDL_BLENDMODE_MUL:
861
        mode_name = "SDL_BLENDMODE_MUL";
862
        expectedR = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcR) * FLOAT(dstR) + FLOAT(dstR) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
863
        expectedG = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcG) * FLOAT(dstG) + FLOAT(dstG) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
864
        expectedB = (Uint8)SDL_roundf(SDL_clamp(FLOAT(srcB) * FLOAT(dstB) + FLOAT(dstB) * (1.0f - FLOAT(srcA)), 0.0f, 1.0f) * 255.0f);
865
        expectedA = dstA;
866
        break;
867
    default:
868
        SDLTest_LogError("Invalid blending mode: %d", mode);
869
        return;
870
    }
871

872
    switch (op) {
873
    case TEST_RENDER_POINT:
874
        operation = "render point";
875
        ret = SDL_RenderPoint(renderer, 0.0f, 0.0f);
876
        SDLTest_AssertCheck(ret == 0, "Validate results from calls to SDL_RenderPoint, expected: 0, got: %i", ret);
877
        break;
878
    case TEST_RENDER_LINE:
879
        operation = "render line";
880
        ret = SDL_RenderLine(renderer, 0.0f, 0.0f, 2.0f, 2.0f);
881
        SDLTest_AssertCheck(ret == 0, "Validate results from calls to SDL_RenderLine, expected: 0, got: %i", ret);
882
        break;
883
    case TEST_RENDER_RECT:
884
        operation = "render rect";
885
        ret = SDL_RenderFillRect(renderer, NULL);
886
        SDLTest_AssertCheck(ret == 0, "Validate results from calls to SDL_RenderFillRect, expected: 0, got: %i", ret);
887
        break;
888
    case TEST_RENDER_COPY_XRGB:
889
    case TEST_RENDER_COPY_ARGB:
890
        operation = (op == TEST_RENDER_COPY_XRGB) ? "render XRGB" : "render ARGB";
891
        ret = SDL_RenderTexture(renderer, src, NULL, NULL);
892
        SDLTest_AssertCheck(ret == 0, "Validate results from calls to SDL_RenderTexture, expected: 0, got: %i", ret);
893
        break;
894
    default:
895
        SDLTest_LogError("Invalid blending operation: %d", op);
896
        return;
897
    }
898

899
    result = SDL_RenderReadPixels(renderer, NULL);
900
    SDL_ReadSurfacePixel(result, 0, 0, &actualR, &actualG, &actualB, &actualA);
901
    deltaR = SDL_abs((int)actualR - expectedR);
902
    deltaG = SDL_abs((int)actualG - expectedG);
903
    deltaB = SDL_abs((int)actualB - expectedB);
904
    deltaA = SDL_abs((int)actualA - expectedA);
905
    SDLTest_AssertCheck(
906
        deltaR <= MAXIMUM_ERROR &&
907
        deltaG <= MAXIMUM_ERROR &&
908
        deltaB <= MAXIMUM_ERROR &&
909
        deltaA <= MAXIMUM_ERROR,
910
        "Checking %s %s operation results, expected %d,%d,%d,%d, got %d,%d,%d,%d",
911
            operation, mode_name,
912
            expectedR, expectedG, expectedB, expectedA, actualR, actualG, actualB, actualA);
913

914
    /* Clean up */
915
    SDL_DestroySurface(result);
916
    SDL_DestroyTexture(src);
917
    SDL_DestroyTexture(dst);
918
}
919

920
static void testBlendMode(int mode)
921
{
922
    const TestRenderOperation operations[] = {
923
        TEST_RENDER_POINT,
924
        TEST_RENDER_LINE,
925
        TEST_RENDER_RECT,
926
        TEST_RENDER_COPY_XRGB,
927
        TEST_RENDER_COPY_ARGB
928
    };
929
    const SDL_PixelFormat dst_formats[] = {
930
        SDL_PIXELFORMAT_XRGB8888, SDL_PIXELFORMAT_ARGB8888
931
    };
932
    int i, j;
933

934
    for (i = 0; i < SDL_arraysize(operations); ++i) {
935
        for (j = 0; j < SDL_arraysize(dst_formats); ++j) {
936
            TestRenderOperation op = operations[i];
937

938
            if (mode < 0) {
939
                if (op != TEST_RENDER_COPY_XRGB && op != TEST_RENDER_COPY_ARGB) {
940
                    /* Unsupported mode for this operation */
941
                    continue;
942
                }
943
            }
944
            testBlendModeOperation(op, mode, dst_formats[j]);
945
        }
946
    }
947
}
948

949
/**
950
 * Tests render operations with blend modes
951
 */
952
static int render_testBlendModes(void *arg)
953
{
954
    testBlendMode(-1);
955
    testBlendMode(-2);
956
    testBlendMode(SDL_BLENDMODE_NONE);
957
    testBlendMode(SDL_BLENDMODE_BLEND);
958
    testBlendMode(SDL_BLENDMODE_BLEND_PREMULTIPLIED);
959
    testBlendMode(SDL_BLENDMODE_ADD);
960
    testBlendMode(SDL_BLENDMODE_ADD_PREMULTIPLIED);
961
    testBlendMode(SDL_BLENDMODE_MOD);
962
    testBlendMode(SDL_BLENDMODE_MUL);
963

964
    return TEST_COMPLETED;
965
}
966

967
/**
968
 * Test viewport
969
 */
970
static int render_testViewport(void *arg)
971
{
972
    SDL_Surface *referenceSurface;
973
    SDL_Rect viewport;
974

975
    viewport.x = TESTRENDER_SCREEN_W / 3;
976
    viewport.y = TESTRENDER_SCREEN_H / 3;
977
    viewport.w = TESTRENDER_SCREEN_W / 2;
978
    viewport.h = TESTRENDER_SCREEN_H / 2;
979

980
    /* Create expected result */
981
    referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, RENDER_COMPARE_FORMAT);
982
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, NULL, RENDER_COLOR_CLEAR))
983
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, &viewport, RENDER_COLOR_GREEN))
984

985
    /* Clear surface. */
986
    clearScreen();
987

988
    /* Set the viewport and do a fill operation */
989
    CHECK_FUNC(SDL_SetRenderViewport, (renderer, &viewport))
990
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE))
991
    CHECK_FUNC(SDL_RenderFillRect, (renderer, NULL))
992
    CHECK_FUNC(SDL_SetRenderViewport, (renderer, NULL))
993

994
    /* Check to see if final image matches. */
995
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
996

997
    /*
998
     * Verify that clear ignores the viewport
999
     */
1000

1001
    /* Create expected result */
1002
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, NULL, RENDER_COLOR_GREEN))
1003

1004
    /* Clear surface. */
1005
    clearScreen();
1006

1007
    /* Set the viewport and do a clear operation */
1008
    CHECK_FUNC(SDL_SetRenderViewport, (renderer, &viewport))
1009
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE))
1010
    CHECK_FUNC(SDL_RenderClear, (renderer))
1011
    CHECK_FUNC(SDL_SetRenderViewport, (renderer, NULL))
1012

1013
    /* Check to see if final image matches. */
1014
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
1015

1016
    /* Make current */
1017
    SDL_RenderPresent(renderer);
1018

1019
    SDL_DestroySurface(referenceSurface);
1020

1021
    return TEST_COMPLETED;
1022
}
1023

1024
/**
1025
 * Test clip rect
1026
 */
1027
static int render_testClipRect(void *arg)
1028
{
1029
    SDL_Surface *referenceSurface;
1030
    SDL_Rect cliprect;
1031

1032
    cliprect.x = TESTRENDER_SCREEN_W / 3;
1033
    cliprect.y = TESTRENDER_SCREEN_H / 3;
1034
    cliprect.w = TESTRENDER_SCREEN_W / 2;
1035
    cliprect.h = TESTRENDER_SCREEN_H / 2;
1036

1037
    /* Create expected result */
1038
    referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, RENDER_COMPARE_FORMAT);
1039
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, NULL, RENDER_COLOR_CLEAR))
1040
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, &cliprect, RENDER_COLOR_GREEN))
1041

1042
    /* Clear surface. */
1043
    clearScreen();
1044

1045
    /* Set the cliprect and do a fill operation */
1046
    CHECK_FUNC(SDL_SetRenderClipRect, (renderer, &cliprect))
1047
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE))
1048
    CHECK_FUNC(SDL_RenderFillRect, (renderer, NULL))
1049
    CHECK_FUNC(SDL_SetRenderClipRect, (renderer, NULL))
1050

1051
    /* Check to see if final image matches. */
1052
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
1053

1054
    /*
1055
     * Verify that clear ignores the cliprect
1056
     */
1057

1058
    /* Create expected result */
1059
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, NULL, RENDER_COLOR_GREEN))
1060

1061
    /* Clear surface. */
1062
    clearScreen();
1063

1064
    /* Set the cliprect and do a clear operation */
1065
    CHECK_FUNC(SDL_SetRenderClipRect, (renderer, &cliprect))
1066
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE))
1067
    CHECK_FUNC(SDL_RenderClear, (renderer))
1068
    CHECK_FUNC(SDL_SetRenderClipRect, (renderer, NULL))
1069

1070
    /* Check to see if final image matches. */
1071
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
1072

1073
    /* Make current */
1074
    SDL_RenderPresent(renderer);
1075

1076
    SDL_DestroySurface(referenceSurface);
1077

1078
    return TEST_COMPLETED;
1079
}
1080

1081
/**
1082
 * Test logical size
1083
 */
1084
static int render_testLogicalSize(void *arg)
1085
{
1086
    SDL_Surface *referenceSurface;
1087
    SDL_Rect viewport;
1088
    SDL_FRect rect;
1089
    int w, h;
1090
    int set_w, set_h;
1091
    SDL_RendererLogicalPresentation set_presentation_mode;
1092
    SDL_ScaleMode set_scale_mode;
1093
    SDL_FRect set_rect;
1094
    const int factor = 2;
1095

1096
    viewport.x = ((TESTRENDER_SCREEN_W / 4) / factor) * factor;
1097
    viewport.y = ((TESTRENDER_SCREEN_H / 4) / factor) * factor;
1098
    viewport.w = ((TESTRENDER_SCREEN_W / 2) / factor) * factor;
1099
    viewport.h = ((TESTRENDER_SCREEN_H / 2) / factor) * factor;
1100

1101
    /* Create expected result */
1102
    referenceSurface = SDL_CreateSurface(TESTRENDER_SCREEN_W, TESTRENDER_SCREEN_H, RENDER_COMPARE_FORMAT);
1103
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, NULL, RENDER_COLOR_CLEAR))
1104
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, &viewport, RENDER_COLOR_GREEN))
1105

1106
    /* Clear surface. */
1107
    clearScreen();
1108

1109
    /* Set the logical size and do a fill operation */
1110
    CHECK_FUNC(SDL_GetCurrentRenderOutputSize, (renderer, &w, &h))
1111
    CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, w / factor, h / factor,
1112
                                           SDL_LOGICAL_PRESENTATION_LETTERBOX,
1113
                                           SDL_SCALEMODE_NEAREST))
1114
    CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode))
1115
    SDLTest_AssertCheck(
1116
        set_w == (w / factor) &&
1117
        set_h == (h / factor) &&
1118
        set_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX &&
1119
        set_scale_mode == SDL_SCALEMODE_NEAREST,
1120
        "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode);
1121
    CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect))
1122
    SDLTest_AssertCheck(
1123
        set_rect.x == 0.0f &&
1124
        set_rect.y == 0.0f &&
1125
        set_rect.w == 320.0f &&
1126
        set_rect.h == 240.0f,
1127
        "Validate result from SDL_GetRenderLogicalPresentationRect, got {%g, %g, %gx%g}", set_rect.x, set_rect.y, set_rect.w, set_rect.h);
1128
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE))
1129
    rect.x = (float)viewport.x / factor;
1130
    rect.y = (float)viewport.y / factor;
1131
    rect.w = (float)viewport.w / factor;
1132
    rect.h = (float)viewport.h / factor;
1133
    CHECK_FUNC(SDL_RenderFillRect, (renderer, &rect))
1134
    CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0,
1135
                                           SDL_LOGICAL_PRESENTATION_DISABLED,
1136
                                           SDL_SCALEMODE_NEAREST))
1137
    CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode))
1138
    SDLTest_AssertCheck(
1139
        set_w == 0 &&
1140
        set_h == 0 &&
1141
        set_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED &&
1142
        set_scale_mode == SDL_SCALEMODE_NEAREST,
1143
        "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode);
1144
    CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect))
1145
    SDLTest_AssertCheck(
1146
        set_rect.x == 0.0f &&
1147
        set_rect.y == 0.0f &&
1148
        set_rect.w == 320.0f &&
1149
        set_rect.h == 240.0f,
1150
        "Validate result from SDL_GetRenderLogicalPresentationRect, got {%g, %g, %gx%g}", set_rect.x, set_rect.y, set_rect.w, set_rect.h);
1151

1152
    /* Check to see if final image matches. */
1153
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
1154

1155
    /* Clear surface. */
1156
    clearScreen();
1157

1158
    /* Set the logical size and viewport and do a fill operation */
1159
    CHECK_FUNC(SDL_GetCurrentRenderOutputSize, (renderer, &w, &h))
1160
    CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, w / factor, h / factor,
1161
                                           SDL_LOGICAL_PRESENTATION_LETTERBOX,
1162
                                           SDL_SCALEMODE_NEAREST))
1163
    viewport.x = (TESTRENDER_SCREEN_W / 4) / factor;
1164
    viewport.y = (TESTRENDER_SCREEN_H / 4) / factor;
1165
    viewport.w = (TESTRENDER_SCREEN_W / 2) / factor;
1166
    viewport.h = (TESTRENDER_SCREEN_H / 2) / factor;
1167
    CHECK_FUNC(SDL_SetRenderViewport, (renderer, &viewport))
1168
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE))
1169
    CHECK_FUNC(SDL_RenderFillRect, (renderer, NULL))
1170
    CHECK_FUNC(SDL_SetRenderViewport, (renderer, NULL))
1171
    CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0,
1172
                                           SDL_LOGICAL_PRESENTATION_DISABLED,
1173
                                           SDL_SCALEMODE_NEAREST))
1174

1175
    /* Check to see if final image matches. */
1176
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
1177

1178
    /*
1179
     * Test a logical size that isn't the same aspect ratio as the window
1180
     */
1181

1182
    viewport.x = (TESTRENDER_SCREEN_W / 4);
1183
    viewport.y = 0;
1184
    viewport.w = TESTRENDER_SCREEN_W;
1185
    viewport.h = TESTRENDER_SCREEN_H;
1186

1187
    /* Create expected result */
1188
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, NULL, RENDER_COLOR_CLEAR))
1189
    CHECK_FUNC(SDL_FillSurfaceRect, (referenceSurface, &viewport, RENDER_COLOR_GREEN))
1190

1191
    /* Clear surface. */
1192
    clearScreen();
1193

1194
    /* Set the logical size and do a fill operation */
1195
    CHECK_FUNC(SDL_GetCurrentRenderOutputSize, (renderer, &w, &h))
1196
    CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer,
1197
                                           w - 2 * (TESTRENDER_SCREEN_W / 4),
1198
                                           h,
1199
                                           SDL_LOGICAL_PRESENTATION_LETTERBOX,
1200
                                           SDL_SCALEMODE_LINEAR))
1201
    CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode))
1202
    SDLTest_AssertCheck(
1203
        set_w == w - 2 * (TESTRENDER_SCREEN_W / 4) &&
1204
        set_h == h &&
1205
        set_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX &&
1206
        set_scale_mode == SDL_SCALEMODE_LINEAR,
1207
        "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode);
1208
    CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect))
1209
    SDLTest_AssertCheck(
1210
        set_rect.x == 20.0f &&
1211
        set_rect.y == 0.0f &&
1212
        set_rect.w == 280.0f &&
1213
        set_rect.h == 240.0f,
1214
        "Validate result from SDL_GetRenderLogicalPresentationRect, got {%g, %g, %gx%g}", set_rect.x, set_rect.y, set_rect.w, set_rect.h);
1215
    CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE))
1216
    CHECK_FUNC(SDL_RenderFillRect, (renderer, NULL))
1217
    CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0,
1218
                                           SDL_LOGICAL_PRESENTATION_DISABLED,
1219
                                           SDL_SCALEMODE_NEAREST))
1220
    CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode))
1221
    SDLTest_AssertCheck(
1222
        set_w == 0 &&
1223
        set_h == 0 &&
1224
        set_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED &&
1225
        set_scale_mode == SDL_SCALEMODE_NEAREST,
1226
        "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode);
1227
    CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect))
1228
    SDLTest_AssertCheck(
1229
        set_rect.x == 0.0f &&
1230
        set_rect.y == 0.0f &&
1231
        set_rect.w == 320.0f &&
1232
        set_rect.h == 240.0f,
1233
        "Validate result from SDL_GetRenderLogicalPresentationRect, got {%g, %g, %gx%g}", set_rect.x, set_rect.y, set_rect.w, set_rect.h);
1234

1235
    /* Check to see if final image matches. */
1236
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
1237

1238
    /* Clear surface. */
1239
    clearScreen();
1240

1241
    /* Make current */
1242
    SDL_RenderPresent(renderer);
1243

1244
    SDL_DestroySurface(referenceSurface);
1245

1246
    return TEST_COMPLETED;
1247
}
1248

1249
/* Helper functions */
1250

1251
/**
1252
 * Checks to see if functionality is supported. Helper function.
1253
 */
1254
static int
1255
isSupported(int code)
1256
{
1257
    return code == 0;
1258
}
1259

1260
/**
1261
 * Test to see if we can vary the draw color. Helper function.
1262
 *
1263
 * \sa SDL_SetRenderDrawColor
1264
 * \sa SDL_GetRenderDrawColor
1265
 */
1266
static int
1267
hasDrawColor(void)
1268
{
1269
    int ret, fail;
1270
    Uint8 r, g, b, a;
1271

1272
    fail = 0;
1273

1274
    /* Set color. */
1275
    ret = SDL_SetRenderDrawColor(renderer, 100, 100, 100, 100);
1276
    if (!isSupported(ret)) {
1277
        fail = 1;
1278
    }
1279
    ret = SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a);
1280
    if (!isSupported(ret)) {
1281
        fail = 1;
1282
    }
1283

1284
    /* Restore natural. */
1285
    ret = SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
1286
    if (!isSupported(ret)) {
1287
        fail = 1;
1288
    }
1289

1290
    /* Something failed, consider not available. */
1291
    if (fail) {
1292
        return 0;
1293
    }
1294
    /* Not set properly, consider failed. */
1295
    else if ((r != 100) || (g != 100) || (b != 100) || (a != 100)) {
1296
        return 0;
1297
    }
1298
    return 1;
1299
}
1300

1301
/**
1302
 * Loads the test image 'Face' as texture. Helper function.
1303
 *
1304
 * \sa SDL_CreateTextureFromSurface
1305
 */
1306
static SDL_Texture *
1307
loadTestFace(void)
1308
{
1309
    SDL_Surface *face;
1310
    SDL_Texture *tface;
1311

1312
    face = SDLTest_ImageFace();
1313
    if (!face) {
1314
        return NULL;
1315
    }
1316

1317
    tface = SDL_CreateTextureFromSurface(renderer, face);
1318
    if (!tface) {
1319
        SDLTest_LogError("SDL_CreateTextureFromSurface() failed with error: %s", SDL_GetError());
1320
    }
1321

1322
    SDL_DestroySurface(face);
1323

1324
    return tface;
1325
}
1326

1327
/**
1328
 * Compares screen pixels with image pixels. Helper function.
1329
 *
1330
 * \param referenceSurface Image to compare against.
1331
 * \param allowable_error allowed difference from the reference image
1332
 *
1333
 * \sa SDL_RenderReadPixels
1334
 * \sa SDL_CreateSurfaceFrom
1335
 * \sa SDL_DestroySurface
1336
 */
1337
static void compare(SDL_Surface *referenceSurface, int allowable_error)
1338
{
1339
    int ret;
1340
    SDL_Rect rect;
1341
    SDL_Surface *surface, *testSurface;
1342

1343
    /* Explicitly specify the rect in case the window isn't the expected size... */
1344
    rect.x = 0;
1345
    rect.y = 0;
1346
    rect.w = TESTRENDER_SCREEN_W;
1347
    rect.h = TESTRENDER_SCREEN_H;
1348

1349
    surface = SDL_RenderReadPixels(renderer, &rect);
1350
    if (!surface) {
1351
        SDLTest_AssertCheck(surface != NULL, "Validate result from SDL_RenderReadPixels, got NULL, %s", SDL_GetError());
1352
        return;
1353
    }
1354

1355
    testSurface = SDL_ConvertSurface(surface, RENDER_COMPARE_FORMAT);
1356
    SDL_DestroySurface(surface);
1357
    if (!testSurface) {
1358
        SDLTest_AssertCheck(testSurface != NULL, "Validate result from SDL_ConvertSurface, got NULL, %s", SDL_GetError());
1359
        return;
1360
    }
1361

1362
    /* Compare surface. */
1363
    ret = SDLTest_CompareSurfaces(testSurface, referenceSurface, allowable_error);
1364
    SDLTest_AssertCheck(ret == 0, "Validate result from SDLTest_CompareSurfaces, expected: 0, got: %i", ret);
1365

1366
    /* Clean up. */
1367
    SDL_DestroySurface(testSurface);
1368
}
1369
static void compare2x(SDL_Surface *referenceSurface, int allowable_error)
1370
{
1371
    int ret;
1372
    SDL_Rect rect;
1373
    SDL_Surface *surface, *testSurface;
1374

1375
    /* Explicitly specify the rect in case the window isn't the expected size... */
1376
    rect.x = 0;
1377
    rect.y = 0;
1378
    rect.w = TESTRENDER_SCREEN_W * 2;
1379
    rect.h = TESTRENDER_SCREEN_H * 2;
1380

1381
    surface = SDL_RenderReadPixels(renderer, &rect);
1382
    if (!surface) {
1383
        SDLTest_AssertCheck(surface != NULL, "Validate result from SDL_RenderReadPixels, got NULL, %s", SDL_GetError());
1384
        return;
1385
    }
1386

1387
    testSurface = SDL_ConvertSurface(surface, RENDER_COMPARE_FORMAT);
1388
    SDL_DestroySurface(surface);
1389
    if (!testSurface) {
1390
        SDLTest_AssertCheck(testSurface != NULL, "Validate result from SDL_ConvertSurface, got NULL, %s", SDL_GetError());
1391
        return;
1392
    }
1393

1394
    /* Compare surface. */
1395
    ret = SDLTest_CompareSurfaces(testSurface, referenceSurface, allowable_error);
1396
    SDLTest_AssertCheck(ret == 0, "Validate result from SDLTest_CompareSurfaces, expected: 0, got: %i", ret);
1397

1398
    /* Clean up. */
1399
    SDL_DestroySurface(testSurface);
1400
}
1401

1402
/**
1403
 * Clears the screen. Helper function.
1404
 *
1405
 * \sa SDL_SetRenderDrawColor
1406
 * \sa SDL_RenderClear
1407
 * \sa SDL_RenderPresent
1408
 * \sa SDL_SetRenderDrawBlendMode
1409
 */
1410
static int
1411
clearScreen(void)
1412
{
1413
    int ret;
1414

1415
    /* Make current */
1416
    SDL_RenderPresent(renderer);
1417

1418
    /* Set color. */
1419
    ret = SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
1420
    SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderDrawColor, expected: 0, got: %i", ret);
1421

1422
    /* Clear screen. */
1423
    ret = SDL_RenderClear(renderer);
1424
    SDLTest_AssertCheck(ret == 0, "Validate result from SDL_RenderClear, expected: 0, got: %i", ret);
1425

1426
    /* Set defaults. */
1427
    ret = SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
1428
    SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderDrawBlendMode, expected: 0, got: %i", ret);
1429

1430
    ret = SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
1431
    SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderDrawColor, expected: 0, got: %i", ret);
1432

1433
    return 0;
1434
}
1435

1436
/**
1437
 * Tests geometry UV wrapping
1438
 */
1439
static int render_testUVWrapping(void *arg)
1440
{
1441
    SDL_Vertex vertices[6];
1442
    SDL_Vertex *verts = vertices;
1443
    SDL_FColor color = { 1.0f, 1.0f, 1.0f, 1.0f };
1444
    float tw, th;
1445
    SDL_FRect rect;
1446
    float min_U = -0.5f;
1447
    float max_U = 1.5f;
1448
    float min_V = -0.5f;
1449
    float max_V = 1.5f;
1450
    SDL_Texture *tface;
1451
    SDL_Surface *referenceSurface = NULL;
1452

1453
    /* Clear surface. */
1454
    clearScreen();
1455

1456
    /* Create face surface. */
1457
    tface = loadTestFace();
1458
    SDLTest_AssertCheck(tface != NULL, "Verify loadTestFace() result");
1459
    if (tface == NULL) {
1460
        return TEST_ABORTED;
1461
    }
1462

1463
    CHECK_FUNC(SDL_GetTextureSize, (tface, &tw, &th))
1464
    rect.w = tw * 2;
1465
    rect.h = th * 2;
1466
    rect.x = (TESTRENDER_SCREEN_W - rect.w) / 2;
1467
    rect.y = (TESTRENDER_SCREEN_H - rect.h) / 2;
1468

1469
    /*
1470
     *   0--1
1471
     *   | /|
1472
     *   |/ |
1473
     *   3--2
1474
     *
1475
     *  Draw sprite2 as triangles that can be recombined as rect by software renderer
1476
     */
1477

1478
    /* 0 */
1479
    verts->position.x = rect.x;
1480
    verts->position.y = rect.y;
1481
    verts->color = color;
1482
    verts->tex_coord.x = min_U;
1483
    verts->tex_coord.y = min_V;
1484
    verts++;
1485
    /* 1 */
1486
    verts->position.x = rect.x + rect.w;
1487
    verts->position.y = rect.y;
1488
    verts->color = color;
1489
    verts->tex_coord.x = max_U;
1490
    verts->tex_coord.y = min_V;
1491
    verts++;
1492
    /* 2 */
1493
    verts->position.x = rect.x + rect.w;
1494
    verts->position.y = rect.y + rect.h;
1495
    verts->color = color;
1496
    verts->tex_coord.x = max_U;
1497
    verts->tex_coord.y = max_V;
1498
    verts++;
1499
    /* 0 */
1500
    verts->position.x = rect.x;
1501
    verts->position.y = rect.y;
1502
    verts->color = color;
1503
    verts->tex_coord.x = min_U;
1504
    verts->tex_coord.y = min_V;
1505
    verts++;
1506
    /* 2 */
1507
    verts->position.x = rect.x + rect.w;
1508
    verts->position.y = rect.y + rect.h;
1509
    verts->color = color;
1510
    verts->tex_coord.x = max_U;
1511
    verts->tex_coord.y = max_V;
1512
    verts++;
1513
    /* 3 */
1514
    verts->position.x = rect.x;
1515
    verts->position.y = rect.y + rect.h;
1516
    verts->color = color;
1517
    verts->tex_coord.x = min_U;
1518
    verts->tex_coord.y = max_V;
1519
    verts++;
1520

1521
    /* Blit sprites as triangles onto the screen */
1522
    SDL_RenderGeometry(renderer, tface, vertices, 6, NULL, 0);
1523

1524
    /* See if it's the same */
1525
    referenceSurface = SDLTest_ImageWrappingSprite();
1526
    compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);
1527

1528
    /* Make current */
1529
    SDL_RenderPresent(renderer);
1530

1531
    /* Clean up. */
1532
    SDL_DestroyTexture(tface);
1533
    SDL_DestroySurface(referenceSurface);
1534
    referenceSurface = NULL;
1535

1536
    return TEST_COMPLETED;
1537
}
1538

1539
/* ================= Test References ================== */
1540

1541
/* Render test cases */
1542
static const SDLTest_TestCaseReference renderTestGetNumRenderDrivers = {
1543
    (SDLTest_TestCaseFp)render_testGetNumRenderDrivers, "render_testGetNumRenderDrivers", "Tests call to SDL_GetNumRenderDrivers", TEST_ENABLED
1544
};
1545

1546
static const SDLTest_TestCaseReference renderTestPrimitives = {
1547
    (SDLTest_TestCaseFp)render_testPrimitives, "render_testPrimitives", "Tests rendering primitives", TEST_ENABLED
1548
};
1549

1550
static const SDLTest_TestCaseReference renderTestPrimitivesWithViewport = {
1551
    (SDLTest_TestCaseFp)render_testPrimitivesWithViewport, "render_testPrimitivesWithViewport", "Tests rendering primitives within a viewport", TEST_ENABLED
1552
};
1553

1554
static const SDLTest_TestCaseReference renderTestBlit = {
1555
    (SDLTest_TestCaseFp)render_testBlit, "render_testBlit", "Tests blitting", TEST_ENABLED
1556
};
1557

1558
static const SDLTest_TestCaseReference renderTestBlitTiled = {
1559
    (SDLTest_TestCaseFp)render_testBlitTiled, "render_testBlitTiled", "Tests tiled blitting", TEST_ENABLED
1560
};
1561

1562
static const SDLTest_TestCaseReference renderTestBlit9Grid = {
1563
    (SDLTest_TestCaseFp)render_testBlit9Grid, "render_testBlit9Grid", "Tests 9-grid blitting", TEST_ENABLED
1564
};
1565

1566
static const SDLTest_TestCaseReference renderTestBlitColor = {
1567
    (SDLTest_TestCaseFp)render_testBlitColor, "render_testBlitColor", "Tests blitting with color", TEST_ENABLED
1568
};
1569

1570
static const SDLTest_TestCaseReference renderTestBlendModes = {
1571
    (SDLTest_TestCaseFp)render_testBlendModes, "render_testBlendModes", "Tests rendering blend modes", TEST_ENABLED
1572
};
1573

1574
static const SDLTest_TestCaseReference renderTestViewport = {
1575
    (SDLTest_TestCaseFp)render_testViewport, "render_testViewport", "Tests viewport", TEST_ENABLED
1576
};
1577

1578
static const SDLTest_TestCaseReference renderTestClipRect = {
1579
    (SDLTest_TestCaseFp)render_testClipRect, "render_testClipRect", "Tests clip rect", TEST_ENABLED
1580
};
1581

1582
static const SDLTest_TestCaseReference renderTestLogicalSize = {
1583
    (SDLTest_TestCaseFp)render_testLogicalSize, "render_testLogicalSize", "Tests logical size", TEST_ENABLED
1584
};
1585

1586
static const SDLTest_TestCaseReference renderTestUVWrapping = {
1587
    (SDLTest_TestCaseFp)render_testUVWrapping, "render_testUVWrapping", "Tests geometry UV wrapping", TEST_ENABLED
1588
};
1589

1590
/* Sequence of Render test cases */
1591
static const SDLTest_TestCaseReference *renderTests[] = {
1592
    &renderTestGetNumRenderDrivers,
1593
    &renderTestPrimitives,
1594
    &renderTestPrimitivesWithViewport,
1595
    &renderTestBlit,
1596
    &renderTestBlitTiled,
1597
    &renderTestBlit9Grid,
1598
    &renderTestBlitColor,
1599
    &renderTestBlendModes,
1600
    &renderTestViewport,
1601
    &renderTestClipRect,
1602
    &renderTestLogicalSize,
1603
    &renderTestUVWrapping,
1604
    NULL
1605
};
1606

1607
/* Render test suite (global) */
1608
SDLTest_TestSuiteReference renderTestSuite = {
1609
    "Render",
1610
    InitCreateRenderer,
1611
    renderTests,
1612
    CleanupDestroyRenderer
1613
};
1614

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.