src/video/SDL_blit.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 17 Aug 2007 02:55:21 +0000
changeset 2260 202ddfd1cfb1
parent 2257 340942cfda48
child 2262 bee005ace1bf
permissions -rw-r--r--
indent
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_video.h"
    25 #include "SDL_sysvideo.h"
    26 #include "SDL_blit.h"
    27 #include "SDL_blit_copy.h"
    28 #include "SDL_RLEaccel_c.h"
    29 #include "SDL_pixels_c.h"
    30 
    31 /* The general purpose software blit routine */
    32 static int
    33 SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect,
    34              SDL_Surface * dst, SDL_Rect * dstrect)
    35 {
    36     int okay;
    37     int src_locked;
    38     int dst_locked;
    39 
    40     /* Everything is okay at the beginning...  */
    41     okay = 1;
    42 
    43     /* Lock the destination if it's in hardware */
    44     dst_locked = 0;
    45     if (SDL_MUSTLOCK(dst)) {
    46         if (SDL_LockSurface(dst) < 0) {
    47             okay = 0;
    48         } else {
    49             dst_locked = 1;
    50         }
    51     }
    52     /* Lock the source if it's in hardware */
    53     src_locked = 0;
    54     if (SDL_MUSTLOCK(src)) {
    55         if (SDL_LockSurface(src) < 0) {
    56             okay = 0;
    57         } else {
    58             src_locked = 1;
    59         }
    60     }
    61 
    62     /* Set up source and destination buffer pointers, and BLIT! */
    63     if (okay && srcrect->w && srcrect->h) {
    64         SDL_BlitInfo info;
    65         SDL_loblit RunBlit;
    66 
    67         /* Set up the blit information */
    68         info.s_pixels = (Uint8 *) src->pixels +
    69             (Uint16) srcrect->y * src->pitch +
    70             (Uint16) srcrect->x * src->format->BytesPerPixel;
    71         info.s_width = srcrect->w;
    72         info.s_height = srcrect->h;
    73         info.s_skip = src->pitch - info.s_width * src->format->BytesPerPixel;
    74         info.d_pixels = (Uint8 *) dst->pixels +
    75             (Uint16) dstrect->y * dst->pitch +
    76             (Uint16) dstrect->x * dst->format->BytesPerPixel;
    77         info.d_width = dstrect->w;
    78         info.d_height = dstrect->h;
    79         info.d_skip = dst->pitch - info.d_width * dst->format->BytesPerPixel;
    80         info.src = src->format;
    81         info.table = src->map->table;
    82         info.dst = dst->format;
    83         info.ckey = src->map->ckey;
    84         info.cmod = src->map->cmod;
    85         RunBlit = (SDL_loblit) 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 
   105 static SDL_bool
   106 SDL_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
   119 static SDL_bool
   120 SDL_UseAltivecPrefetch()
   121 {
   122     /* Just guess G4 */
   123     return SDL_TRUE;
   124 }
   125 #endif /* __MACOSX__ */
   126 
   127 static SDL_loblit
   128 SDL_ChooseBlitFunc(SDL_BlitEntry * entries, int count)
   129 {
   130     int i;
   131     static Uint32 features = 0xffffffff;
   132 
   133     if (features == 0xffffffff) {
   134         const char *override = SDL_getenv("SDL_BLIT_FEATURES");
   135 
   136         features = SDL_BLIT_ANY;
   137 
   138         /* Allow an override for testing .. */
   139         if (override) {
   140             SDL_sscanf(override, "%u", &features);
   141         } else {
   142             if (SDL_HasMMX()) {
   143                 features |= SDL_BLIT_MMX;
   144             }
   145             if (SDL_HasSSE()) {
   146                 features |= SDL_BLIT_SSE;
   147             }
   148             if (SDL_HasAltiVec()) {
   149                 if (SDL_UseAltivecPrefetch()) {
   150                     features |= SDL_BLIT_ALTIVEC_PREFETCH;
   151                 } else {
   152                     features |= SDL_BLIT_ALTIVEC_NOPREFETCH;
   153                 }
   154             }
   155         }
   156     }
   157 
   158     for (i = count; i > 0; --i) {
   159         if (features & entries[i].features) {
   160             return entries[i].blit;
   161         }
   162     }
   163     return entries[0].blit;
   164 }
   165 
   166 /* Figure out which of many blit routines to set up on a surface */
   167 int
   168 SDL_CalculateBlit(SDL_Surface * surface)
   169 {
   170     SDL_loblit blit = NULL;
   171     int blit_index;
   172 
   173     /* Clean everything out to start */
   174     if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
   175         SDL_UnRLESurface(surface, 1);
   176     }
   177     surface->map->blit = NULL;
   178 
   179     /* Get the blit function index, based on surface mode */
   180     /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
   181     blit_index = 0;
   182     blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0;
   183     if (surface->flags & SDL_SRCALPHA
   184         && ((surface->map->cmod >> 24) != SDL_ALPHA_OPAQUE
   185             || surface->format->Amask)) {
   186         blit_index |= 2;
   187     }
   188 
   189     /* Check for special "identity" case -- copy blit */
   190     if (surface->map->identity && blit_index == 0) {
   191         /* Handle overlapping blits on the same surface */
   192         if (surface == surface->map->dst) {
   193             blit = SDL_BlitCopyOverlap;
   194         } else {
   195             blit = SDL_BlitCopy;
   196         }
   197     } else {
   198         if (surface->format->BitsPerPixel < 8) {
   199             blit = SDL_CalculateBlit0(surface, blit_index);
   200         } else {
   201             switch (surface->format->BytesPerPixel) {
   202             case 1:
   203                 blit = SDL_CalculateBlit1(surface, blit_index);
   204                 break;
   205             case 2:
   206             case 3:
   207             case 4:
   208                 blit = SDL_CalculateBlitN(surface, blit_index);
   209                 break;
   210             }
   211         }
   212     }
   213     /* Make sure we have a blit function */
   214     if (blit == NULL) {
   215         SDL_InvalidateMap(surface->map);
   216         SDL_SetError("Blit combination not supported");
   217         return (-1);
   218     }
   219 
   220     /* Choose software blitting function */
   221     if (surface->flags & SDL_RLEACCELOK) {
   222         if (surface->map->identity
   223             && (blit_index == 1
   224                 || (blit_index == 3 && !surface->format->Amask))) {
   225             if (SDL_RLESurface(surface) == 0)
   226                 surface->map->blit = SDL_RLEBlit;
   227         } else if (blit_index == 2 && surface->format->Amask) {
   228             if (SDL_RLESurface(surface) == 0)
   229                 surface->map->blit = SDL_RLEAlphaBlit;
   230         }
   231     }
   232 
   233     if (surface->map->blit == NULL) {
   234         surface->map->blit = SDL_SoftBlit;
   235         surface->map->data = blit;
   236     }
   237     return (0);
   238 }
   239 
   240 /* vi: set ts=4 sw=4 expandtab: */