Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 1 | /* |
2 | SDL - Simple DirectMedia Layer |
||
3 | Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga |
||
4 | |||
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. |
||
9 | |||
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. |
||
14 | |||
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 |
||
18 | |||
19 | Sam Lantinga |
||
20 | slouken@devolution.com |
||
21 | */ |
||
22 | |||
23 | #include |
||
24 | #include |
||
25 | #include |
||
26 | |||
27 | #include "SDL_error.h" |
||
28 | #include "SDL_video.h" |
||
29 | #include "SDL_sysvideo.h" |
||
30 | #include "SDL_blit.h" |
||
31 | #include "SDL_RLEaccel_c.h" |
||
32 | #include "SDL_pixels_c.h" |
||
33 | #include "SDL_memops.h" |
||
34 | |||
35 | /* The general purpose software blit routine */ |
||
36 | static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect, |
||
37 | SDL_Surface *dst, SDL_Rect *dstrect) |
||
38 | { |
||
39 | int okay; |
||
40 | int src_locked; |
||
41 | int dst_locked; |
||
42 | |||
43 | /* Everything is okay at the beginning... */ |
||
44 | okay = 1; |
||
45 | |||
46 | /* Lock the destination if it's in hardware */ |
||
47 | dst_locked = 0; |
||
48 | if ( dst->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { |
||
49 | SDL_VideoDevice *video = current_video; |
||
50 | SDL_VideoDevice *this = current_video; |
||
51 | if ( video->LockHWSurface(this, dst) < 0 ) { |
||
52 | okay = 0; |
||
53 | } else { |
||
54 | dst_locked = 1; |
||
55 | } |
||
56 | } |
||
57 | /* Lock the source if it's in hardware */ |
||
58 | src_locked = 0; |
||
59 | if ( src->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) { |
||
60 | SDL_VideoDevice *video = current_video; |
||
61 | SDL_VideoDevice *this = current_video; |
||
62 | if ( video->LockHWSurface(this, src) < 0 ) { |
||
63 | okay = 0; |
||
64 | } else { |
||
65 | src_locked = 1; |
||
66 | } |
||
67 | } |
||
68 | |||
69 | /* Unencode the destination if it's RLE encoded */ |
||
70 | if ( dst->flags & SDL_RLEACCEL ) { |
||
71 | SDL_UnRLESurface(dst, 1); |
||
72 | dst->flags |= SDL_RLEACCEL; /* save accel'd state */ |
||
73 | } |
||
74 | |||
75 | /* Set up source and destination buffer pointers, and BLIT! */ |
||
76 | if ( okay && srcrect->w && srcrect->h ) { |
||
77 | SDL_BlitInfo info; |
||
78 | SDL_loblit RunBlit; |
||
79 | |||
80 | /* Set up the blit information */ |
||
81 | info.s_pixels = (Uint8 *)src->pixels + src->offset + |
||
82 | (Uint16)srcrect->y*src->pitch + |
||
83 | (Uint16)srcrect->x*src->format->BytesPerPixel; |
||
84 | info.s_width = srcrect->w; |
||
85 | info.s_height = srcrect->h; |
||
86 | info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel; |
||
87 | info.d_pixels = (Uint8 *)dst->pixels + dst->offset + |
||
88 | (Uint16)dstrect->y*dst->pitch + |
||
89 | (Uint16)dstrect->x*dst->format->BytesPerPixel; |
||
90 | info.d_width = dstrect->w; |
||
91 | info.d_height = dstrect->h; |
||
92 | info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel; |
||
93 | info.aux_data = src->map->sw_data->aux_data; |
||
94 | info.src = src->format; |
||
95 | info.table = src->map->table; |
||
96 | info.dst = dst->format; |
||
97 | RunBlit = src->map->sw_data->blit; |
||
98 | |||
99 | /* Run the actual software blit */ |
||
100 | RunBlit(&info); |
||
101 | } |
||
102 | |||
103 | /* Re-encode the destination if it's RLE encoded */ |
||
104 | if ( dst->flags & SDL_RLEACCEL ) { |
||
105 | dst->flags &= ~SDL_RLEACCEL; /* stop lying */ |
||
106 | SDL_RLESurface(dst); |
||
107 | } |
||
108 | |||
109 | /* We need to unlock the surfaces if they're locked */ |
||
110 | if ( dst_locked ) { |
||
111 | SDL_VideoDevice *video = current_video; |
||
112 | SDL_VideoDevice *this = current_video; |
||
113 | video->UnlockHWSurface(this, dst); |
||
114 | } else |
||
115 | if ( src_locked ) { |
||
116 | SDL_VideoDevice *video = current_video; |
||
117 | SDL_VideoDevice *this = current_video; |
||
118 | video->UnlockHWSurface(this, src); |
||
119 | } |
||
120 | /* Blit is done! */ |
||
121 | return(okay ? 0 : -1); |
||
122 | } |
||
123 | |||
124 | static void SDL_BlitCopy(SDL_BlitInfo *info) |
||
125 | { |
||
126 | Uint8 *src, *dst; |
||
127 | int w, h; |
||
128 | int srcskip, dstskip; |
||
129 | |||
130 | w = info->d_width*info->dst->BytesPerPixel; |
||
131 | h = info->d_height; |
||
132 | src = info->s_pixels; |
||
133 | dst = info->d_pixels; |
||
134 | srcskip = w+info->s_skip; |
||
135 | dstskip = w+info->d_skip; |
||
136 | while ( h-- ) { |
||
137 | SDL_memcpy(dst, src, w); |
||
138 | src += srcskip; |
||
139 | dst += dstskip; |
||
140 | } |
||
141 | } |
||
142 | |||
143 | static void SDL_BlitCopyOverlap(SDL_BlitInfo *info) |
||
144 | { |
||
145 | Uint8 *src, *dst; |
||
146 | int w, h; |
||
147 | int srcskip, dstskip; |
||
148 | |||
149 | w = info->d_width*info->dst->BytesPerPixel; |
||
150 | h = info->d_height; |
||
151 | src = info->s_pixels; |
||
152 | dst = info->d_pixels; |
||
153 | srcskip = w+info->s_skip; |
||
154 | dstskip = w+info->d_skip; |
||
155 | if ( dst < src ) { |
||
156 | while ( h-- ) { |
||
157 | SDL_memcpy(dst, src, w); |
||
158 | src += srcskip; |
||
159 | dst += dstskip; |
||
160 | } |
||
161 | } else { |
||
162 | src += ((h-1) * srcskip); |
||
163 | dst += ((h-1) * dstskip); |
||
164 | while ( h-- ) { |
||
165 | SDL_revcpy(dst, src, w); |
||
166 | src -= srcskip; |
||
167 | dst -= dstskip; |
||
168 | } |
||
169 | } |
||
170 | } |
||
171 | |||
172 | /* Figure out which of many blit routines to set up on a surface */ |
||
173 | int SDL_CalculateBlit(SDL_Surface *surface) |
||
174 | { |
||
175 | int blit_index; |
||
176 | |||
177 | /* Clean everything out to start */ |
||
178 | if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) { |
||
179 | SDL_UnRLESurface(surface, 1); |
||
180 | } |
||
181 | surface->map->sw_blit = NULL; |
||
182 | |||
183 | /* Figure out if an accelerated hardware blit is possible */ |
||
184 | surface->flags &= ~SDL_HWACCEL; |
||
185 | if ( surface->map->identity ) { |
||
186 | int hw_blit_ok; |
||
187 | |||
188 | if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { |
||
189 | /* We only support accelerated blitting to hardware */ |
||
190 | if ( surface->map->dst->flags & SDL_HWSURFACE ) { |
||
191 | hw_blit_ok = current_video->info.blit_hw; |
||
192 | } else { |
||
193 | hw_blit_ok = 0; |
||
194 | } |
||
195 | if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { |
||
196 | hw_blit_ok = current_video->info.blit_hw_CC; |
||
197 | } |
||
198 | if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { |
||
199 | hw_blit_ok = current_video->info.blit_hw_A; |
||
200 | } |
||
201 | } else { |
||
202 | /* We only support accelerated blitting to hardware */ |
||
203 | if ( surface->map->dst->flags & SDL_HWSURFACE ) { |
||
204 | hw_blit_ok = current_video->info.blit_sw; |
||
205 | } else { |
||
206 | hw_blit_ok = 0; |
||
207 | } |
||
208 | if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) { |
||
209 | hw_blit_ok = current_video->info.blit_sw_CC; |
||
210 | } |
||
211 | if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) { |
||
212 | hw_blit_ok = current_video->info.blit_sw_A; |
||
213 | } |
||
214 | } |
||
215 | if ( hw_blit_ok ) { |
||
216 | SDL_VideoDevice *video = current_video; |
||
217 | SDL_VideoDevice *this = current_video; |
||
218 | video->CheckHWBlit(this, surface, surface->map->dst); |
||
219 | } |
||
220 | } |
||
221 | |||
222 | /* Get the blit function index, based on surface mode */ |
||
223 | /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */ |
||
224 | blit_index = 0; |
||
225 | blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY)) << 0; |
||
226 | if ( surface->flags & SDL_SRCALPHA |
||
227 | && (surface->format->alpha != SDL_ALPHA_OPAQUE |
||
228 | || surface->format->Amask) ) { |
||
229 | blit_index |= 2; |
||
230 | } |
||
231 | |||
232 | /* Check for special "identity" case -- copy blit */ |
||
233 | if ( surface->map->identity && blit_index == 0 ) { |
||
234 | surface->map->sw_data->blit = SDL_BlitCopy; |
||
235 | |||
236 | /* Handle overlapping blits on the same surface */ |
||
237 | if ( surface == surface->map->dst ) { |
||
238 | surface->map->sw_data->blit = SDL_BlitCopyOverlap; |
||
239 | } |
||
240 | } else { |
||
241 | if ( surface->format->BitsPerPixel < 8 ) { |
||
242 | surface->map->sw_data->blit = |
||
243 | SDL_CalculateBlit0(surface, blit_index); |
||
244 | } else { |
||
245 | switch ( surface->format->BytesPerPixel ) { |
||
246 | case 1: |
||
247 | surface->map->sw_data->blit = |
||
248 | SDL_CalculateBlit1(surface, blit_index); |
||
249 | break; |
||
250 | case 2: |
||
251 | case 3: |
||
252 | case 4: |
||
253 | surface->map->sw_data->blit = |
||
254 | SDL_CalculateBlitN(surface, blit_index); |
||
255 | break; |
||
256 | default: |
||
257 | surface->map->sw_data->blit = NULL; |
||
258 | break; |
||
259 | } |
||
260 | } |
||
261 | } |
||
262 | /* Make sure we have a blit function */ |
||
263 | if ( surface->map->sw_data->blit == NULL ) { |
||
264 | SDL_InvalidateMap(surface->map); |
||
265 | SDL_SetError("Blit combination not supported"); |
||
266 | return(-1); |
||
267 | } |
||
268 | |||
269 | /* Choose software blitting function */ |
||
270 | if(surface->flags & SDL_RLEACCELOK |
||
271 | && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) { |
||
272 | |||
273 | if(surface->map->identity |
||
274 | && (blit_index == 1 |
||
275 | || (blit_index == 3 && !surface->format->Amask))) { |
||
276 | if ( SDL_RLESurface(surface) == 0 ) |
||
277 | surface->map->sw_blit = SDL_RLEBlit; |
||
278 | } else if(blit_index == 2 && surface->format->Amask) { |
||
279 | if ( SDL_RLESurface(surface) == 0 ) |
||
280 | surface->map->sw_blit = SDL_RLEAlphaBlit; |
||
281 | } |
||
282 | } |
||
283 | |||
284 | if ( surface->map->sw_blit == NULL ) { |
||
285 | surface->map->sw_blit = SDL_SoftBlit; |
||
286 | } |
||
287 | return(0); |
||
288 | }>><>>>> |
||
289 |