comparison src/video/SDL_blit.c @ 1662:782fd950bd46 SDL-1.3

Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API. WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid. The code is now run through a consistent indent format: indent -i4 -nut -nsc -br -ce The headers are being converted to automatically generate doxygen documentation.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 28 May 2006 13:04:16 +0000
parents e49147870aac
children 4da1ee79c9af
comparison
equal deleted inserted replaced
1661:281d3f4870e5 1662:782fd950bd46
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 SDL_memcpy(to, from, len&7);
147 } 146 }
148 #endif 147 #endif
149 148
150 static void SDL_BlitCopy(SDL_BlitInfo *info) 149 static void
151 { 150 SDL_BlitCopy (SDL_BlitInfo * info)
152 Uint8 *src, *dst; 151 {
153 int w, h; 152 Uint8 *src, *dst;
154 int srcskip, dstskip; 153 int w, h;
155 154 int srcskip, dstskip;
156 w = info->d_width*info->dst->BytesPerPixel; 155
157 h = info->d_height; 156 w = info->d_width * info->dst->BytesPerPixel;
158 src = info->s_pixels; 157 h = info->d_height;
159 dst = info->d_pixels; 158 src = info->s_pixels;
160 srcskip = w+info->s_skip; 159 dst = info->d_pixels;
161 dstskip = w+info->d_skip; 160 srcskip = w + info->s_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);
179 src += srcskip;
180 dst += dstskip;
181 }
182 __asm__ __volatile__ (
183 " emms\n"
184 ::);
185 }
186 else
187 #endif 178 #endif
188 while ( h-- ) { 179 while (h--) {
189 SDL_memcpy(dst, src, w); 180 SDL_memcpy (dst, src, w);
190 src += srcskip; 181 src += srcskip;
191 dst += dstskip; 182 dst += dstskip;
192 } 183 }
193 } 184 }
194 185
195 static void SDL_BlitCopyOverlap(SDL_BlitInfo *info) 186 static void
196 { 187 SDL_BlitCopyOverlap (SDL_BlitInfo * info)
197 Uint8 *src, *dst; 188 {
198 int w, h; 189 Uint8 *src, *dst;
199 int srcskip, dstskip; 190 int w, h;
200 191 int srcskip, dstskip;
201 w = info->d_width*info->dst->BytesPerPixel; 192
202 h = info->d_height; 193 w = info->d_width * info->dst->BytesPerPixel;
203 src = info->s_pixels; 194 h = info->d_height;
204 dst = info->d_pixels; 195 src = info->s_pixels;
205 srcskip = w+info->s_skip; 196 dst = info->d_pixels;
206 dstskip = w+info->d_skip; 197 srcskip = w + info->s_skip;
207 if ( dst < src ) { 198 dstskip = w + info->d_skip;
208 while ( h-- ) { 199 if (dst < src) {
209 SDL_memcpy(dst, src, w); 200 while (h--) {
210 src += srcskip; 201 SDL_memcpy (dst, src, w);
211 dst += dstskip; 202 src += srcskip;
212 } 203 dst += dstskip;
213 } else { 204 }
214 src += ((h-1) * srcskip); 205 } else {
215 dst += ((h-1) * dstskip); 206 src += ((h - 1) * srcskip);
216 while ( h-- ) { 207 dst += ((h - 1) * dstskip);
217 SDL_revcpy(dst, src, w); 208 while (h--) {
218 src -= srcskip; 209 SDL_revcpy (dst, src, w);
219 dst -= dstskip; 210 src -= srcskip;
220 } 211 dst -= dstskip;
221 } 212 }
213 }
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 SDL_VideoDevice *_this = SDL_GetVideoDevice ();
229 /* Clean everything out to start */ 221 const SDL_VideoInfo *info = SDL_GetVideoInfo ();
230 if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { 222 int blit_index;
231 SDL_UnRLESurface(surface, 1); 223
232 } 224 /* Clean everything out to start */
233 surface->map->sw_blit = NULL; 225 if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
234 226 SDL_UnRLESurface (surface, 1);
235 /* Figure out if an accelerated hardware blit is possible */ 227 }
236 surface->flags &= ~SDL_HWACCEL; 228 surface->map->sw_blit = NULL;
237 if ( surface->map->identity ) { 229
238 int hw_blit_ok; 230 /* Figure out if an accelerated hardware blit is possible */
239 231 surface->flags &= ~SDL_HWACCEL;
240 if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { 232 if (surface->map->identity) {
241 /* We only support accelerated blitting to hardware */ 233 int hw_blit_ok;
242 if ( surface->map->dst->flags & SDL_HWSURFACE ) { 234
243 hw_blit_ok = current_video->info.blit_hw; 235 if ((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
244 } else { 236 /* We only support accelerated blitting to hardware */
245 hw_blit_ok = 0; 237 if (surface->map->dst->flags & SDL_HWSURFACE) {
246 } 238 hw_blit_ok = info->blit_hw;
247 if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { 239 } else {
248 hw_blit_ok = current_video->info.blit_hw_CC; 240 hw_blit_ok = 0;
249 } 241 }
250 if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { 242 if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
251 hw_blit_ok = current_video->info.blit_hw_A; 243 hw_blit_ok = info->blit_hw_CC;
252 } 244 }
253 } else { 245 if (hw_blit_ok && (surface->flags & SDL_SRCALPHA)) {
254 /* We only support accelerated blitting to hardware */ 246 hw_blit_ok = info->blit_hw_A;
255 if ( surface->map->dst->flags & SDL_HWSURFACE ) { 247 }
256 hw_blit_ok = current_video->info.blit_sw; 248 } else {
257 } else { 249 /* We only support accelerated blitting to hardware */
258 hw_blit_ok = 0; 250 if (surface->map->dst->flags & SDL_HWSURFACE) {
259 } 251 hw_blit_ok = info->blit_sw;
260 if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { 252 } else {
261 hw_blit_ok = current_video->info.blit_sw_CC; 253 hw_blit_ok = 0;
262 } 254 }
263 if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { 255 if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
264 hw_blit_ok = current_video->info.blit_sw_A; 256 hw_blit_ok = info->blit_sw_CC;
265 } 257 }
266 } 258 if (hw_blit_ok && (surface->flags & SDL_SRCALPHA)) {
267 if ( hw_blit_ok ) { 259 hw_blit_ok = info->blit_sw_A;
268 SDL_VideoDevice *video = current_video; 260 }
269 SDL_VideoDevice *this = current_video; 261 }
270 video->CheckHWBlit(this, surface, surface->map->dst); 262 if (hw_blit_ok) {
271 } 263 _this->CheckHWBlit (_this, surface, surface->map->dst);
272 } 264 }
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 /* if an alpha pixel format is specified, we can accelerate alpha blits */
276 { 268 if (((surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE)
277 if ( (surface->flags & SDL_SRCALPHA) ) 269 && (_this->displayformatalphapixel)) {
278 if ( current_video->info.blit_hw_A ) { 270 if ((surface->flags & SDL_SRCALPHA))
279 SDL_VideoDevice *video = current_video; 271 if (info->blit_hw_A) {
280 SDL_VideoDevice *this = current_video; 272 _this->CheckHWBlit (_this, surface, surface->map->dst);
281 video->CheckHWBlit(this, surface, surface->map->dst); 273 }
282 } 274 }
283 } 275
284 276 /* Get the blit function index, based on surface mode */
285 /* Get the blit function index, based on surface mode */ 277 /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
286 /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */ 278 blit_index = 0;
287 blit_index = 0; 279 blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0;
288 blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0; 280 if (surface->flags & SDL_SRCALPHA
289 if ( surface->flags & SDL_SRCALPHA 281 && (surface->format->alpha != SDL_ALPHA_OPAQUE
290 && (surface->format->alpha != SDL_ALPHA_OPAQUE 282 || surface->format->Amask)) {
291 || surface->format->Amask) ) { 283 blit_index |= 2;
292 blit_index |= 2; 284 }
293 } 285
294 286 /* Check for special "identity" case -- copy blit */
295 /* Check for special "identity" case -- copy blit */ 287 if (surface->map->identity && blit_index == 0) {
296 if ( surface->map->identity && blit_index == 0 ) { 288 surface->map->sw_data->blit = SDL_BlitCopy;
297 surface->map->sw_data->blit = SDL_BlitCopy; 289
298 290 /* Handle overlapping blits on the same surface */
299 /* Handle overlapping blits on the same surface */ 291 if (surface == surface->map->dst) {
300 if ( surface == surface->map->dst ) { 292 surface->map->sw_data->blit = SDL_BlitCopyOverlap;
301 surface->map->sw_data->blit = SDL_BlitCopyOverlap; 293 }
302 } 294 } else {
303 } else { 295 if (surface->format->BitsPerPixel < 8) {
304 if ( surface->format->BitsPerPixel < 8 ) { 296 surface->map->sw_data->blit =
305 surface->map->sw_data->blit = 297 SDL_CalculateBlit0 (surface, blit_index);
306 SDL_CalculateBlit0(surface, blit_index); 298 } else {
307 } else { 299 switch (surface->format->BytesPerPixel) {
308 switch ( surface->format->BytesPerPixel ) { 300 case 1:
309 case 1: 301 surface->map->sw_data->blit =
310 surface->map->sw_data->blit = 302 SDL_CalculateBlit1 (surface, blit_index);
311 SDL_CalculateBlit1(surface, blit_index); 303 break;
312 break; 304 case 2:
313 case 2: 305 case 3:
314 case 3: 306 case 4:
315 case 4: 307 surface->map->sw_data->blit =
316 surface->map->sw_data->blit = 308 SDL_CalculateBlitN (surface, blit_index);
317 SDL_CalculateBlitN(surface, blit_index); 309 break;
318 break; 310 default:
319 default: 311 surface->map->sw_data->blit = NULL;
320 surface->map->sw_data->blit = NULL; 312 break;
321 break; 313 }
322 } 314 }
323 } 315 }
324 } 316 /* Make sure we have a blit function */
325 /* Make sure we have a blit function */ 317 if (surface->map->sw_data->blit == NULL) {
326 if ( surface->map->sw_data->blit == NULL ) { 318 SDL_InvalidateMap (surface->map);
327 SDL_InvalidateMap(surface->map); 319 SDL_SetError ("Blit combination not supported");
328 SDL_SetError("Blit combination not supported"); 320 return (-1);
329 return(-1); 321 }
330 } 322
331 323 /* Choose software blitting function */
332 /* Choose software blitting function */ 324 if (surface->flags & SDL_RLEACCELOK
333 if(surface->flags & SDL_RLEACCELOK 325 && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) {
334 && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) { 326
335 327 if (surface->map->identity
336 if(surface->map->identity 328 && (blit_index == 1
337 && (blit_index == 1 329 || (blit_index == 3 && !surface->format->Amask))) {
338 || (blit_index == 3 && !surface->format->Amask))) { 330 if (SDL_RLESurface (surface) == 0)
339 if ( SDL_RLESurface(surface) == 0 ) 331 surface->map->sw_blit = SDL_RLEBlit;
340 surface->map->sw_blit = SDL_RLEBlit; 332 } else if (blit_index == 2 && surface->format->Amask) {
341 } else if(blit_index == 2 && surface->format->Amask) { 333 if (SDL_RLESurface (surface) == 0)
342 if ( SDL_RLESurface(surface) == 0 ) 334 surface->map->sw_blit = SDL_RLEAlphaBlit;
343 surface->map->sw_blit = SDL_RLEAlphaBlit; 335 }
344 } 336 }
345 } 337
346 338 if (surface->map->sw_blit == NULL) {
347 if ( surface->map->sw_blit == NULL ) { 339 surface->map->sw_blit = SDL_SoftBlit;
348 surface->map->sw_blit = SDL_SoftBlit; 340 }
349 } 341 return (0);
350 return(0); 342 }
351 } 343
352 344 /* vi: set ts=4 sw=4 expandtab: */