src/video/SDL_blit.c
author Bob Pendleton <bob@pendleton.com>
Fri, 14 Mar 2008 18:17:49 +0000
changeset 2328 91e601d9df8b
parent 2267 c785543d1843
child 2329 c1a390f6a819
permissions -rw-r--r--
re: bug#563. checking in some commented out trace code and a fix so that the in testalpha.c the background only flashes when alpha == 255. The problem that is being
fixed is caused by clearing SDL_COPY_RLE_COLORKEY without setting SDL_COPY_RLE_DESIRED in SDL_UnRELSurface.
     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_auto.h"
    28 #include "SDL_blit_copy.h"
    29 #include "SDL_RLEaccel_c.h"
    30 #include "SDL_pixels_c.h"
    31 
    32 /* The general purpose software blit routine */
    33 static int
    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 && srcrect->w && srcrect->h) {
    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_skip =
    75             info->src_pitch - info->src_w * info->src_fmt->BytesPerPixel;
    76         info->dst =
    77             (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch +
    78             (Uint16) dstrect->x * info->dst_fmt->BytesPerPixel;
    79         info->dst_w = dstrect->w;
    80         info->dst_h = dstrect->h;
    81         info->dst_skip =
    82             info->dst_pitch - info->dst_w * info->dst_fmt->BytesPerPixel;
    83         RunBlit = (SDL_BlitFunc) src->map->data;
    84 
    85         /* Run the actual software blit */
    86         RunBlit(info);
    87     }
    88 
    89     /* We need to unlock the surfaces if they're locked */
    90     if (dst_locked) {
    91         SDL_UnlockSurface(dst);
    92     }
    93     if (src_locked) {
    94         SDL_UnlockSurface(src);
    95     }
    96     /* Blit is done! */
    97     return (okay ? 0 : -1);
    98 }
    99 
   100 #ifdef __MACOSX__
   101 #include <sys/sysctl.h>
   102 
   103 static SDL_bool
   104 SDL_UseAltivecPrefetch()
   105 {
   106     const char key[] = "hw.l3cachesize";
   107     u_int64_t result = 0;
   108     size_t typeSize = sizeof(result);
   109 
   110     if (sysctlbyname(key, &result, &typeSize, NULL, 0) == 0 && result > 0) {
   111         return SDL_TRUE;
   112     } else {
   113         return SDL_FALSE;
   114     }
   115 }
   116 #else
   117 static SDL_bool
   118 SDL_UseAltivecPrefetch()
   119 {
   120     /* Just guess G4 */
   121     return SDL_TRUE;
   122 }
   123 #endif /* __MACOSX__ */
   124 
   125 static SDL_BlitFunc
   126 SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags,
   127                    SDL_BlitFuncEntry * entries)
   128 {
   129     int i, flagcheck;
   130     static Uint32 features = 0xffffffff;
   131 
   132     /* Get the available CPU features */
   133     if (features == 0xffffffff) {
   134         const char *override = SDL_getenv("SDL_BLIT_CPU_FEATURES");
   135 
   136         features = SDL_CPU_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_CPU_MMX;
   144             }
   145             if (SDL_Has3DNow()) {
   146                 features |= SDL_CPU_3DNOW;
   147             }
   148             if (SDL_HasSSE()) {
   149                 features |= SDL_CPU_SSE;
   150             }
   151             if (SDL_HasSSE2()) {
   152                 features |= SDL_CPU_SSE2;
   153             }
   154             if (SDL_HasAltiVec()) {
   155                 if (SDL_UseAltivecPrefetch()) {
   156                     features |= SDL_CPU_ALTIVEC_PREFETCH;
   157                 } else {
   158                     features |= SDL_CPU_ALTIVEC_NOPREFETCH;
   159                 }
   160             }
   161         }
   162     }
   163 
   164     for (i = 0; entries[i].func; ++i) {
   165         /* Check for matching pixel formats */
   166         if (src_format != entries[i].src_format) {
   167             continue;
   168         }
   169         if (dst_format != entries[i].dst_format) {
   170             continue;
   171         }
   172 
   173         /* Check modulation flags */
   174         flagcheck =
   175             (flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_COLOR));
   176         if ((flagcheck & entries[i].flags) != flagcheck) {
   177             continue;
   178         }
   179 
   180         /* Check blend flags */
   181         flagcheck =
   182             (flags &
   183              (SDL_COPY_MASK | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD));
   184         if ((flagcheck & entries[i].flags) != flagcheck) {
   185             continue;
   186         }
   187 
   188         /* Check colorkey flag */
   189         flagcheck = (flags & SDL_COPY_COLORKEY);
   190         if ((flagcheck & entries[i].flags) != flagcheck) {
   191             continue;
   192         }
   193 
   194         /* Check scaling flags */
   195         flagcheck = (flags & SDL_COPY_NEAREST);
   196         if ((flagcheck & entries[i].flags) != flagcheck) {
   197             continue;
   198         }
   199 
   200         /* Check CPU features */
   201         flagcheck = entries[i].cpu;
   202         if ((flagcheck & features) != flagcheck) {
   203             continue;
   204         }
   205 
   206         /* We found the best one! */
   207         return entries[i].func;
   208     }
   209     return NULL;
   210 }
   211 
   212 /* Figure out which of many blit routines to set up on a surface */
   213 int
   214 SDL_CalculateBlit(SDL_Surface * surface)
   215 {
   216     SDL_BlitFunc blit = NULL;
   217     SDL_BlitMap *map = surface->map;
   218     SDL_Surface *dst = map->dst;
   219 
   220     /* Clean everything out to start */
   221     if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
   222         SDL_UnRLESurface(surface, 1);
   223     }
   224     map->blit = SDL_SoftBlit;
   225     map->info.src_fmt = surface->format;
   226     map->info.src_pitch = surface->pitch;
   227     map->info.dst_fmt = dst->format;
   228     map->info.dst_pitch = dst->pitch;
   229 
   230     /* See if we can do RLE acceleration */
   231     if (surface->map->info.flags & SDL_COPY_RLE_DESIRED) {
   232         if (SDL_RLESurface(surface) == 0) {
   233             return 0;
   234         }
   235     }
   236 
   237     /* Choose a standard blit function */
   238     if (map->identity && !map->info.flags) {
   239         /* Handle overlapping blits on the same surface */
   240         if (surface == dst) {
   241             blit = SDL_BlitCopyOverlap;
   242         } else {
   243             blit = SDL_BlitCopy;
   244         }
   245     } else if (surface->format->BitsPerPixel < 8) {
   246         blit = SDL_CalculateBlit0(surface);
   247     } else if (surface->format->BytesPerPixel == 1) {
   248         blit = SDL_CalculateBlit1(surface);
   249     } else if (map->info.flags & SDL_COPY_BLEND) {
   250         blit = SDL_CalculateBlitA(surface);
   251     } else {
   252         blit = SDL_CalculateBlitN(surface);
   253     }
   254     if (blit == NULL) {
   255         Uint32 src_format =
   256             SDL_MasksToPixelFormatEnum(surface->format->BitsPerPixel,
   257                                        surface->format->Rmask,
   258                                        surface->format->Gmask,
   259                                        surface->format->Bmask,
   260                                        surface->format->Amask);
   261         Uint32 dst_format =
   262             SDL_MasksToPixelFormatEnum(dst->format->BitsPerPixel,
   263                                        dst->format->Rmask, 
   264                                        dst->format->Gmask,
   265                                        dst->format->Bmask,
   266                                        dst->format->Amask);
   267 
   268         blit =
   269             SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags,
   270                                SDL_GeneratedBlitFuncTable);
   271     }
   272     map->data = blit;
   273 
   274     /* Make sure we have a blit function */
   275     if (blit == NULL) {
   276         SDL_InvalidateMap(map);
   277         SDL_SetError("Blit combination not supported");
   278         return (-1);
   279     }
   280 
   281     return (0);
   282 }
   283 
   284 /* vi: set ts=4 sw=4 expandtab: */