Mercurial > sdl-ios-xcode
comparison src/video/SDL_stretch.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 | e3242177fe4a |
children | 4da1ee79c9af |
comparison
equal
deleted
inserted
replaced
1661:281d3f4870e5 | 1662:782fd950bd46 |
---|---|
53 #error Need assembly opcodes for this architecture | 53 #error Need assembly opcodes for this architecture |
54 #endif | 54 #endif |
55 | 55 |
56 static unsigned char copy_row[4096]; | 56 static unsigned char copy_row[4096]; |
57 | 57 |
58 static int generate_rowbytes(int src_w, int dst_w, int bpp) | 58 static int |
59 generate_rowbytes (int src_w, int dst_w, int bpp) | |
59 { | 60 { |
60 static struct { | 61 static struct |
61 int bpp; | 62 { |
62 int src_w; | 63 int bpp; |
63 int dst_w; | 64 int src_w; |
64 } last; | 65 int dst_w; |
65 | 66 } last; |
66 int i; | 67 |
67 int pos, inc; | 68 int i; |
68 unsigned char *eip; | 69 int pos, inc; |
69 unsigned char load, store; | 70 unsigned char *eip; |
70 | 71 unsigned char load, store; |
71 /* See if we need to regenerate the copy buffer */ | 72 |
72 if ( (src_w == last.src_w) && | 73 /* See if we need to regenerate the copy buffer */ |
73 (dst_w == last.dst_w) && (bpp == last.bpp) ) { | 74 if ((src_w == last.src_w) && (dst_w == last.dst_w) && (bpp == last.bpp)) { |
74 return(0); | 75 return (0); |
75 } | 76 } |
76 last.bpp = bpp; | 77 last.bpp = bpp; |
77 last.src_w = src_w; | 78 last.src_w = src_w; |
78 last.dst_w = dst_w; | 79 last.dst_w = dst_w; |
79 | 80 |
80 switch (bpp) { | 81 switch (bpp) { |
81 case 1: | 82 case 1: |
82 load = LOAD_BYTE; | 83 load = LOAD_BYTE; |
83 store = STORE_BYTE; | 84 store = STORE_BYTE; |
84 break; | 85 break; |
85 case 2: | 86 case 2: |
86 case 4: | 87 case 4: |
87 load = LOAD_WORD; | 88 load = LOAD_WORD; |
88 store = STORE_WORD; | 89 store = STORE_WORD; |
89 break; | 90 break; |
90 default: | 91 default: |
91 SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp); | 92 SDL_SetError ("ASM stretch of %d bytes isn't supported\n", bpp); |
92 return(-1); | 93 return (-1); |
93 } | 94 } |
94 pos = 0x10000; | 95 pos = 0x10000; |
95 inc = (src_w << 16) / dst_w; | 96 inc = (src_w << 16) / dst_w; |
96 eip = copy_row; | 97 eip = copy_row; |
97 for ( i=0; i<dst_w; ++i ) { | 98 for (i = 0; i < dst_w; ++i) { |
98 while ( pos >= 0x10000L ) { | 99 while (pos >= 0x10000L) { |
99 if ( bpp == 2 ) { | 100 if (bpp == 2) { |
100 *eip++ = PREFIX16; | 101 *eip++ = PREFIX16; |
101 } | 102 } |
102 *eip++ = load; | 103 *eip++ = load; |
103 pos -= 0x10000L; | 104 pos -= 0x10000L; |
104 } | 105 } |
105 if ( bpp == 2 ) { | 106 if (bpp == 2) { |
106 *eip++ = PREFIX16; | 107 *eip++ = PREFIX16; |
107 } | 108 } |
108 *eip++ = store; | 109 *eip++ = store; |
109 pos += inc; | 110 pos += inc; |
110 } | 111 } |
111 *eip++ = RETURN; | 112 *eip++ = RETURN; |
112 | 113 |
113 /* Verify that we didn't overflow (too late) */ | 114 /* Verify that we didn't overflow (too late) */ |
114 if ( eip > (copy_row+sizeof(copy_row)) ) { | 115 if (eip > (copy_row + sizeof (copy_row))) { |
115 SDL_SetError("Copy buffer overflow"); | 116 SDL_SetError ("Copy buffer overflow"); |
116 return(-1); | 117 return (-1); |
117 } | 118 } |
118 return(0); | 119 return (0); |
119 } | 120 } |
120 | 121 |
121 #else | 122 #else |
122 | 123 |
123 #define DEFINE_COPY_ROW(name, type) \ | 124 #define DEFINE_COPY_ROW(name, type) \ |
136 } \ | 137 } \ |
137 *dst++ = pixel; \ | 138 *dst++ = pixel; \ |
138 pos += inc; \ | 139 pos += inc; \ |
139 } \ | 140 } \ |
140 } | 141 } |
141 DEFINE_COPY_ROW(copy_row1, Uint8) | 142 DEFINE_COPY_ROW (copy_row1, Uint8) |
142 DEFINE_COPY_ROW(copy_row2, Uint16) | 143 DEFINE_COPY_ROW (copy_row2, Uint16) DEFINE_COPY_ROW (copy_row4, Uint32) |
143 DEFINE_COPY_ROW(copy_row4, Uint32) | |
144 | |
145 #endif /* USE_ASM_STRETCH */ | 144 #endif /* USE_ASM_STRETCH */ |
146 | |
147 /* The ASM code doesn't handle 24-bpp stretch blits */ | 145 /* The ASM code doesn't handle 24-bpp stretch blits */ |
148 void copy_row3(Uint8 *src, int src_w, Uint8 *dst, int dst_w) | 146 void |
147 copy_row3 (Uint8 * src, int src_w, Uint8 * dst, int dst_w) | |
149 { | 148 { |
150 int i; | 149 int i; |
151 int pos, inc; | 150 int pos, inc; |
152 Uint8 pixel[3]; | 151 Uint8 pixel[3]; |
153 | 152 |
154 pos = 0x10000; | 153 pos = 0x10000; |
155 inc = (src_w << 16) / dst_w; | 154 inc = (src_w << 16) / dst_w; |
156 for ( i=dst_w; i>0; --i ) { | 155 for (i = dst_w; i > 0; --i) { |
157 while ( pos >= 0x10000L ) { | 156 while (pos >= 0x10000L) { |
158 pixel[0] = *src++; | 157 pixel[0] = *src++; |
159 pixel[1] = *src++; | 158 pixel[1] = *src++; |
160 pixel[2] = *src++; | 159 pixel[2] = *src++; |
161 pos -= 0x10000L; | 160 pos -= 0x10000L; |
162 } | 161 } |
163 *dst++ = pixel[0]; | 162 *dst++ = pixel[0]; |
164 *dst++ = pixel[1]; | 163 *dst++ = pixel[1]; |
165 *dst++ = pixel[2]; | 164 *dst++ = pixel[2]; |
166 pos += inc; | 165 pos += inc; |
167 } | 166 } |
168 } | 167 } |
169 | 168 |
170 /* Perform a stretch blit between two surfaces of the same format. | 169 /* Perform a stretch blit between two surfaces of the same format. |
171 NOTE: This function is not safe to call from multiple threads! | 170 NOTE: This function is not safe to call from multiple threads! |
172 */ | 171 */ |
173 int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect, | 172 int |
174 SDL_Surface *dst, SDL_Rect *dstrect) | 173 SDL_SoftStretch (SDL_Surface * src, SDL_Rect * srcrect, |
174 SDL_Surface * dst, SDL_Rect * dstrect) | |
175 { | 175 { |
176 int src_locked; | 176 int src_locked; |
177 int dst_locked; | 177 int dst_locked; |
178 int pos, inc; | 178 int pos, inc; |
179 int dst_width; | 179 int dst_width; |
180 int dst_maxrow; | 180 int dst_maxrow; |
181 int src_row, dst_row; | 181 int src_row, dst_row; |
182 Uint8 *srcp = NULL; | 182 Uint8 *srcp = NULL; |
183 Uint8 *dstp; | 183 Uint8 *dstp; |
184 SDL_Rect full_src; | 184 SDL_Rect full_src; |
185 SDL_Rect full_dst; | 185 SDL_Rect full_dst; |
186 #if defined(USE_ASM_STRETCH) && defined(__GNUC__) | 186 #if defined(USE_ASM_STRETCH) && defined(__GNUC__) |
187 int u1, u2; | 187 int u1, u2; |
188 #endif | 188 #endif |
189 const int bpp = dst->format->BytesPerPixel; | 189 const int bpp = dst->format->BytesPerPixel; |
190 | 190 |
191 if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) { | 191 if (src->format->BitsPerPixel != dst->format->BitsPerPixel) { |
192 SDL_SetError("Only works with same format surfaces"); | 192 SDL_SetError ("Only works with same format surfaces"); |
193 return(-1); | 193 return (-1); |
194 } | 194 } |
195 | 195 |
196 /* Verify the blit rectangles */ | 196 /* Verify the blit rectangles */ |
197 if ( srcrect ) { | 197 if (srcrect) { |
198 if ( (srcrect->x < 0) || (srcrect->y < 0) || | 198 if ((srcrect->x < 0) || (srcrect->y < 0) || |
199 ((srcrect->x+srcrect->w) > src->w) || | 199 ((srcrect->x + srcrect->w) > src->w) || |
200 ((srcrect->y+srcrect->h) > src->h) ) { | 200 ((srcrect->y + srcrect->h) > src->h)) { |
201 SDL_SetError("Invalid source blit rectangle"); | 201 SDL_SetError ("Invalid source blit rectangle"); |
202 return(-1); | 202 return (-1); |
203 } | 203 } |
204 } else { | 204 } else { |
205 full_src.x = 0; | 205 full_src.x = 0; |
206 full_src.y = 0; | 206 full_src.y = 0; |
207 full_src.w = src->w; | 207 full_src.w = src->w; |
208 full_src.h = src->h; | 208 full_src.h = src->h; |
209 srcrect = &full_src; | 209 srcrect = &full_src; |
210 } | 210 } |
211 if ( dstrect ) { | 211 if (dstrect) { |
212 if ( (dstrect->x < 0) || (dstrect->y < 0) || | 212 if ((dstrect->x < 0) || (dstrect->y < 0) || |
213 ((dstrect->x+dstrect->w) > dst->w) || | 213 ((dstrect->x + dstrect->w) > dst->w) || |
214 ((dstrect->y+dstrect->h) > dst->h) ) { | 214 ((dstrect->y + dstrect->h) > dst->h)) { |
215 SDL_SetError("Invalid destination blit rectangle"); | 215 SDL_SetError ("Invalid destination blit rectangle"); |
216 return(-1); | 216 return (-1); |
217 } | 217 } |
218 } else { | 218 } else { |
219 full_dst.x = 0; | 219 full_dst.x = 0; |
220 full_dst.y = 0; | 220 full_dst.y = 0; |
221 full_dst.w = dst->w; | 221 full_dst.w = dst->w; |
222 full_dst.h = dst->h; | 222 full_dst.h = dst->h; |
223 dstrect = &full_dst; | 223 dstrect = &full_dst; |
224 } | 224 } |
225 | 225 |
226 /* Lock the destination if it's in hardware */ | 226 /* Lock the destination if it's in hardware */ |
227 dst_locked = 0; | 227 dst_locked = 0; |
228 if ( SDL_MUSTLOCK(dst) ) { | 228 if (SDL_MUSTLOCK (dst)) { |
229 if ( SDL_LockSurface(dst) < 0 ) { | 229 if (SDL_LockSurface (dst) < 0) { |
230 SDL_SetError("Unable to lock destination surface"); | 230 SDL_SetError ("Unable to lock destination surface"); |
231 return(-1); | 231 return (-1); |
232 } | 232 } |
233 dst_locked = 1; | 233 dst_locked = 1; |
234 } | 234 } |
235 /* Lock the source if it's in hardware */ | 235 /* Lock the source if it's in hardware */ |
236 src_locked = 0; | 236 src_locked = 0; |
237 if ( SDL_MUSTLOCK(src) ) { | 237 if (SDL_MUSTLOCK (src)) { |
238 if ( SDL_LockSurface(src) < 0 ) { | 238 if (SDL_LockSurface (src) < 0) { |
239 if ( dst_locked ) { | 239 if (dst_locked) { |
240 SDL_UnlockSurface(dst); | 240 SDL_UnlockSurface (dst); |
241 } | 241 } |
242 SDL_SetError("Unable to lock source surface"); | 242 SDL_SetError ("Unable to lock source surface"); |
243 return(-1); | 243 return (-1); |
244 } | 244 } |
245 src_locked = 1; | 245 src_locked = 1; |
246 } | 246 } |
247 | 247 |
248 /* Set up the data... */ | 248 /* Set up the data... */ |
249 pos = 0x10000; | 249 pos = 0x10000; |
250 inc = (srcrect->h << 16) / dstrect->h; | 250 inc = (srcrect->h << 16) / dstrect->h; |
251 src_row = srcrect->y; | 251 src_row = srcrect->y; |
252 dst_row = dstrect->y; | 252 dst_row = dstrect->y; |
253 dst_width = dstrect->w*bpp; | 253 dst_width = dstrect->w * bpp; |
254 | 254 |
255 #ifdef USE_ASM_STRETCH | 255 #ifdef USE_ASM_STRETCH |
256 /* Write the opcodes for this stretch */ | 256 /* Write the opcodes for this stretch */ |
257 if ( (bpp != 3) && | 257 if ((bpp != 3) && (generate_rowbytes (srcrect->w, dstrect->w, bpp) < 0)) { |
258 (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0) ) { | 258 return (-1); |
259 return(-1); | 259 } |
260 } | 260 #endif |
261 #endif | 261 |
262 | 262 /* Perform the stretch blit */ |
263 /* Perform the stretch blit */ | 263 for (dst_maxrow = dst_row + dstrect->h; dst_row < dst_maxrow; ++dst_row) { |
264 for ( dst_maxrow = dst_row+dstrect->h; dst_row<dst_maxrow; ++dst_row ) { | 264 dstp = (Uint8 *) dst->pixels + (dst_row * dst->pitch) |
265 dstp = (Uint8 *)dst->pixels + (dst_row*dst->pitch) | 265 + (dstrect->x * bpp); |
266 + (dstrect->x*bpp); | 266 while (pos >= 0x10000L) { |
267 while ( pos >= 0x10000L ) { | 267 srcp = (Uint8 *) src->pixels + (src_row * src->pitch) |
268 srcp = (Uint8 *)src->pixels + (src_row*src->pitch) | 268 + (srcrect->x * bpp); |
269 + (srcrect->x*bpp); | 269 ++src_row; |
270 ++src_row; | 270 pos -= 0x10000L; |
271 pos -= 0x10000L; | 271 } |
272 } | |
273 #ifdef USE_ASM_STRETCH | 272 #ifdef USE_ASM_STRETCH |
274 switch (bpp) { | 273 switch (bpp) { |
275 case 3: | 274 case 3: |
276 copy_row3(srcp, srcrect->w, dstp, dstrect->w); | 275 copy_row3 (srcp, srcrect->w, dstp, dstrect->w); |
277 break; | 276 break; |
278 default: | 277 default: |
279 #ifdef __GNUC__ | 278 #ifdef __GNUC__ |
280 __asm__ __volatile__ ( | 279 __asm__ __volatile__ ("call *%4": "=&D" (u1), "=&S" (u2): "0" (dstp), "1" (srcp), "r" (copy_row):"memory"); |
281 "call *%4" | |
282 : "=&D" (u1), "=&S" (u2) | |
283 : "0" (dstp), "1" (srcp), "r" (copy_row) | |
284 : "memory" ); | |
285 #elif defined(_MSC_VER) || defined(__WATCOMC__) | 280 #elif defined(_MSC_VER) || defined(__WATCOMC__) |
286 { void *code = copy_row; | 281 { |
287 __asm { | 282 void *code = copy_row; |
288 push edi | 283 __asm { |
289 push esi | 284 push edi |
290 | 285 push esi |
291 mov edi, dstp | 286 mov edi, dstp |
292 mov esi, srcp | 287 mov esi, srcp call dword ptr code pop esi pop edi} |
293 call dword ptr code | 288 } |
294 | |
295 pop esi | |
296 pop edi | |
297 } | |
298 } | |
299 #else | 289 #else |
300 #error Need inline assembly for this compiler | 290 #error Need inline assembly for this compiler |
301 #endif | 291 #endif |
302 break; | 292 break; |
303 } | 293 } |
304 #else | 294 #else |
305 switch (bpp) { | 295 switch (bpp) { |
306 case 1: | 296 case 1: |
307 copy_row1(srcp, srcrect->w, dstp, dstrect->w); | 297 copy_row1 (srcp, srcrect->w, dstp, dstrect->w); |
308 break; | 298 break; |
309 case 2: | 299 case 2: |
310 copy_row2((Uint16 *)srcp, srcrect->w, | 300 copy_row2 ((Uint16 *) srcp, srcrect->w, |
311 (Uint16 *)dstp, dstrect->w); | 301 (Uint16 *) dstp, dstrect->w); |
312 break; | 302 break; |
313 case 3: | 303 case 3: |
314 copy_row3(srcp, srcrect->w, dstp, dstrect->w); | 304 copy_row3 (srcp, srcrect->w, dstp, dstrect->w); |
315 break; | 305 break; |
316 case 4: | 306 case 4: |
317 copy_row4((Uint32 *)srcp, srcrect->w, | 307 copy_row4 ((Uint32 *) srcp, srcrect->w, |
318 (Uint32 *)dstp, dstrect->w); | 308 (Uint32 *) dstp, dstrect->w); |
319 break; | 309 break; |
320 } | 310 } |
321 #endif | 311 #endif |
322 pos += inc; | 312 pos += inc; |
323 } | 313 } |
324 | 314 |
325 /* We need to unlock the surfaces if they're locked */ | 315 /* We need to unlock the surfaces if they're locked */ |
326 if ( dst_locked ) { | 316 if (dst_locked) { |
327 SDL_UnlockSurface(dst); | 317 SDL_UnlockSurface (dst); |
328 } | 318 } |
329 if ( src_locked ) { | 319 if (src_locked) { |
330 SDL_UnlockSurface(src); | 320 SDL_UnlockSurface (src); |
331 } | 321 } |
332 return(0); | 322 return (0); |
333 } | 323 } |
334 | 324 |
325 /* vi: set ts=4 sw=4 expandtab: */ |