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