comparison src/video/SDL_blit.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents d910939febfa
children 93994f65c74c
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
35 #include "SDL_cpuinfo.h" 35 #include "SDL_cpuinfo.h"
36 #include "mmx.h" 36 #include "mmx.h"
37 #endif 37 #endif
38 38
39 /* The general purpose software blit routine */ 39 /* The general purpose software blit routine */
40 static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect, 40 static int
41 SDL_Surface *dst, SDL_Rect *dstrect) 41 SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect,
42 { 42 SDL_Surface * dst, SDL_Rect * dstrect)
43 int okay; 43 {
44 int src_locked; 44 int okay;
45 int dst_locked; 45 int src_locked;
46 46 int dst_locked;
47 /* Everything is okay at the beginning... */ 47
48 okay = 1; 48 /* Everything is okay at the beginning... */
49 49 okay = 1;
50 /* Lock the destination if it's in hardware */ 50
51 dst_locked = 0; 51 /* Lock the destination if it's in hardware */
52 if ( SDL_MUSTLOCK(dst) ) { 52 dst_locked = 0;
53 if ( SDL_LockSurface(dst) < 0 ) { 53 if (SDL_MUSTLOCK(dst)) {
54 okay = 0; 54 if (SDL_LockSurface(dst) < 0) {
55 } else { 55 okay = 0;
56 dst_locked = 1; 56 } else {
57 } 57 dst_locked = 1;
58 } 58 }
59 /* Lock the source if it's in hardware */ 59 }
60 src_locked = 0; 60 /* Lock the source if it's in hardware */
61 if ( SDL_MUSTLOCK(src) ) { 61 src_locked = 0;
62 if ( SDL_LockSurface(src) < 0 ) { 62 if (SDL_MUSTLOCK(src)) {
63 okay = 0; 63 if (SDL_LockSurface(src) < 0) {
64 } else { 64 okay = 0;
65 src_locked = 1; 65 } else {
66 } 66 src_locked = 1;
67 } 67 }
68 68 }
69 /* Set up source and destination buffer pointers, and BLIT! */ 69
70 if ( okay && srcrect->w && srcrect->h ) { 70 /* Set up source and destination buffer pointers, and BLIT! */
71 SDL_BlitInfo info; 71 if (okay && srcrect->w && srcrect->h) {
72 SDL_loblit RunBlit; 72 SDL_BlitInfo info;
73 73 SDL_loblit RunBlit;
74 /* Set up the blit information */ 74
75 info.s_pixels = (Uint8 *)src->pixels + 75 /* Set up the blit information */
76 (Uint16)srcrect->y*src->pitch + 76 info.s_pixels = (Uint8 *) src->pixels +
77 (Uint16)srcrect->x*src->format->BytesPerPixel; 77 (Uint16) srcrect->y * src->pitch +
78 info.s_width = srcrect->w; 78 (Uint16) srcrect->x * src->format->BytesPerPixel;
79 info.s_height = srcrect->h; 79 info.s_width = srcrect->w;
80 info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel; 80 info.s_height = srcrect->h;
81 info.d_pixels = (Uint8 *)dst->pixels + 81 info.s_skip = src->pitch - info.s_width * src->format->BytesPerPixel;
82 (Uint16)dstrect->y*dst->pitch + 82 info.d_pixels = (Uint8 *) dst->pixels +
83 (Uint16)dstrect->x*dst->format->BytesPerPixel; 83 (Uint16) dstrect->y * dst->pitch +
84 info.d_width = dstrect->w; 84 (Uint16) dstrect->x * dst->format->BytesPerPixel;
85 info.d_height = dstrect->h; 85 info.d_width = dstrect->w;
86 info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel; 86 info.d_height = dstrect->h;
87 info.aux_data = src->map->sw_data->aux_data; 87 info.d_skip = dst->pitch - info.d_width * dst->format->BytesPerPixel;
88 info.src = src->format; 88 info.aux_data = src->map->sw_data->aux_data;
89 info.table = src->map->table; 89 info.src = src->format;
90 info.dst = dst->format; 90 info.table = src->map->table;
91 RunBlit = src->map->sw_data->blit; 91 info.dst = dst->format;
92 92 RunBlit = src->map->sw_data->blit;
93 /* Run the actual software blit */ 93
94 RunBlit(&info); 94 /* Run the actual software blit */
95 } 95 RunBlit(&info);
96 96 }
97 /* We need to unlock the surfaces if they're locked */ 97
98 if ( dst_locked ) { 98 /* We need to unlock the surfaces if they're locked */
99 SDL_UnlockSurface(dst); 99 if (dst_locked) {
100 } 100 SDL_UnlockSurface(dst);
101 if ( src_locked ) { 101 }
102 SDL_UnlockSurface(src); 102 if (src_locked) {
103 } 103 SDL_UnlockSurface(src);
104 /* Blit is done! */ 104 }
105 return(okay ? 0 : -1); 105 /* Blit is done! */
106 return (okay ? 0 : -1);
106 } 107 }
107 108
108 #ifdef MMX_ASMBLIT 109 #ifdef MMX_ASMBLIT
109 static __inline__ void SDL_memcpyMMX(Uint8 *to, const Uint8 *from, int len) 110 static __inline__ void
110 { 111 SDL_memcpyMMX(Uint8 * to, const Uint8 * from, int len)
111 int i; 112 {
112 113 int i;
113 for(i=0; i<len/8; i++) { 114
114 __asm__ __volatile__ ( 115 for (i = 0; i < len / 8; i++) {
115 " movq (%0), %%mm0\n" 116 __asm__ __volatile__(" movq (%0), %%mm0\n"
116 " movq %%mm0, (%1)\n" 117 " movq %%mm0, (%1)\n"::"r"(from),
117 : : "r" (from), "r" (to) : "memory"); 118 "r"(to):"memory");
118 from+=8; 119 from += 8;
119 to+=8; 120 to += 8;
120 } 121 }
121 if (len&7) 122 if (len & 7)
122 SDL_memcpy(to, from, len&7); 123 SDL_memcpy(to, from, len & 7);
123 } 124 }
124 125
125 static __inline__ void SDL_memcpySSE(Uint8 *to, const Uint8 *from, int len) 126 static __inline__ void
126 { 127 SDL_memcpySSE(Uint8 * to, const Uint8 * from, int len)
127 int i; 128 {
128 129 int i;
129 __asm__ __volatile__ ( 130
130 " prefetchnta (%0)\n" 131 __asm__ __volatile__(" prefetchnta (%0)\n"
131 " prefetchnta 64(%0)\n" 132 " prefetchnta 64(%0)\n"
132 " prefetchnta 128(%0)\n" 133 " prefetchnta 128(%0)\n"
133 " prefetchnta 192(%0)\n" 134 " prefetchnta 192(%0)\n"::"r"(from));
134 : : "r" (from) ); 135
135 136 for (i = 0; i < len / 8; i++) {
136 for(i=0; i<len/8; i++) { 137 __asm__ __volatile__(" prefetchnta 256(%0)\n"
137 __asm__ __volatile__ ( 138 " movq (%0), %%mm0\n"
138 " prefetchnta 256(%0)\n" 139 " movntq %%mm0, (%1)\n"::"r"(from),
139 " movq (%0), %%mm0\n" 140 "r"(to):"memory");
140 " movntq %%mm0, (%1)\n" 141 from += 8;
141 : : "r" (from), "r" (to) : "memory"); 142 to += 8;
142 from+=8; 143 }
143 to+=8; 144 if (len & 7)
144 } 145 SDL_memcpy(to, from, len & 7);
145 if (len&7) 146 }
146 SDL_memcpy(to, from, len&7); 147 #endif
147 } 148
148 #endif 149 static void
149 150 SDL_BlitCopy(SDL_BlitInfo * info)
150 static void SDL_BlitCopy(SDL_BlitInfo *info) 151 {
151 { 152 Uint8 *src, *dst;
152 Uint8 *src, *dst; 153 int w, h;
153 int w, h; 154 int srcskip, dstskip;
154 int srcskip, dstskip; 155
155 156 w = info->d_width * info->dst->BytesPerPixel;
156 w = info->d_width*info->dst->BytesPerPixel; 157 h = info->d_height;
157 h = info->d_height; 158 src = info->s_pixels;
158 src = info->s_pixels; 159 dst = info->d_pixels;
159 dst = info->d_pixels; 160 srcskip = w + info->s_skip;
160 srcskip = w+info->s_skip; 161 dstskip = w + info->d_skip;
161 dstskip = w+info->d_skip;
162 #ifdef MMX_ASMBLIT 162 #ifdef MMX_ASMBLIT
163 if(SDL_HasSSE()) 163 if (SDL_HasSSE()) {
164 { 164 while (h--) {
165 while ( h-- ) { 165 SDL_memcpySSE(dst, src, w);
166 SDL_memcpySSE(dst, src, w); 166 src += srcskip;
167 src += srcskip; 167 dst += dstskip;
168 dst += dstskip; 168 }
169 } 169 __asm__ __volatile__(" emms\n"::);
170 __asm__ __volatile__ ( 170 } else if (SDL_HasMMX()) {
171 " emms\n" 171 while (h--) {
172 ::); 172 SDL_memcpyMMX(dst, src, w);
173 } 173 src += srcskip;
174 else 174 dst += dstskip;
175 if(SDL_HasMMX()) 175 }
176 { 176 __asm__ __volatile__(" emms\n"::);
177 while ( h-- ) { 177 } else
178 SDL_memcpyMMX(dst, src, w); 178 #endif
179 src += srcskip; 179 while (h--) {
180 dst += dstskip; 180 SDL_memcpy(dst, src, w);
181 } 181 src += srcskip;
182 __asm__ __volatile__ ( 182 dst += dstskip;
183 " emms\n" 183 }
184 ::); 184 }
185 } 185
186 else 186 static void
187 #endif 187 SDL_BlitCopyOverlap(SDL_BlitInfo * info)
188 while ( h-- ) { 188 {
189 SDL_memcpy(dst, src, w); 189 Uint8 *src, *dst;
190 src += srcskip; 190 int w, h;
191 dst += dstskip; 191 int srcskip, dstskip;
192 } 192
193 } 193 w = info->d_width * info->dst->BytesPerPixel;
194 194 h = info->d_height;
195 static void SDL_BlitCopyOverlap(SDL_BlitInfo *info) 195 src = info->s_pixels;
196 { 196 dst = info->d_pixels;
197 Uint8 *src, *dst; 197 srcskip = w + info->s_skip;
198 int w, h; 198 dstskip = w + info->d_skip;
199 int srcskip, dstskip; 199 if (dst < src) {
200 200 while (h--) {
201 w = info->d_width*info->dst->BytesPerPixel; 201 SDL_memcpy(dst, src, w);
202 h = info->d_height; 202 src += srcskip;
203 src = info->s_pixels; 203 dst += dstskip;
204 dst = info->d_pixels; 204 }
205 srcskip = w+info->s_skip; 205 } else {
206 dstskip = w+info->d_skip; 206 src += ((h - 1) * srcskip);
207 if ( dst < src ) { 207 dst += ((h - 1) * dstskip);
208 while ( h-- ) { 208 while (h--) {
209 SDL_memcpy(dst, src, w); 209 SDL_revcpy(dst, src, w);
210 src += srcskip; 210 src -= srcskip;
211 dst += dstskip; 211 dst -= dstskip;
212 } 212 }
213 } else { 213 }
214 src += ((h-1) * srcskip);
215 dst += ((h-1) * dstskip);
216 while ( h-- ) {
217 SDL_revcpy(dst, src, w);
218 src -= srcskip;
219 dst -= dstskip;
220 }
221 }
222 } 214 }
223 215
224 /* Figure out which of many blit routines to set up on a surface */ 216 /* Figure out which of many blit routines to set up on a surface */
225 int SDL_CalculateBlit(SDL_Surface *surface) 217 int
226 { 218 SDL_CalculateBlit(SDL_Surface * surface)
227 int blit_index; 219 {
228 220 int blit_index;
229 /* Clean everything out to start */ 221
230 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { 222 /* Clean everything out to start */
231 SDL_UnRLESurface(surface, 1); 223 if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
232 } 224 SDL_UnRLESurface(surface, 1);
233 surface->map->sw_blit = NULL; 225 }
234 226 surface->map->sw_blit = NULL;
235 /* Figure out if an accelerated hardware blit is possible */ 227
236 surface->flags &= ~SDL_HWACCEL; 228 /* Get the blit function index, based on surface mode */
237 if ( surface->map->identity ) { 229 /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
238 int hw_blit_ok; 230 blit_index = 0;
239 231 blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0;
240 if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { 232 if (surface->flags & SDL_SRCALPHA
241 /* We only support accelerated blitting to hardware */ 233 && (surface->format->alpha != SDL_ALPHA_OPAQUE
242 if ( surface->map->dst->flags & SDL_HWSURFACE ) { 234 || surface->format->Amask)) {
243 hw_blit_ok = current_video->info.blit_hw; 235 blit_index |= 2;
244 } else { 236 }
245 hw_blit_ok = 0; 237
246 } 238 /* Check for special "identity" case -- copy blit */
247 if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { 239 if (surface->map->identity && blit_index == 0) {
248 hw_blit_ok = current_video->info.blit_hw_CC; 240 surface->map->sw_data->blit = SDL_BlitCopy;
249 } 241
250 if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { 242 /* Handle overlapping blits on the same surface */
251 hw_blit_ok = current_video->info.blit_hw_A; 243 if (surface == surface->map->dst) {
252 } 244 surface->map->sw_data->blit = SDL_BlitCopyOverlap;
253 } else { 245 }
254 /* We only support accelerated blitting to hardware */ 246 } else {
255 if ( surface->map->dst->flags & SDL_HWSURFACE ) { 247 if (surface->format->BitsPerPixel < 8) {
256 hw_blit_ok = current_video->info.blit_sw; 248 surface->map->sw_data->blit =
257 } else { 249 SDL_CalculateBlit0(surface, blit_index);
258 hw_blit_ok = 0; 250 } else {
259 } 251 switch (surface->format->BytesPerPixel) {
260 if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { 252 case 1:
261 hw_blit_ok = current_video->info.blit_sw_CC; 253 surface->map->sw_data->blit =
262 } 254 SDL_CalculateBlit1(surface, blit_index);
263 if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { 255 break;
264 hw_blit_ok = current_video->info.blit_sw_A; 256 case 2:
265 } 257 case 3:
266 } 258 case 4:
267 if ( hw_blit_ok ) { 259 surface->map->sw_data->blit =
268 SDL_VideoDevice *video = current_video; 260 SDL_CalculateBlitN(surface, blit_index);
269 SDL_VideoDevice *this = current_video; 261 break;
270 video->CheckHWBlit(this, surface, surface->map->dst); 262 default:
271 } 263 surface->map->sw_data->blit = NULL;
272 } 264 break;
273 265 }
274 /* if an alpha pixel format is specified, we can accelerate alpha blits */ 266 }
275 if (((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE )&&(current_video->displayformatalphapixel)) 267 }
276 { 268 /* Make sure we have a blit function */
277 if ( (surface->flags & SDL_SRCALPHA) ) 269 if (surface->map->sw_data->blit == NULL) {
278 if ( current_video->info.blit_hw_A ) { 270 SDL_InvalidateMap(surface->map);
279 SDL_VideoDevice *video = current_video; 271 SDL_SetError("Blit combination not supported");
280 SDL_VideoDevice *this = current_video; 272 return (-1);
281 video->CheckHWBlit(this, surface, surface->map->dst); 273 }
282 } 274
283 } 275 /* Choose software blitting function */
284 276 if (surface->flags & SDL_RLEACCELOK) {
285 /* Get the blit function index, based on surface mode */ 277 if (surface->map->identity
286 /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */ 278 && (blit_index == 1
287 blit_index = 0; 279 || (blit_index == 3 && !surface->format->Amask))) {
288 blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0; 280 if (SDL_RLESurface(surface) == 0)
289 if ( surface->flags & SDL_SRCALPHA 281 surface->map->sw_blit = SDL_RLEBlit;
290 && (surface->format->alpha != SDL_ALPHA_OPAQUE 282 } else if (blit_index == 2 && surface->format->Amask) {
291 || surface->format->Amask) ) { 283 if (SDL_RLESurface(surface) == 0)
292 blit_index |= 2; 284 surface->map->sw_blit = SDL_RLEAlphaBlit;
293 } 285 }
294 286 }
295 /* Check for special "identity" case -- copy blit */ 287
296 if ( surface->map->identity && blit_index == 0 ) { 288 if (surface->map->sw_blit == NULL) {
297 surface->map->sw_data->blit = SDL_BlitCopy; 289 surface->map->sw_blit = SDL_SoftBlit;
298 290 }
299 /* Handle overlapping blits on the same surface */ 291 return (0);
300 if ( surface == surface->map->dst ) { 292 }
301 surface->map->sw_data->blit = SDL_BlitCopyOverlap; 293
302 } 294 /* vi: set ts=4 sw=4 expandtab: */
303 } else {
304 if ( surface->format->BitsPerPixel < 8 ) {
305 surface->map->sw_data->blit =
306 SDL_CalculateBlit0(surface, blit_index);
307 } else {
308 switch ( surface->format->BytesPerPixel ) {
309 case 1:
310 surface->map->sw_data->blit =
311 SDL_CalculateBlit1(surface, blit_index);
312 break;
313 case 2:
314 case 3:
315 case 4:
316 surface->map->sw_data->blit =
317 SDL_CalculateBlitN(surface, blit_index);
318 break;
319 default:
320 surface->map->sw_data->blit = NULL;
321 break;
322 }
323 }
324 }
325 /* Make sure we have a blit function */
326 if ( surface->map->sw_data->blit == NULL ) {
327 SDL_InvalidateMap(surface->map);
328 SDL_SetError("Blit combination not supported");
329 return(-1);
330 }
331
332 /* Choose software blitting function */
333 if(surface->flags & SDL_RLEACCELOK
334 && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) {
335
336 if(surface->map->identity
337 && (blit_index == 1
338 || (blit_index == 3 && !surface->format->Amask))) {
339 if ( SDL_RLESurface(surface) == 0 )
340 surface->map->sw_blit = SDL_RLEBlit;
341 } else if(blit_index == 2 && surface->format->Amask) {
342 if ( SDL_RLESurface(surface) == 0 )
343 surface->map->sw_blit = SDL_RLEAlphaBlit;
344 }
345 }
346
347 if ( surface->map->sw_blit == NULL ) {
348 surface->map->sw_blit = SDL_SoftBlit;
349 }
350 return(0);
351 }
352