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