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
32 #include "SDL_error.h"
33 #include "SDL_video.h"
34 #include "SDL_sysvideo.h"
36 #include "SDL_RLEaccel_c.h"
37 #include "SDL_pixels_c.h"
38 #include "SDL_memops.h"
40 /* The general purpose software blit routine */
41 static int SDL_SoftBlit(SDL_Surface
*src
, SDL_Rect
*srcrect
,
42 SDL_Surface
*dst
, SDL_Rect
*dstrect
)
48 /* Everything is okay at the beginning... */
51 /* Lock the destination if it's in hardware */
53 if ( SDL_MUSTLOCK(dst
) ) {
54 if ( SDL_LockSurface(dst
) < 0 ) {
60 /* Lock the source if it's in hardware */
62 if ( SDL_MUSTLOCK(src
) ) {
63 if ( SDL_LockSurface(src
) < 0 ) {
70 /* Set up source and destination buffer pointers, and BLIT! */
71 if ( okay
&& srcrect
->w
&& srcrect
->h
) {
75 /* Set up the blit information */
76 info
.s_pixels
= (Uint8
*)src
->pixels
+
77 (Uint16
)srcrect
->y
*src
->pitch
+
78 (Uint16
)srcrect
->x
*src
->format
->BytesPerPixel
;
79 info
.s_width
= srcrect
->w
;
80 info
.s_height
= srcrect
->h
;
81 info
.s_skip
=src
->pitch
-info
.s_width
*src
->format
->BytesPerPixel
;
82 info
.d_pixels
= (Uint8
*)dst
->pixels
+
83 (Uint16
)dstrect
->y
*dst
->pitch
+
84 (Uint16
)dstrect
->x
*dst
->format
->BytesPerPixel
;
85 info
.d_width
= dstrect
->w
;
86 info
.d_height
= dstrect
->h
;
87 info
.d_skip
=dst
->pitch
-info
.d_width
*dst
->format
->BytesPerPixel
;
88 info
.aux_data
= src
->map
->sw_data
->aux_data
;
89 info
.src
= src
->format
;
90 info
.table
= src
->map
->table
;
91 info
.dst
= dst
->format
;
92 RunBlit
= src
->map
->sw_data
->blit
;
94 /* Run the actual software blit */
98 /* We need to unlock the surfaces if they're locked */
100 SDL_UnlockSurface(dst
);
103 SDL_UnlockSurface(src
);
106 return(okay
? 0 : -1);
109 static void SDL_BlitCopy(SDL_BlitInfo
*info
)
113 int srcskip
, dstskip
;
115 w
= info
->d_width
*info
->dst
->BytesPerPixel
;
117 src
= info
->s_pixels
;
118 dst
= info
->d_pixels
;
119 srcskip
= w
+info
->s_skip
;
120 dstskip
= w
+info
->d_skip
;
122 SDL_memcpy(dst
, src
, w
);
128 static void SDL_BlitCopyOverlap(SDL_BlitInfo
*info
)
132 int srcskip
, dstskip
;
134 w
= info
->d_width
*info
->dst
->BytesPerPixel
;
136 src
= info
->s_pixels
;
137 dst
= info
->d_pixels
;
138 srcskip
= w
+info
->s_skip
;
139 dstskip
= w
+info
->d_skip
;
142 SDL_memcpy(dst
, src
, w
);
147 src
+= ((h
-1) * srcskip
);
148 dst
+= ((h
-1) * dstskip
);
150 SDL_revcpy(dst
, src
, w
);
157 /* Figure out which of many blit routines to set up on a surface */
158 int SDL_CalculateBlit(SDL_Surface
*surface
)
162 /* Clean everything out to start */
163 if ( (surface
->flags
& SDL_RLEACCEL
) == SDL_RLEACCEL
) {
164 SDL_UnRLESurface(surface
, 1);
166 surface
->map
->sw_blit
= NULL
;
168 /* Figure out if an accelerated hardware blit is possible */
169 surface
->flags
&= ~SDL_HWACCEL
;
170 if ( surface
->map
->identity
) {
173 if ( (surface
->flags
& SDL_HWSURFACE
) == SDL_HWSURFACE
) {
174 /* We only support accelerated blitting to hardware */
175 if ( surface
->map
->dst
->flags
& SDL_HWSURFACE
) {
176 hw_blit_ok
= current_video
->info
.blit_hw
;
180 if (hw_blit_ok
&& (surface
->flags
& SDL_SRCCOLORKEY
)) {
181 hw_blit_ok
= current_video
->info
.blit_hw_CC
;
183 if ( hw_blit_ok
&& (surface
->flags
& SDL_SRCALPHA
) ) {
184 hw_blit_ok
= current_video
->info
.blit_hw_A
;
187 /* We only support accelerated blitting to hardware */
188 if ( surface
->map
->dst
->flags
& SDL_HWSURFACE
) {
189 hw_blit_ok
= current_video
->info
.blit_sw
;
193 if (hw_blit_ok
&& (surface
->flags
& SDL_SRCCOLORKEY
)) {
194 hw_blit_ok
= current_video
->info
.blit_sw_CC
;
196 if ( hw_blit_ok
&& (surface
->flags
& SDL_SRCALPHA
) ) {
197 hw_blit_ok
= current_video
->info
.blit_sw_A
;
201 SDL_VideoDevice
*video
= current_video
;
202 SDL_VideoDevice
*this = current_video
;
203 video
->CheckHWBlit(this, surface
, surface
->map
->dst
);
207 /* Get the blit function index, based on surface mode */
208 /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
210 blit_index
|= (!!(surface
->flags
& SDL_SRCCOLORKEY
)) << 0;
211 if ( surface
->flags
& SDL_SRCALPHA
212 && (surface
->format
->alpha
!= SDL_ALPHA_OPAQUE
213 || surface
->format
->Amask
) ) {
217 /* Check for special "identity" case -- copy blit */
218 if ( surface
->map
->identity
&& blit_index
== 0 ) {
219 surface
->map
->sw_data
->blit
= SDL_BlitCopy
;
221 /* Handle overlapping blits on the same surface */
222 if ( surface
== surface
->map
->dst
) {
223 surface
->map
->sw_data
->blit
= SDL_BlitCopyOverlap
;
226 if ( surface
->format
->BitsPerPixel
< 8 ) {
227 surface
->map
->sw_data
->blit
=
228 SDL_CalculateBlit0(surface
, blit_index
);
230 switch ( surface
->format
->BytesPerPixel
) {
232 surface
->map
->sw_data
->blit
=
233 SDL_CalculateBlit1(surface
, blit_index
);
238 surface
->map
->sw_data
->blit
=
239 SDL_CalculateBlitN(surface
, blit_index
);
242 surface
->map
->sw_data
->blit
= NULL
;
247 /* Make sure we have a blit function */
248 if ( surface
->map
->sw_data
->blit
== NULL
) {
249 SDL_InvalidateMap(surface
->map
);
250 SDL_SetError("Blit combination not supported");
254 /* Choose software blitting function */
255 if(surface
->flags
& SDL_RLEACCELOK
256 && (surface
->flags
& SDL_HWACCEL
) != SDL_HWACCEL
) {
258 if(surface
->map
->identity
260 || (blit_index
== 3 && !surface
->format
->Amask
))) {
261 if ( SDL_RLESurface(surface
) == 0 )
262 surface
->map
->sw_blit
= SDL_RLEBlit
;
263 } else if(blit_index
== 2 && surface
->format
->Amask
) {
264 if ( SDL_RLESurface(surface
) == 0 )
265 surface
->map
->sw_blit
= SDL_RLEAlphaBlit
;
269 if ( surface
->map
->sw_blit
== NULL
) {
270 surface
->map
->sw_blit
= SDL_SoftBlit
;