2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../SDL_internal.h"
23 #include "SDL_video.h"
24 #include "SDL_sysvideo.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"
32 /* The general purpose software blit routine */
34 SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect,
35 SDL_Surface * dst, SDL_Rect * dstrect)
41 /* Everything is okay at the beginning... */
44 /* Lock the destination if it's in hardware */
46 if (SDL_MUSTLOCK(dst)) {
47 if (SDL_LockSurface(dst) < 0) {
53 /* Lock the source if it's in hardware */
55 if (SDL_MUSTLOCK(src)) {
56 if (SDL_LockSurface(src) < 0) {
63 /* Set up source and destination buffer pointers, and BLIT! */
64 if (okay && !SDL_RectEmpty(srcrect)) {
66 SDL_BlitInfo *info = &src->map->info;
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;
76 info->src_pitch - info->src_w * info->src_fmt->BytesPerPixel;
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;
84 info->dst_pitch - info->dst_w * info->dst_fmt->BytesPerPixel;
85 RunBlit = (SDL_BlitFunc) src->map->data;
87 /* Run the actual software blit */
91 /* We need to unlock the surfaces if they're locked */
93 SDL_UnlockSurface(dst);
96 SDL_UnlockSurface(src);
99 return (okay ? 0 : -1);
102 #if SDL_HAVE_BLIT_AUTO
105 #include <sys/sysctl.h>
108 SDL_UseAltivecPrefetch()
110 const char key[] = "hw.l3cachesize";
111 u_int64_t result = 0;
112 size_t typeSize = sizeof(result);
114 if (sysctlbyname(key, &result, &typeSize, NULL, 0) == 0 && result > 0) {
122 SDL_UseAltivecPrefetch()
127 #endif /* __MACOSX__ */
130 SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags,
131 SDL_BlitFuncEntry * entries)
133 int i, flagcheck = (flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL | SDL_COPY_COLORKEY | SDL_COPY_NEAREST));
134 static int features = 0x7fffffff;
136 /* Get the available CPU features */
137 if (features == 0x7fffffff) {
138 const char *override = SDL_getenv("SDL_BLIT_CPU_FEATURES");
140 features = SDL_CPU_ANY;
142 /* Allow an override for testing .. */
144 SDL_sscanf(override, "%u", &features);
147 features |= SDL_CPU_MMX;
149 if (SDL_Has3DNow()) {
150 features |= SDL_CPU_3DNOW;
153 features |= SDL_CPU_SSE;
156 features |= SDL_CPU_SSE2;
158 if (SDL_HasAltiVec()) {
159 if (SDL_UseAltivecPrefetch()) {
160 features |= SDL_CPU_ALTIVEC_PREFETCH;
162 features |= SDL_CPU_ALTIVEC_NOPREFETCH;
168 for (i = 0; entries[i].func; ++i) {
169 /* Check for matching pixel formats */
170 if (src_format != entries[i].src_format) {
173 if (dst_format != entries[i].dst_format) {
178 if ((flagcheck & entries[i].flags) != flagcheck) {
182 /* Check CPU features */
183 if ((entries[i].cpu & features) != entries[i].cpu) {
187 /* We found the best one! */
188 return entries[i].func;
192 #endif /* SDL_HAVE_BLIT_AUTO */
194 /* Figure out which of many blit routines to set up on a surface */
196 SDL_CalculateBlit(SDL_Surface * surface)
198 SDL_BlitFunc blit = NULL;
199 SDL_BlitMap *map = surface->map;
200 SDL_Surface *dst = map->dst;
202 /* We don't currently support blitting to < 8 bpp surfaces */
203 if (dst->format->BitsPerPixel < 8) {
204 SDL_InvalidateMap(map);
205 return SDL_SetError("Blit combination not supported");
209 /* Clean everything out to start */
210 if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
211 SDL_UnRLESurface(surface, 1);
215 map->blit = SDL_SoftBlit;
216 map->info.src_fmt = surface->format;
217 map->info.src_pitch = surface->pitch;
218 map->info.dst_fmt = dst->format;
219 map->info.dst_pitch = dst->pitch;
222 /* See if we can do RLE acceleration */
223 if (map->info.flags & SDL_COPY_RLE_DESIRED) {
224 if (SDL_RLESurface(surface) == 0) {
230 /* Choose a standard blit function */
231 if (map->identity && !(map->info.flags & ~SDL_COPY_RLE_DESIRED)) {
233 } else if (surface->format->Rloss > 8 || dst->format->Rloss > 8) {
234 /* Greater than 8 bits per channel not supported yet */
235 SDL_InvalidateMap(map);
236 return SDL_SetError("Blit combination not supported");
239 else if (surface->format->BitsPerPixel < 8 &&
240 SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
241 blit = SDL_CalculateBlit0(surface);
245 else if (surface->format->BytesPerPixel == 1 &&
246 SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
247 blit = SDL_CalculateBlit1(surface);
251 else if (map->info.flags & SDL_COPY_BLEND) {
252 blit = SDL_CalculateBlitA(surface);
257 blit = SDL_CalculateBlitN(surface);
260 #if SDL_HAVE_BLIT_AUTO
262 Uint32 src_format = surface->format->format;
263 Uint32 dst_format = dst->format->format;
266 SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags,
267 SDL_GeneratedBlitFuncTable);
271 #ifndef TEST_SLOW_BLIT
275 Uint32 src_format = surface->format->format;
276 Uint32 dst_format = dst->format->format;
278 if (!SDL_ISPIXELFORMAT_INDEXED(src_format) &&
279 !SDL_ISPIXELFORMAT_FOURCC(src_format) &&
280 !SDL_ISPIXELFORMAT_INDEXED(dst_format) &&
281 !SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
282 blit = SDL_Blit_Slow;
287 /* Make sure we have a blit function */
289 SDL_InvalidateMap(map);
290 return SDL_SetError("Blit combination not supported");
296 /* vi: set ts=4 sw=4 expandtab: */