2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 /* This a stretch blit implementation based on ideas given to me by
29 Tomasz Cejner - thanks! :)
31 April 27, 2000 - Sam Lantinga
34 #include "SDL_error.h"
35 #include "SDL_video.h"
38 /* This isn't ready for general consumption yet - it should be folded
39 into the general blitting mechanism.
42 #if (defined(WIN32) && !defined(_M_ALPHA) && !defined(_WIN32_WCE) && \
43 !defined(__WATCOMC__) && !defined(__LCC__) && !defined(__FREEBCC__)) || \
44 (defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT))
45 #define USE_ASM_STRETCH
48 #ifdef USE_ASM_STRETCH
50 #if defined(WIN32) || defined(i386)
52 #define STORE_BYTE 0xAA
53 #define STORE_WORD 0xAB
54 #define LOAD_BYTE 0xAC
55 #define LOAD_WORD 0xAD
58 #error Need assembly opcodes for this architecture
61 #if defined(__ELF__) && defined(__GNUC__)
62 extern unsigned char _copy_row
[4096] __attribute__ ((alias ("copy_row")));
64 static unsigned char copy_row
[4096];
66 static int generate_rowbytes(int src_w
, int dst_w
, int bpp
)
77 unsigned char load
, store
;
79 /* See if we need to regenerate the copy buffer */
80 if ( (src_w
== last
.src_w
) &&
81 (dst_w
== last
.src_w
) && (bpp
== last
.bpp
) ) {
99 SDL_SetError("ASM stretch of %d bytes isn't supported\n", bpp
);
103 inc
= (src_w
<< 16) / dst_w
;
105 for ( i
=0; i
<dst_w
; ++i
) {
106 while ( pos
>= 0x10000L
) {
121 /* Verify that we didn't overflow (too late) */
122 if ( eip
> (copy_row
+sizeof(copy_row
)) ) {
123 SDL_SetError("Copy buffer overflow");
131 #define DEFINE_COPY_ROW(name, type) \
132 void name(type *src, int src_w, type *dst, int dst_w) \
139 inc = (src_w << 16) / dst_w; \
140 for ( i=dst_w; i>0; --i ) { \
141 while ( pos >= 0x10000L ) { \
149 DEFINE_COPY_ROW(copy_row1
, Uint8
)
150 DEFINE_COPY_ROW(copy_row2
, Uint16
)
151 DEFINE_COPY_ROW(copy_row4
, Uint32
)
153 #endif /* USE_ASM_STRETCH */
155 /* The ASM code doesn't handle 24-bpp stretch blits */
156 void copy_row3(Uint8
*src
, int src_w
, Uint8
*dst
, int dst_w
)
163 inc
= (src_w
<< 16) / dst_w
;
164 for ( i
=dst_w
; i
>0; --i
) {
165 while ( pos
>= 0x10000L
) {
178 /* Perform a stretch blit between two surfaces of the same format.
179 NOTE: This function is not safe to call from multiple threads!
181 int SDL_SoftStretch(SDL_Surface
*src
, SDL_Rect
*srcrect
,
182 SDL_Surface
*dst
, SDL_Rect
*dstrect
)
187 int src_row
, dst_row
;
192 #if defined(USE_ASM_STRETCH) && defined(__GNUC__)
195 const int bpp
= dst
->format
->BytesPerPixel
;
197 if ( src
->format
->BitsPerPixel
!= dst
->format
->BitsPerPixel
) {
198 SDL_SetError("Only works with same format surfaces");
202 /* Verify the blit rectangles */
204 if ( (srcrect
->x
< 0) || (srcrect
->y
< 0) ||
205 ((srcrect
->x
+srcrect
->w
) > src
->w
) ||
206 ((srcrect
->y
+srcrect
->h
) > src
->h
) ) {
207 SDL_SetError("Invalid source blit rectangle");
218 if ( (dstrect
->x
< 0) || (dstrect
->y
< 0) ||
219 ((dstrect
->x
+dstrect
->w
) > dst
->w
) ||
220 ((dstrect
->y
+dstrect
->h
) > dst
->h
) ) {
221 SDL_SetError("Invalid destination blit rectangle");
232 /* Set up the data... */
234 inc
= (srcrect
->h
<< 16) / dstrect
->h
;
235 src_row
= srcrect
->y
;
236 dst_row
= dstrect
->y
;
237 dst_width
= dstrect
->w
*bpp
;
239 #ifdef USE_ASM_STRETCH
240 /* Write the opcodes for this stretch */
242 (generate_rowbytes(srcrect
->w
, dstrect
->w
, bpp
) < 0) ) {
247 /* Perform the stretch blit */
248 for ( dst_maxrow
= dst_row
+dstrect
->h
; dst_row
<dst_maxrow
; ++dst_row
) {
249 dstp
= (Uint8
*)dst
->pixels
+ (dst_row
*dst
->pitch
)
251 while ( pos
>= 0x10000L
) {
252 srcp
= (Uint8
*)src
->pixels
+ (src_row
*src
->pitch
)
257 #ifdef USE_ASM_STRETCH
260 copy_row3(srcp
, srcrect
->w
, dstp
, dstrect
->w
);
264 __asm__
__volatile__ (""
267 : "=&D" (u1
), "=&S" (u2
)
268 : "0" (dstp
), "1" (srcp
)
272 { void *code
= ©_row
;
286 #error Need inline assembly for this compiler
288 #endif /* __GNUC__ */
294 copy_row1(srcp
, srcrect
->w
, dstp
, dstrect
->w
);
297 copy_row2((Uint16
*)srcp
, srcrect
->w
,
298 (Uint16
*)dstp
, dstrect
->w
);
301 copy_row3(srcp
, srcrect
->w
, dstp
, dstrect
->w
);
304 copy_row4((Uint32
*)srcp
, srcrect
->w
,
305 (Uint32
*)dstp
, dstrect
->w
);