cscg22-gearboy

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

SDL_blit.c (8428B)


      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_sysvideo.h"
     25#include "SDL_blit.h"
     26#include "SDL_blit_auto.h"
     27#include "SDL_blit_copy.h"
     28#include "SDL_blit_slow.h"
     29#include "SDL_RLEaccel_c.h"
     30#include "SDL_pixels_c.h"
     31
     32/* The general purpose software blit routine */
     33static int
     34SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect,
     35             SDL_Surface * dst, SDL_Rect * dstrect)
     36{
     37    int okay;
     38    int src_locked;
     39    int dst_locked;
     40
     41    /* Everything is okay at the beginning...  */
     42    okay = 1;
     43
     44    /* Lock the destination if it's in hardware */
     45    dst_locked = 0;
     46    if (SDL_MUSTLOCK(dst)) {
     47        if (SDL_LockSurface(dst) < 0) {
     48            okay = 0;
     49        } else {
     50            dst_locked = 1;
     51        }
     52    }
     53    /* Lock the source if it's in hardware */
     54    src_locked = 0;
     55    if (SDL_MUSTLOCK(src)) {
     56        if (SDL_LockSurface(src) < 0) {
     57            okay = 0;
     58        } else {
     59            src_locked = 1;
     60        }
     61    }
     62
     63    /* Set up source and destination buffer pointers, and BLIT! */
     64    if (okay && !SDL_RectEmpty(srcrect)) {
     65        SDL_BlitFunc RunBlit;
     66        SDL_BlitInfo *info = &src->map->info;
     67
     68        /* Set up the blit information */
     69        info->src = (Uint8 *) src->pixels +
     70            (Uint16) srcrect->y * src->pitch +
     71            (Uint16) srcrect->x * info->src_fmt->BytesPerPixel;
     72        info->src_w = srcrect->w;
     73        info->src_h = srcrect->h;
     74        info->src_pitch = src->pitch;
     75        info->src_skip =
     76            info->src_pitch - info->src_w * info->src_fmt->BytesPerPixel;
     77        info->dst =
     78            (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch +
     79            (Uint16) dstrect->x * info->dst_fmt->BytesPerPixel;
     80        info->dst_w = dstrect->w;
     81        info->dst_h = dstrect->h;
     82        info->dst_pitch = dst->pitch;
     83        info->dst_skip =
     84            info->dst_pitch - info->dst_w * info->dst_fmt->BytesPerPixel;
     85        RunBlit = (SDL_BlitFunc) src->map->data;
     86
     87        /* Run the actual software blit */
     88        RunBlit(info);
     89    }
     90
     91    /* We need to unlock the surfaces if they're locked */
     92    if (dst_locked) {
     93        SDL_UnlockSurface(dst);
     94    }
     95    if (src_locked) {
     96        SDL_UnlockSurface(src);
     97    }
     98    /* Blit is done! */
     99    return (okay ? 0 : -1);
    100}
    101
    102#ifdef __MACOSX__
    103#include <sys/sysctl.h>
    104
    105static SDL_bool
    106SDL_UseAltivecPrefetch()
    107{
    108    const char key[] = "hw.l3cachesize";
    109    u_int64_t result = 0;
    110    size_t typeSize = sizeof(result);
    111
    112    if (sysctlbyname(key, &result, &typeSize, NULL, 0) == 0 && result > 0) {
    113        return SDL_TRUE;
    114    } else {
    115        return SDL_FALSE;
    116    }
    117}
    118#else
    119static SDL_bool
    120SDL_UseAltivecPrefetch()
    121{
    122    /* Just guess G4 */
    123    return SDL_TRUE;
    124}
    125#endif /* __MACOSX__ */
    126
    127static SDL_BlitFunc
    128SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags,
    129                   SDL_BlitFuncEntry * entries)
    130{
    131    int i, flagcheck;
    132    static Uint32 features = 0xffffffff;
    133
    134    /* Get the available CPU features */
    135    if (features == 0xffffffff) {
    136        const char *override = SDL_getenv("SDL_BLIT_CPU_FEATURES");
    137
    138        features = SDL_CPU_ANY;
    139
    140        /* Allow an override for testing .. */
    141        if (override) {
    142            SDL_sscanf(override, "%u", &features);
    143        } else {
    144            if (SDL_HasMMX()) {
    145                features |= SDL_CPU_MMX;
    146            }
    147            if (SDL_Has3DNow()) {
    148                features |= SDL_CPU_3DNOW;
    149            }
    150            if (SDL_HasSSE()) {
    151                features |= SDL_CPU_SSE;
    152            }
    153            if (SDL_HasSSE2()) {
    154                features |= SDL_CPU_SSE2;
    155            }
    156            if (SDL_HasAltiVec()) {
    157                if (SDL_UseAltivecPrefetch()) {
    158                    features |= SDL_CPU_ALTIVEC_PREFETCH;
    159                } else {
    160                    features |= SDL_CPU_ALTIVEC_NOPREFETCH;
    161                }
    162            }
    163        }
    164    }
    165
    166    for (i = 0; entries[i].func; ++i) {
    167        /* Check for matching pixel formats */
    168        if (src_format != entries[i].src_format) {
    169            continue;
    170        }
    171        if (dst_format != entries[i].dst_format) {
    172            continue;
    173        }
    174
    175        /* Check modulation flags */
    176        flagcheck =
    177            (flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA));
    178        if ((flagcheck & entries[i].flags) != flagcheck) {
    179            continue;
    180        }
    181
    182        /* Check blend flags */
    183        flagcheck =
    184            (flags &
    185             (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD));
    186        if ((flagcheck & entries[i].flags) != flagcheck) {
    187            continue;
    188        }
    189
    190        /* Check colorkey flag */
    191        flagcheck = (flags & SDL_COPY_COLORKEY);
    192        if ((flagcheck & entries[i].flags) != flagcheck) {
    193            continue;
    194        }
    195
    196        /* Check scaling flags */
    197        flagcheck = (flags & SDL_COPY_NEAREST);
    198        if ((flagcheck & entries[i].flags) != flagcheck) {
    199            continue;
    200        }
    201
    202        /* Check CPU features */
    203        flagcheck = entries[i].cpu;
    204        if ((flagcheck & features) != flagcheck) {
    205            continue;
    206        }
    207
    208        /* We found the best one! */
    209        return entries[i].func;
    210    }
    211    return NULL;
    212}
    213
    214/* Figure out which of many blit routines to set up on a surface */
    215int
    216SDL_CalculateBlit(SDL_Surface * surface)
    217{
    218    SDL_BlitFunc blit = NULL;
    219    SDL_BlitMap *map = surface->map;
    220    SDL_Surface *dst = map->dst;
    221
    222    /* Clean everything out to start */
    223    if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
    224        SDL_UnRLESurface(surface, 1);
    225    }
    226    map->blit = SDL_SoftBlit;
    227    map->info.src_fmt = surface->format;
    228    map->info.src_pitch = surface->pitch;
    229    map->info.dst_fmt = dst->format;
    230    map->info.dst_pitch = dst->pitch;
    231
    232    /* See if we can do RLE acceleration */
    233    if (map->info.flags & SDL_COPY_RLE_DESIRED) {
    234        if (SDL_RLESurface(surface) == 0) {
    235            return 0;
    236        }
    237    }
    238
    239    /* Choose a standard blit function */
    240    if (map->identity && !(map->info.flags & ~SDL_COPY_RLE_DESIRED)) {
    241        blit = SDL_BlitCopy;
    242    } else if (surface->format->BitsPerPixel < 8 &&
    243               SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
    244        blit = SDL_CalculateBlit0(surface);
    245    } else if (surface->format->BytesPerPixel == 1 &&
    246               SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
    247        blit = SDL_CalculateBlit1(surface);
    248    } else if (map->info.flags & SDL_COPY_BLEND) {
    249        blit = SDL_CalculateBlitA(surface);
    250    } else {
    251        blit = SDL_CalculateBlitN(surface);
    252    }
    253    if (blit == NULL) {
    254        Uint32 src_format = surface->format->format;
    255        Uint32 dst_format = dst->format->format;
    256
    257        blit =
    258            SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags,
    259                               SDL_GeneratedBlitFuncTable);
    260    }
    261#ifndef TEST_SLOW_BLIT
    262    if (blit == NULL)
    263#endif
    264    {
    265        Uint32 src_format = surface->format->format;
    266        Uint32 dst_format = dst->format->format;
    267
    268        if (!SDL_ISPIXELFORMAT_INDEXED(src_format) &&
    269            !SDL_ISPIXELFORMAT_FOURCC(src_format) &&
    270            !SDL_ISPIXELFORMAT_INDEXED(dst_format) &&
    271            !SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
    272            blit = SDL_Blit_Slow;
    273        }
    274    }
    275    map->data = blit;
    276
    277    /* Make sure we have a blit function */
    278    if (blit == NULL) {
    279        SDL_InvalidateMap(map);
    280        return SDL_SetError("Blit combination not supported");
    281    }
    282
    283    return 0;
    284}
    285
    286/* vi: set ts=4 sw=4 expandtab: */