This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_blit.c
294 lines (263 loc) · 8.28 KB
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
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
14
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
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
25
26
27
28
29
#include "SDL_video.h"
#include "SDL_sysvideo.h"
#include "SDL_blit.h"
#include "SDL_RLEaccel_c.h"
#include "SDL_pixels_c.h"
30
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && SDL_ASSEMBLY_ROUTINES
31
32
33
34
#define MMX_ASMBLIT
#endif
#if defined(MMX_ASMBLIT)
35
#include "SDL_cpuinfo.h"
36
37
38
#include "mmx.h"
#endif
39
/* The general purpose software blit routine */
40
static int
41
42
SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect)
43
{
44
45
46
47
48
49
50
51
52
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;
53
54
if (SDL_MUSTLOCK(dst)) {
if (SDL_LockSurface(dst) < 0) {
55
56
57
58
59
60
61
okay = 0;
} else {
dst_locked = 1;
}
}
/* Lock the source if it's in hardware */
src_locked = 0;
62
63
if (SDL_MUSTLOCK(src)) {
if (SDL_LockSurface(src) < 0) {
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
okay = 0;
} else {
src_locked = 1;
}
}
/* Set up source and destination buffer pointers, and BLIT! */
if (okay && srcrect->w && srcrect->h) {
SDL_BlitInfo info;
SDL_loblit RunBlit;
/* Set up the blit information */
info.s_pixels = (Uint8 *) src->pixels +
(Uint16) srcrect->y * src->pitch +
(Uint16) srcrect->x * src->format->BytesPerPixel;
info.s_width = srcrect->w;
info.s_height = srcrect->h;
info.s_skip = src->pitch - info.s_width * src->format->BytesPerPixel;
info.d_pixels = (Uint8 *) dst->pixels +
(Uint16) dstrect->y * dst->pitch +
(Uint16) dstrect->x * dst->format->BytesPerPixel;
info.d_width = dstrect->w;
info.d_height = dstrect->h;
info.d_skip = dst->pitch - info.d_width * dst->format->BytesPerPixel;
info.aux_data = src->map->sw_data->aux_data;
info.src = src->format;
info.table = src->map->table;
info.dst = dst->format;
RunBlit = src->map->sw_data->blit;
/* Run the actual software blit */
95
RunBlit(&info);
96
97
98
99
}
/* We need to unlock the surfaces if they're locked */
if (dst_locked) {
100
SDL_UnlockSurface(dst);
101
102
}
if (src_locked) {
103
SDL_UnlockSurface(src);
104
105
106
}
/* Blit is done! */
return (okay ? 0 : -1);
107
108
}
109
#ifdef MMX_ASMBLIT
110
static __inline__ void
111
SDL_memcpyMMX(Uint8 * to, const Uint8 * from, int len)
112
{
113
114
115
int i;
for (i = 0; i < len / 8; i++) {
116
117
118
__asm__ __volatile__(" movq (%0), %%mm0\n"
" movq %%mm0, (%1)\n"::"r"(from),
"r"(to):"memory");
119
120
121
122
from += 8;
to += 8;
}
if (len & 7)
123
SDL_memcpy(to, from, len & 7);
124
125
}
126
static __inline__ void
127
SDL_memcpySSE(Uint8 * to, const Uint8 * from, int len)
128
{
129
130
int i;
131
132
133
134
__asm__ __volatile__(" prefetchnta (%0)\n"
" prefetchnta 64(%0)\n"
" prefetchnta 128(%0)\n"
" prefetchnta 192(%0)\n"::"r"(from));
135
136
for (i = 0; i < len / 8; i++) {
137
138
139
140
__asm__ __volatile__(" prefetchnta 256(%0)\n"
" movq (%0), %%mm0\n"
" movntq %%mm0, (%1)\n"::"r"(from),
"r"(to):"memory");
141
142
143
144
from += 8;
to += 8;
}
if (len & 7)
145
SDL_memcpy(to, from, len & 7);
146
147
148
}
#endif
149
static void
150
SDL_BlitCopy(SDL_BlitInfo * info)
151
{
152
153
154
155
156
157
158
159
160
161
Uint8 *src, *dst;
int w, h;
int srcskip, dstskip;
w = info->d_width * info->dst->BytesPerPixel;
h = info->d_height;
src = info->s_pixels;
dst = info->d_pixels;
srcskip = w + info->s_skip;
dstskip = w + info->d_skip;
162
#ifdef MMX_ASMBLIT
163
if (SDL_HasSSE()) {
164
while (h--) {
165
SDL_memcpySSE(dst, src, w);
166
167
168
src += srcskip;
dst += dstskip;
}
169
170
__asm__ __volatile__(" emms\n"::);
} else if (SDL_HasMMX()) {
171
while (h--) {
172
SDL_memcpyMMX(dst, src, w);
173
174
175
src += srcskip;
dst += dstskip;
}
176
__asm__ __volatile__(" emms\n"::);
177
} else
178
#endif
179
while (h--) {
180
SDL_memcpy(dst, src, w);
181
182
183
src += srcskip;
dst += dstskip;
}
184
185
}
186
static void
187
SDL_BlitCopyOverlap(SDL_BlitInfo * info)
188
{
189
190
191
192
193
194
195
196
197
198
199
200
Uint8 *src, *dst;
int w, h;
int srcskip, dstskip;
w = info->d_width * info->dst->BytesPerPixel;
h = info->d_height;
src = info->s_pixels;
dst = info->d_pixels;
srcskip = w + info->s_skip;
dstskip = w + info->d_skip;
if (dst < src) {
while (h--) {
201
SDL_memcpy(dst, src, w);
202
203
204
205
206
207
208
src += srcskip;
dst += dstskip;
}
} else {
src += ((h - 1) * srcskip);
dst += ((h - 1) * dstskip);
while (h--) {
209
SDL_revcpy(dst, src, w);
210
211
212
213
src -= srcskip;
dst -= dstskip;
}
}
214
215
216
}
/* Figure out which of many blit routines to set up on a surface */
217
int
218
SDL_CalculateBlit(SDL_Surface * surface)
219
{
220
221
222
223
int blit_index;
/* Clean everything out to start */
if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
224
SDL_UnRLESurface(surface, 1);
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
}
surface->map->sw_blit = NULL;
/* Get the blit function index, based on surface mode */
/* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
blit_index = 0;
blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0;
if (surface->flags & SDL_SRCALPHA
&& (surface->format->alpha != SDL_ALPHA_OPAQUE
|| surface->format->Amask)) {
blit_index |= 2;
}
/* Check for special "identity" case -- copy blit */
if (surface->map->identity && blit_index == 0) {
surface->map->sw_data->blit = SDL_BlitCopy;
/* Handle overlapping blits on the same surface */
if (surface == surface->map->dst) {
surface->map->sw_data->blit = SDL_BlitCopyOverlap;
}
} else {
if (surface->format->BitsPerPixel < 8) {
surface->map->sw_data->blit =
249
SDL_CalculateBlit0(surface, blit_index);
250
251
252
253
} else {
switch (surface->format->BytesPerPixel) {
case 1:
surface->map->sw_data->blit =
254
SDL_CalculateBlit1(surface, blit_index);
255
256
257
258
259
break;
case 2:
case 3:
case 4:
surface->map->sw_data->blit =
260
SDL_CalculateBlitN(surface, blit_index);
261
262
263
264
265
266
267
268
269
break;
default:
surface->map->sw_data->blit = NULL;
break;
}
}
}
/* Make sure we have a blit function */
if (surface->map->sw_data->blit == NULL) {
270
271
SDL_InvalidateMap(surface->map);
SDL_SetError("Blit combination not supported");
272
273
274
275
return (-1);
}
/* Choose software blitting function */
276
if (surface->flags & SDL_RLEACCELOK) {
277
278
279
if (surface->map->identity
&& (blit_index == 1
|| (blit_index == 3 && !surface->format->Amask))) {
280
if (SDL_RLESurface(surface) == 0)
281
282
surface->map->sw_blit = SDL_RLEBlit;
} else if (blit_index == 2 && surface->format->Amask) {
283
if (SDL_RLESurface(surface) == 0)
284
285
286
287
288
289
290
291
surface->map->sw_blit = SDL_RLEAlphaBlit;
}
}
if (surface->map->sw_blit == NULL) {
surface->map->sw_blit = SDL_SoftBlit;
}
return (0);
292
293
}
294
/* vi: set ts=4 sw=4 expandtab: */