sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_blit.c (8589B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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 */
     33 static int SDLCALL
     34 SDL_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 #if SDL_HAVE_BLIT_AUTO
    103 
    104 #ifdef __MACOSX__
    105 #include <sys/sysctl.h>
    106 
    107 static SDL_bool
    108 SDL_UseAltivecPrefetch()
    109 {
    110     const char key[] = "hw.l3cachesize";
    111     u_int64_t result = 0;
    112     size_t typeSize = sizeof(result);
    113 
    114     if (sysctlbyname(key, &result, &typeSize, NULL, 0) == 0 && result > 0) {
    115         return SDL_TRUE;
    116     } else {
    117         return SDL_FALSE;
    118     }
    119 }
    120 #else
    121 static SDL_bool
    122 SDL_UseAltivecPrefetch()
    123 {
    124     /* Just guess G4 */
    125     return SDL_TRUE;
    126 }
    127 #endif /* __MACOSX__ */
    128 
    129 static SDL_BlitFunc
    130 SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags,
    131                    SDL_BlitFuncEntry * entries)
    132 {
    133     int i, flagcheck = (flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL | SDL_COPY_COLORKEY | SDL_COPY_NEAREST));
    134     static int features = 0x7fffffff;
    135 
    136     /* Get the available CPU features */
    137     if (features == 0x7fffffff) {
    138         const char *override = SDL_getenv("SDL_BLIT_CPU_FEATURES");
    139 
    140         features = SDL_CPU_ANY;
    141 
    142         /* Allow an override for testing .. */
    143         if (override) {
    144             SDL_sscanf(override, "%u", &features);
    145         } else {
    146             if (SDL_HasMMX()) {
    147                 features |= SDL_CPU_MMX;
    148             }
    149             if (SDL_Has3DNow()) {
    150                 features |= SDL_CPU_3DNOW;
    151             }
    152             if (SDL_HasSSE()) {
    153                 features |= SDL_CPU_SSE;
    154             }
    155             if (SDL_HasSSE2()) {
    156                 features |= SDL_CPU_SSE2;
    157             }
    158             if (SDL_HasAltiVec()) {
    159                 if (SDL_UseAltivecPrefetch()) {
    160                     features |= SDL_CPU_ALTIVEC_PREFETCH;
    161                 } else {
    162                     features |= SDL_CPU_ALTIVEC_NOPREFETCH;
    163                 }
    164             }
    165         }
    166     }
    167 
    168     for (i = 0; entries[i].func; ++i) {
    169         /* Check for matching pixel formats */
    170         if (src_format != entries[i].src_format) {
    171             continue;
    172         }
    173         if (dst_format != entries[i].dst_format) {
    174             continue;
    175         }
    176 
    177         /* Check flags */
    178         if ((flagcheck & entries[i].flags) != flagcheck) {
    179             continue;
    180         }
    181 
    182         /* Check CPU features */
    183         if ((entries[i].cpu & features) != entries[i].cpu) {
    184             continue;
    185         }
    186 
    187         /* We found the best one! */
    188         return entries[i].func;
    189     }
    190     return NULL;
    191 }
    192 #endif /* SDL_HAVE_BLIT_AUTO */
    193 
    194 /* Figure out which of many blit routines to set up on a surface */
    195 int
    196 SDL_CalculateBlit(SDL_Surface * surface)
    197 {
    198     SDL_BlitFunc blit = NULL;
    199     SDL_BlitMap *map = surface->map;
    200     SDL_Surface *dst = map->dst;
    201 
    202     /* We don't currently support blitting to < 8 bpp surfaces */
    203     if (dst->format->BitsPerPixel < 8) {
    204         SDL_InvalidateMap(map);
    205         return SDL_SetError("Blit combination not supported");
    206     }
    207 
    208 #if SDL_HAVE_RLE
    209     /* Clean everything out to start */
    210     if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
    211         SDL_UnRLESurface(surface, 1);
    212     }
    213 #endif
    214 
    215     map->blit = SDL_SoftBlit;
    216     map->info.src_fmt = surface->format;
    217     map->info.src_pitch = surface->pitch;
    218     map->info.dst_fmt = dst->format;
    219     map->info.dst_pitch = dst->pitch;
    220 
    221 #if SDL_HAVE_RLE
    222     /* See if we can do RLE acceleration */
    223     if (map->info.flags & SDL_COPY_RLE_DESIRED) {
    224         if (SDL_RLESurface(surface) == 0) {
    225             return 0;
    226         }
    227     }
    228 #endif
    229 
    230     /* Choose a standard blit function */
    231     if (map->identity && !(map->info.flags & ~SDL_COPY_RLE_DESIRED)) {
    232         blit = SDL_BlitCopy;
    233     } else if (surface->format->Rloss > 8 || dst->format->Rloss > 8) {
    234         /* Greater than 8 bits per channel not supported yet */
    235         SDL_InvalidateMap(map);
    236         return SDL_SetError("Blit combination not supported");
    237     }
    238 #if SDL_HAVE_BLIT_0
    239     else if (surface->format->BitsPerPixel < 8 &&
    240                SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
    241         blit = SDL_CalculateBlit0(surface);
    242     }
    243 #endif
    244 #if SDL_HAVE_BLIT_1
    245     else if (surface->format->BytesPerPixel == 1 &&
    246                SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
    247         blit = SDL_CalculateBlit1(surface);
    248     }
    249 #endif
    250 #if SDL_HAVE_BLIT_A
    251     else if (map->info.flags & SDL_COPY_BLEND) {
    252         blit = SDL_CalculateBlitA(surface);
    253     }
    254 #endif
    255 #if SDL_HAVE_BLIT_N
    256     else {
    257         blit = SDL_CalculateBlitN(surface);
    258     }
    259 #endif
    260 #if SDL_HAVE_BLIT_AUTO
    261     if (blit == NULL) {
    262         Uint32 src_format = surface->format->format;
    263         Uint32 dst_format = dst->format->format;
    264 
    265         blit =
    266             SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags,
    267                                SDL_GeneratedBlitFuncTable);
    268     }
    269 #endif
    270 
    271 #ifndef TEST_SLOW_BLIT
    272     if (blit == NULL)
    273 #endif
    274     {
    275         Uint32 src_format = surface->format->format;
    276         Uint32 dst_format = dst->format->format;
    277 
    278         if (!SDL_ISPIXELFORMAT_INDEXED(src_format) &&
    279             !SDL_ISPIXELFORMAT_FOURCC(src_format) &&
    280             !SDL_ISPIXELFORMAT_INDEXED(dst_format) &&
    281             !SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
    282             blit = SDL_Blit_Slow;
    283         }
    284     }
    285     map->data = blit;
    286 
    287     /* Make sure we have a blit function */
    288     if (blit == NULL) {
    289         SDL_InvalidateMap(map);
    290         return SDL_SetError("Blit combination not supported");
    291     }
    292 
    293     return 0;
    294 }
    295 
    296 /* vi: set ts=4 sw=4 expandtab: */