cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_fillrect.c (7970B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../SDL_internal.h"
     22
     23#include "SDL_video.h"
     24#include "SDL_blit.h"
     25
     26
     27#ifdef __SSE__
     28/* *INDENT-OFF* */
     29
     30#ifdef _MSC_VER
     31#define SSE_BEGIN \
     32    __m128 c128; \
     33    c128.m128_u32[0] = color; \
     34    c128.m128_u32[1] = color; \
     35    c128.m128_u32[2] = color; \
     36    c128.m128_u32[3] = color;
     37#else
     38#define SSE_BEGIN \
     39    __m128 c128; \
     40    DECLARE_ALIGNED(Uint32, cccc[4], 16); \
     41    cccc[0] = color; \
     42    cccc[1] = color; \
     43    cccc[2] = color; \
     44    cccc[3] = color; \
     45    c128 = *(__m128 *)cccc;
     46#endif
     47
     48#define SSE_WORK \
     49    for (i = n / 64; i--;) { \
     50        _mm_stream_ps((float *)(p+0), c128); \
     51        _mm_stream_ps((float *)(p+16), c128); \
     52        _mm_stream_ps((float *)(p+32), c128); \
     53        _mm_stream_ps((float *)(p+48), c128); \
     54        p += 64; \
     55    }
     56
     57#define SSE_END
     58
     59#define DEFINE_SSE_FILLRECT(bpp, type) \
     60static void \
     61SDL_FillRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
     62{ \
     63    int i, n; \
     64    Uint8 *p = NULL; \
     65 \
     66    SSE_BEGIN; \
     67 \
     68    while (h--) { \
     69        n = w * bpp; \
     70        p = pixels; \
     71 \
     72        if (n > 63) { \
     73            int adjust = 16 - ((uintptr_t)p & 15); \
     74            if (adjust < 16) { \
     75                n -= adjust; \
     76                adjust /= bpp; \
     77                while (adjust--) { \
     78                    *((type *)p) = (type)color; \
     79                    p += bpp; \
     80                } \
     81            } \
     82            SSE_WORK; \
     83        } \
     84        if (n & 63) { \
     85            int remainder = (n & 63); \
     86            remainder /= bpp; \
     87            while (remainder--) { \
     88                *((type *)p) = (type)color; \
     89                p += bpp; \
     90            } \
     91        } \
     92        pixels += pitch; \
     93    } \
     94 \
     95    SSE_END; \
     96}
     97
     98static void
     99SDL_FillRect1SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
    100{
    101    int i, n;
    102
    103    SSE_BEGIN;
    104    while (h--) {
    105        Uint8 *p = pixels;
    106        n = w;
    107
    108        if (n > 63) {
    109            int adjust = 16 - ((uintptr_t)p & 15);
    110            if (adjust) {
    111                n -= adjust;
    112                SDL_memset(p, color, adjust);
    113                p += adjust;
    114            }
    115            SSE_WORK;
    116        }
    117        if (n & 63) {
    118            int remainder = (n & 63);
    119            SDL_memset(p, color, remainder);
    120        }
    121        pixels += pitch;
    122    }
    123
    124    SSE_END;
    125}
    126/* DEFINE_SSE_FILLRECT(1, Uint8) */
    127DEFINE_SSE_FILLRECT(2, Uint16)
    128DEFINE_SSE_FILLRECT(4, Uint32)
    129
    130/* *INDENT-ON* */
    131#endif /* __SSE__ */
    132
    133static void
    134SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
    135{
    136    int n;
    137    Uint8 *p = NULL;
    138    
    139    while (h--) {
    140        n = w;
    141        p = pixels;
    142
    143        if (n > 3) {
    144            switch ((uintptr_t) p & 3) {
    145            case 1:
    146                *p++ = (Uint8) color;
    147                --n;
    148            case 2:
    149                *p++ = (Uint8) color;
    150                --n;
    151            case 3:
    152                *p++ = (Uint8) color;
    153                --n;
    154            }
    155            SDL_memset4(p, color, (n >> 2));
    156        }
    157        if (n & 3) {
    158            p += (n & ~3);
    159            switch (n & 3) {
    160            case 3:
    161                *p++ = (Uint8) color;
    162            case 2:
    163                *p++ = (Uint8) color;
    164            case 1:
    165                *p++ = (Uint8) color;
    166            }
    167        }
    168        pixels += pitch;
    169    }
    170}
    171
    172static void
    173SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
    174{
    175    int n;
    176    Uint16 *p = NULL;
    177    
    178    while (h--) {
    179        n = w;
    180        p = (Uint16 *) pixels;
    181
    182        if (n > 1) {
    183            if ((uintptr_t) p & 2) {
    184                *p++ = (Uint16) color;
    185                --n;
    186            }
    187            SDL_memset4(p, color, (n >> 1));
    188        }
    189        if (n & 1) {
    190            p[n - 1] = (Uint16) color;
    191        }
    192        pixels += pitch;
    193    }
    194}
    195
    196static void
    197SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
    198{
    199    Uint8 r = (Uint8) ((color >> 16) & 0xFF);
    200    Uint8 g = (Uint8) ((color >> 8) & 0xFF);
    201    Uint8 b = (Uint8) (color & 0xFF);
    202    int n;
    203    Uint8 *p = NULL;
    204
    205    while (h--) {
    206        n = w;
    207        p = pixels;
    208
    209        while (n--) {
    210            *p++ = r;
    211            *p++ = g;
    212            *p++ = b;
    213        }
    214        pixels += pitch;
    215    }
    216}
    217
    218static void
    219SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
    220{
    221    while (h--) {
    222        SDL_memset4(pixels, color, w);
    223        pixels += pitch;
    224    }
    225}
    226
    227/* 
    228 * This function performs a fast fill of the given rectangle with 'color'
    229 */
    230int
    231SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
    232{
    233    SDL_Rect clipped;
    234    Uint8 *pixels;
    235
    236    if (!dst) {
    237        return SDL_SetError("Passed NULL destination surface");
    238    }
    239
    240    /* This function doesn't work on surfaces < 8 bpp */
    241    if (dst->format->BitsPerPixel < 8) {
    242        return SDL_SetError("SDL_FillRect(): Unsupported surface format");
    243    }
    244
    245    /* If 'rect' == NULL, then fill the whole surface */
    246    if (rect) {
    247        /* Perform clipping */
    248        if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
    249            return 0;
    250        }
    251        rect = &clipped;
    252    } else {
    253        rect = &dst->clip_rect;
    254    }
    255
    256    /* Perform software fill */
    257    if (!dst->pixels) {
    258        return SDL_SetError("SDL_FillRect(): You must lock the surface");
    259    }
    260
    261    pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
    262                                     rect->x * dst->format->BytesPerPixel;
    263
    264    switch (dst->format->BytesPerPixel) {
    265    case 1:
    266        {
    267            color |= (color << 8);
    268            color |= (color << 16);
    269#ifdef __SSE__
    270            if (SDL_HasSSE()) {
    271                SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
    272                break;
    273            }
    274#endif
    275            SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h);
    276            break;
    277        }
    278
    279    case 2:
    280        {
    281            color |= (color << 16);
    282#ifdef __SSE__
    283            if (SDL_HasSSE()) {
    284                SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h);
    285                break;
    286            }
    287#endif
    288            SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
    289            break;
    290        }
    291
    292    case 3:
    293        /* 24-bit RGB is a slow path, at least for now. */
    294        {
    295            SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
    296            break;
    297        }
    298
    299    case 4:
    300        {
    301#ifdef __SSE__
    302            if (SDL_HasSSE()) {
    303                SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
    304                break;
    305            }
    306#endif
    307            SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
    308            break;
    309        }
    310    }
    311
    312    /* We're done! */
    313    return 0;
    314}
    315
    316int
    317SDL_FillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
    318              Uint32 color)
    319{
    320    int i;
    321    int status = 0;
    322
    323    if (!rects) {
    324        return SDL_SetError("SDL_FillRects() passed NULL rects");
    325    }
    326
    327    for (i = 0; i < count; ++i) {
    328        status += SDL_FillRect(dst, &rects[i], color);
    329    }
    330    return status;
    331}
    332
    333/* vi: set ts=4 sw=4 expandtab: */