This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_blit.c
280 lines (247 loc) · 7.89 KB
1
/*
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Simple DirectMedia Layer
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
20
*/
21
#include "SDL_config.h"
22
23
24
25
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#include "SDL_blit.h"
26
#include "SDL_blit_auto.h"
27
#include "SDL_blit_copy.h"
28
#include "SDL_blit_slow.h"
29
30
31
32
#include "SDL_RLEaccel_c.h"
#include "SDL_pixels_c.h"
/* The general purpose software blit routine */
33
34
35
static int
SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect)
36
{
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
int okay;
int src_locked;
int dst_locked;
/* Everything is okay at the beginning... */
okay = 1;
/* Lock the destination if it's in hardware */
dst_locked = 0;
if (SDL_MUSTLOCK(dst)) {
if (SDL_LockSurface(dst) < 0) {
okay = 0;
} else {
dst_locked = 1;
}
}
/* Lock the source if it's in hardware */
src_locked = 0;
if (SDL_MUSTLOCK(src)) {
if (SDL_LockSurface(src) < 0) {
okay = 0;
} else {
src_locked = 1;
}
}
/* Set up source and destination buffer pointers, and BLIT! */
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
73
info->src_w = srcrect->w;
info->src_h = srcrect->h;
74
info->src_pitch = src->pitch;
75
76
77
78
info->src_skip =
info->src_pitch - info->src_w * info->src_fmt->BytesPerPixel;
info->dst =
(Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch +
79
(Uint16) dstrect->x * info->dst_fmt->BytesPerPixel;
80
81
info->dst_w = dstrect->w;
info->dst_h = dstrect->h;
82
info->dst_pitch = dst->pitch;
83
84
info->dst_skip =
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
92
93
94
95
96
97
98
99
}
/* We need to unlock the surfaces if they're locked */
if (dst_locked) {
SDL_UnlockSurface(dst);
}
if (src_locked) {
SDL_UnlockSurface(src);
}
/* Blit is done! */
return (okay ? 0 : -1);
100
101
}
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#ifdef __MACOSX__
#include <sys/sysctl.h>
static SDL_bool
SDL_UseAltivecPrefetch()
{
const char key[] = "hw.l3cachesize";
u_int64_t result = 0;
size_t typeSize = sizeof(result);
if (sysctlbyname(key, &result, &typeSize, NULL, 0) == 0 && result > 0) {
return SDL_TRUE;
} else {
return SDL_FALSE;
}
}
#else
static SDL_bool
SDL_UseAltivecPrefetch()
{
/* Just guess G4 */
return SDL_TRUE;
}
#endif /* __MACOSX__ */
126
127
static SDL_BlitFunc
128
129
SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int flags,
SDL_BlitFuncEntry * entries)
130
{
131
int i, flagcheck;
132
133
static Uint32 features = 0xffffffff;
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
142
143
144
if (override) {
SDL_sscanf(override, "%u", &features);
} else {
if (SDL_HasMMX()) {
145
146
features |= SDL_CPU_MMX;
}
147
148
149
if (SDL_Has3DNow()) {
features |= SDL_CPU_3DNOW;
}
150
if (SDL_HasSSE()) {
151
152
153
154
features |= SDL_CPU_SSE;
}
if (SDL_HasSSE2()) {
features |= SDL_CPU_SSE2;
155
}
156
157
158
159
160
161
162
if (SDL_HasAltiVec()) {
if (SDL_UseAltivecPrefetch()) {
features |= SDL_CPU_ALTIVEC_PREFETCH;
} else {
features |= SDL_CPU_ALTIVEC_NOPREFETCH;
}
}
163
}
164
165
}
166
for (i = 0; entries[i].func; ++i) {
167
/* Check for matching pixel formats */
168
169
170
171
172
173
if (src_format != entries[i].src_format) {
continue;
}
if (dst_format != entries[i].dst_format) {
continue;
}
174
175
/* Check modulation flags */
176
flagcheck =
177
(flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA));
178
179
180
181
182
if ((flagcheck & entries[i].flags) != flagcheck) {
continue;
}
/* Check blend flags */
183
184
185
flagcheck =
(flags &
(SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD));
186
187
188
189
190
191
192
193
194
195
196
197
198
if ((flagcheck & entries[i].flags) != flagcheck) {
continue;
}
/* Check colorkey flag */
flagcheck = (flags & SDL_COPY_COLORKEY);
if ((flagcheck & entries[i].flags) != flagcheck) {
continue;
}
/* Check scaling flags */
flagcheck = (flags & SDL_COPY_NEAREST);
if ((flagcheck & entries[i].flags) != flagcheck) {
199
continue;
200
}
201
202
203
204
/* Check CPU features */
flagcheck = entries[i].cpu;
if ((flagcheck & features) != flagcheck) {
205
206
continue;
}
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 */
215
216
int
SDL_CalculateBlit(SDL_Surface * surface)
217
{
218
SDL_BlitFunc blit = NULL;
219
220
SDL_BlitMap *map = surface->map;
SDL_Surface *dst = map->dst;
221
222
223
224
225
/* Clean everything out to start */
if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
SDL_UnRLESurface(surface, 1);
}
226
227
228
229
230
231
232
map->blit = SDL_SoftBlit;
map->info.src_fmt = surface->format;
map->info.src_pitch = surface->pitch;
map->info.dst_fmt = dst->format;
map->info.dst_pitch = dst->pitch;
/* See if we can do RLE acceleration */
233
if (map->info.flags & SDL_COPY_RLE_DESIRED) {
234
235
236
237
if (SDL_RLESurface(surface) == 0) {
return 0;
}
}
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
blit = SDL_CalculateBlit0(surface);
244
} else if (surface->format->BytesPerPixel == 1) {
245
246
247
blit = SDL_CalculateBlit1(surface);
} else if (map->info.flags & SDL_COPY_BLEND) {
blit = SDL_CalculateBlitA(surface);
248
} else {
249
blit = SDL_CalculateBlitN(surface);
250
}
251
if (blit == NULL) {
252
253
Uint32 src_format = surface->format->format;
Uint32 dst_format = dst->format->format;
254
255
256
257
blit =
SDL_ChooseBlitFunc(src_format, dst_format, map->info.flags,
SDL_GeneratedBlitFuncTable);
258
}
259
260
261
262
263
264
265
266
267
#ifndef TEST_SLOW_BLIT
if (blit == NULL)
#endif
{
if (surface->format->BytesPerPixel > 1
&& dst->format->BytesPerPixel > 1) {
blit = SDL_Blit_Slow;
}
}
268
map->data = blit;
269
270
/* Make sure we have a blit function */
271
if (blit == NULL) {
272
SDL_InvalidateMap(map);
273
274
275
276
277
SDL_SetError("Blit combination not supported");
return (-1);
}
return (0);
278
279
}
280
/* vi: set ts=4 sw=4 expandtab: */