src/video/SDL_blit.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 17 Aug 2007 06:40:12 +0000
changeset 2263 900c35d8e8fd
parent 2262 bee005ace1bf
child 2265 265bb136af92
permissions -rw-r--r--
More work in progress, still doesn't compile...
     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->dst = (Uint8 *) dst->pixels +
    75             (Uint16) dstrect->y * dst->pitch +
    76             (Uint16) dstrect->x * info->dst_fmt->BytesPerPixel;
    77         info->dst_w = dstrect->w;
    78         info->dst_h = dstrect->h;
    79         RunBlit = (SDL_BlitFunc) src->map->data;
    80 
    81         /* Run the actual software blit */
    82         RunBlit(info);
    83     }
    84 
    85     /* We need to unlock the surfaces if they're locked */
    86     if (dst_locked) {
    87         SDL_UnlockSurface(dst);
    88     }
    89     if (src_locked) {
    90         SDL_UnlockSurface(src);
    91     }
    92     /* Blit is done! */
    93     return (okay ? 0 : -1);
    94 }
    95 
    96 #ifdef __MACOSX__
    97 #include <sys/sysctl.h>
    98 
    99 static SDL_bool
   100 SDL_UseAltivecPrefetch()
   101 {
   102     const char key[] = "hw.l3cachesize";
   103     u_int64_t result = 0;
   104     size_t typeSize = sizeof(result);
   105 
   106     if (sysctlbyname(key, &result, &typeSize, NULL, 0) == 0 && result > 0) {
   107         return SDL_TRUE;
   108     } else {
   109         return SDL_FALSE;
   110     }
   111 }
   112 #else
   113 static SDL_bool
   114 SDL_UseAltivecPrefetch()
   115 {
   116     /* Just guess G4 */
   117     return SDL_TRUE;
   118 }
   119 #endif /* __MACOSX__ */
   120 
   121 static SDL_BlitFunc
   122 SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags, SDL_BlitFuncEntry * entries)
   123 {
   124     int i;
   125     static Uint32 features = 0xffffffff;
   126 
   127     /* Get the available CPU features */
   128     if (features == 0xffffffff) {
   129         const char *override = SDL_getenv("SDL_BLIT_CPU_FEATURES");
   130 
   131         features = SDL_CPU_ANY;
   132 
   133         /* Allow an override for testing .. */
   134         if (override) {
   135             SDL_sscanf(override, "%u", &features);
   136         } else {
   137             if (SDL_HasMMX()) {
   138                 features |= SDL_CPU_MMX;
   139             }
   140             if (SDL_Has3DNow()) {
   141                 features |= SDL_CPU_3DNOW;
   142             }
   143             if (SDL_HasSSE()) {
   144                 features |= SDL_CPU_SSE;
   145             }
   146             if (SDL_HasSSE2()) {
   147                 features |= SDL_CPU_SSE2;
   148             }
   149             if (SDL_HasAltiVec()) {
   150                 if (SDL_UseAltivecPrefetch()) {
   151                     features |= SDL_CPU_ALTIVEC_PREFETCH;
   152                 } else {
   153                     features |= SDL_CPU_ALTIVEC_NOPREFETCH;
   154                 }
   155             }
   156         }
   157     }
   158 
   159     for (i = 0; entries[i].func; ++i) {
   160         if (src_format != entries[i].src_format) {
   161             continue;
   162         }
   163         if (dst_format != entries[i].dst_format) {
   164             continue;
   165         }
   166         if ((flags & entries[i].flags) != flags) {
   167             continue;
   168         }
   169         if (!(features & entries[i].cpu)) {
   170             continue;
   171         }
   172         return entries[i].func;
   173     }
   174     return NULL;
   175 }
   176 
   177 /* Figure out which of many blit routines to set up on a surface */
   178 int
   179 SDL_CalculateBlit(SDL_Surface * surface)
   180 {
   181     SDL_BlitFunc blit = NULL;
   182     SDL_Surface *dst = surface->map->dst;
   183     Uint32 src_format;
   184     Uint32 dst_format;
   185 
   186     /* Clean everything out to start */
   187     if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
   188         SDL_UnRLESurface(surface, 1);
   189     }
   190     surface->map->blit = NULL;
   191     surface->map->info.src_fmt = surface->format;
   192     surface->map->info.src_pitch = surface->pitch;
   193     surface->map->info.dst_fmt = dst->format;
   194     surface->map->info.dst_pitch = dst->pitch;
   195 
   196     src_format = SDL_MasksToPixelFormatEnum(surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask);
   197     dst_format = SDL_MasksToPixelFormatEnum(dst->format->BitsPerPixel, dst->format->Rmask, dst->format->Gmask, dst->format->Bmask, dst->format->Amask);
   198 
   199     /* Check for special "identity" case -- copy blit */
   200     if (surface->map->identity && !surface->map->info.flags) {
   201         /* Handle overlapping blits on the same surface */
   202         if (surface == dst) {
   203             blit = SDL_BlitCopyOverlap;
   204         } else {
   205             blit = SDL_BlitCopy;
   206         }
   207     } else {
   208         if (surface->format->BitsPerPixel < 8) {
   209             blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_BlitFuncTable0);
   210         } else {
   211             switch (surface->format->BytesPerPixel) {
   212             case 1:
   213                 blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_BlitFuncTable1);
   214                 break;
   215             case 2:
   216             case 3:
   217             case 4:
   218                 blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_BlitFuncTableN);
   219                 break;
   220             }
   221         }
   222     }
   223     if (blit == NULL) {
   224         blit = SDL_ChooseBlitFunc(src_format, dst_format, surface->map->info.flags, SDL_GeneratedBlitFuncTable);
   225     }
   226 
   227     /* Make sure we have a blit function */
   228     if (blit == NULL) {
   229         SDL_InvalidateMap(surface->map);
   230         SDL_SetError("Blit combination not supported");
   231         return (-1);
   232     }
   233 
   234     /* Choose software blitting function */
   235     if (surface->flags & SDL_RLEACCELOK) {
   236         if (surface->map->identity
   237             && (blit_index == 1
   238                 || (blit_index == 3 && !surface->format->Amask))) {
   239             if (SDL_RLESurface(surface) == 0)
   240                 surface->map->blit = SDL_RLEBlit;
   241         } else if (blit_index == 2 && surface->format->Amask) {
   242             if (SDL_RLESurface(surface) == 0)
   243                 surface->map->blit = SDL_RLEAlphaBlit;
   244         }
   245     }
   246 
   247     if (surface->map->blit == NULL) {
   248         surface->map->blit = SDL_SoftBlit;
   249         surface->map->data = blit;
   250     }
   251     return (0);
   252 }
   253 
   254 /* vi: set ts=4 sw=4 expandtab: */