comparison src/video/SDL_stretch.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 b5a4ac87b98c
children 8055185ae4ed
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
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) \
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] = { 0, 0, 0 }; 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: */