Mercurial > sdl-ios-xcode
comparison src/video/SDL_fillrect.c @ 2888:32e8bbba1e94
Added stubs for software implementations of blending fills and line drawing
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 20 Dec 2008 13:14:28 +0000 |
parents | |
children | ffae53de58f4 |
comparison
equal
deleted
inserted
replaced
2887:f8c0c5ef6d54 | 2888:32e8bbba1e94 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2009 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Lesser General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2.1 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 Lesser General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Lesser General Public | |
16 License along with this library; if not, write to the Free Software | |
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 #include "SDL_config.h" | |
23 | |
24 #include "SDL_video.h" | |
25 #include "SDL_blit.h" | |
26 | |
27 | |
28 #ifdef __SSE__ | |
29 /* *INDENT-OFF* */ | |
30 | |
31 #ifdef _MSC_VER | |
32 #define SSE_BEGIN \ | |
33 __m128 c128; \ | |
34 c128.m128_u32[0] = color; \ | |
35 c128.m128_u32[1] = color; \ | |
36 c128.m128_u32[2] = color; \ | |
37 c128.m128_u32[3] = color; | |
38 #else | |
39 #define SSE_BEGIN \ | |
40 DECLARE_ALIGNED(Uint32, cccc[4], 16); \ | |
41 cccc[0] = color; \ | |
42 cccc[1] = color; \ | |
43 cccc[2] = color; \ | |
44 cccc[3] = color; \ | |
45 __m128 c128 = *(__m128 *)cccc; | |
46 #endif | |
47 | |
48 #define SSE_WORK \ | |
49 for (i = n / 64; i--;) { \ | |
50 _mm_stream_ps((float *)(p+0), c128); \ | |
51 _mm_stream_ps((float *)(p+16), c128); \ | |
52 _mm_stream_ps((float *)(p+32), c128); \ | |
53 _mm_stream_ps((float *)(p+48), c128); \ | |
54 p += 64; \ | |
55 } | |
56 | |
57 #define SSE_END | |
58 | |
59 #define DEFINE_SSE_FILLRECT(bpp, type) \ | |
60 static void \ | |
61 SDL_FillRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \ | |
62 { \ | |
63 SSE_BEGIN; \ | |
64 \ | |
65 while (h--) { \ | |
66 int i, n = w * bpp; \ | |
67 Uint8 *p = pixels; \ | |
68 \ | |
69 if (n > 15) { \ | |
70 int adjust = 16 - ((uintptr_t)p & 15); \ | |
71 if (adjust < 16) { \ | |
72 n -= adjust; \ | |
73 adjust /= bpp; \ | |
74 while (adjust--) { \ | |
75 *((type *)p) = (type)color; \ | |
76 p += bpp; \ | |
77 } \ | |
78 } \ | |
79 SSE_WORK; \ | |
80 } \ | |
81 if (n & 63) { \ | |
82 int remainder = (n & 63); \ | |
83 remainder /= bpp; \ | |
84 while (remainder--) { \ | |
85 *((type *)p) = (type)color; \ | |
86 p += bpp; \ | |
87 } \ | |
88 } \ | |
89 pixels += pitch; \ | |
90 } \ | |
91 \ | |
92 SSE_END; \ | |
93 } | |
94 | |
95 DEFINE_SSE_FILLRECT(1, Uint8) | |
96 DEFINE_SSE_FILLRECT(2, Uint16) | |
97 DEFINE_SSE_FILLRECT(4, Uint32) | |
98 | |
99 /* *INDENT-ON* */ | |
100 #endif /* __SSE__ */ | |
101 | |
102 #ifdef __MMX__ | |
103 /* *INDENT-OFF* */ | |
104 | |
105 #define MMX_BEGIN \ | |
106 __m64 c64 = _mm_set_pi32(color, color) | |
107 | |
108 #define MMX_WORK \ | |
109 for (i = n / 64; i--;) { \ | |
110 _mm_stream_pi((__m64 *)(p+0), c64); \ | |
111 _mm_stream_pi((__m64 *)(p+8), c64); \ | |
112 _mm_stream_pi((__m64 *)(p+16), c64); \ | |
113 _mm_stream_pi((__m64 *)(p+24), c64); \ | |
114 _mm_stream_pi((__m64 *)(p+32), c64); \ | |
115 _mm_stream_pi((__m64 *)(p+40), c64); \ | |
116 _mm_stream_pi((__m64 *)(p+48), c64); \ | |
117 _mm_stream_pi((__m64 *)(p+56), c64); \ | |
118 p += 64; \ | |
119 } | |
120 | |
121 #define MMX_END \ | |
122 _mm_empty() | |
123 | |
124 #define DEFINE_MMX_FILLRECT(bpp, type) \ | |
125 static void \ | |
126 SDL_FillRect##bpp##MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \ | |
127 { \ | |
128 MMX_BEGIN; \ | |
129 \ | |
130 while (h--) { \ | |
131 int i, n = w * bpp; \ | |
132 Uint8 *p = pixels; \ | |
133 \ | |
134 if (n > 7) { \ | |
135 int adjust = 8 - ((uintptr_t)p & 7); \ | |
136 if (adjust < 8) { \ | |
137 n -= adjust; \ | |
138 adjust /= bpp; \ | |
139 while (adjust--) { \ | |
140 *((type *)p) = (type)color; \ | |
141 p += bpp; \ | |
142 } \ | |
143 } \ | |
144 MMX_WORK; \ | |
145 } \ | |
146 if (n & 63) { \ | |
147 int remainder = (n & 63); \ | |
148 remainder /= bpp; \ | |
149 while (remainder--) { \ | |
150 *((type *)p) = (type)color; \ | |
151 p += bpp; \ | |
152 } \ | |
153 } \ | |
154 pixels += pitch; \ | |
155 } \ | |
156 \ | |
157 MMX_END; \ | |
158 } | |
159 | |
160 DEFINE_MMX_FILLRECT(1, Uint8) | |
161 DEFINE_MMX_FILLRECT(2, Uint16) | |
162 DEFINE_MMX_FILLRECT(4, Uint32) | |
163 | |
164 /* *INDENT-ON* */ | |
165 #endif /* __MMX__ */ | |
166 | |
167 static void | |
168 SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h) | |
169 { | |
170 while (h--) { | |
171 int n = w; | |
172 Uint8 *p = pixels; | |
173 | |
174 if (n > 3) { | |
175 switch ((uintptr_t) p & 3) { | |
176 case 1: | |
177 *p++ = (Uint8) color; | |
178 --n; | |
179 case 2: | |
180 *p++ = (Uint8) color; | |
181 --n; | |
182 case 3: | |
183 *p++ = (Uint8) color; | |
184 --n; | |
185 } | |
186 SDL_memset4(p, color, (n >> 2)); | |
187 } | |
188 if (n & 3) { | |
189 p += (n & ~3); | |
190 switch (n & 3) { | |
191 case 3: | |
192 *p++ = (Uint8) color; | |
193 case 2: | |
194 *p++ = (Uint8) color; | |
195 case 1: | |
196 *p++ = (Uint8) color; | |
197 } | |
198 } | |
199 pixels += pitch; | |
200 } | |
201 } | |
202 | |
203 static void | |
204 SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h) | |
205 { | |
206 while (h--) { | |
207 int n = w; | |
208 Uint16 *p = (Uint16 *) pixels; | |
209 | |
210 if (n > 1) { | |
211 if ((uintptr_t) p & 2) { | |
212 *p++ = (Uint16) color; | |
213 --n; | |
214 } | |
215 SDL_memset4(p, color, (n >> 1)); | |
216 } | |
217 if (n & 1) { | |
218 p[n - 1] = (Uint16) color; | |
219 } | |
220 pixels += pitch; | |
221 } | |
222 } | |
223 | |
224 static void | |
225 SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h) | |
226 { | |
227 Uint8 r = (Uint8) ((color >> 16) & 0xFF); | |
228 Uint8 g = (Uint8) ((color >> 8) & 0xFF); | |
229 Uint8 b = (Uint8) (color & 0xFF); | |
230 | |
231 while (h--) { | |
232 int n = w; | |
233 Uint8 *p = pixels; | |
234 | |
235 while (n--) { | |
236 *p++ = r; | |
237 *p++ = g; | |
238 *p++ = b; | |
239 } | |
240 pixels += pitch; | |
241 } | |
242 } | |
243 | |
244 static void | |
245 SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h) | |
246 { | |
247 while (h--) { | |
248 SDL_memset4(pixels, color, w); | |
249 pixels += pitch; | |
250 } | |
251 } | |
252 | |
253 /* | |
254 * This function performs a fast fill of the given rectangle with 'color' | |
255 */ | |
256 int | |
257 SDL_FillRect(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color) | |
258 { | |
259 Uint8 *pixels; | |
260 | |
261 /* This function doesn't work on surfaces < 8 bpp */ | |
262 if (dst->format->BitsPerPixel < 8) { | |
263 SDL_SetError("SDL_FillRect(): Unsupported surface format"); | |
264 return (-1); | |
265 } | |
266 | |
267 /* If 'dstrect' == NULL, then fill the whole surface */ | |
268 if (dstrect) { | |
269 /* Perform clipping */ | |
270 if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) { | |
271 return (0); | |
272 } | |
273 } else { | |
274 dstrect = &dst->clip_rect; | |
275 } | |
276 | |
277 /* Perform software fill */ | |
278 if (!dst->pixels) { | |
279 SDL_SetError("SDL_FillRect(): You must lock the surface"); | |
280 return (-1); | |
281 } | |
282 | |
283 pixels = | |
284 (Uint8 *) dst->pixels + dstrect->y * dst->pitch + | |
285 dstrect->x * dst->format->BytesPerPixel; | |
286 | |
287 switch (dst->format->BytesPerPixel) { | |
288 case 1: | |
289 { | |
290 color |= (color << 8); | |
291 color |= (color << 16); | |
292 #ifdef __SSE__ | |
293 if (SDL_HasSSE()) { | |
294 SDL_FillRect1SSE(pixels, dst->pitch, color, dstrect->w, | |
295 dstrect->h); | |
296 break; | |
297 } | |
298 #endif | |
299 #ifdef __MMX__ | |
300 if (SDL_HasMMX()) { | |
301 SDL_FillRect1MMX(pixels, dst->pitch, color, dstrect->w, | |
302 dstrect->h); | |
303 break; | |
304 } | |
305 #endif | |
306 SDL_FillRect1(pixels, dst->pitch, color, dstrect->w, dstrect->h); | |
307 break; | |
308 } | |
309 | |
310 case 2: | |
311 { | |
312 color |= (color << 16); | |
313 #ifdef __SSE__ | |
314 if (SDL_HasSSE()) { | |
315 SDL_FillRect2SSE(pixels, dst->pitch, color, dstrect->w, | |
316 dstrect->h); | |
317 break; | |
318 } | |
319 #endif | |
320 #ifdef __MMX__ | |
321 if (SDL_HasMMX()) { | |
322 SDL_FillRect2MMX(pixels, dst->pitch, color, dstrect->w, | |
323 dstrect->h); | |
324 break; | |
325 } | |
326 #endif | |
327 SDL_FillRect2(pixels, dst->pitch, color, dstrect->w, dstrect->h); | |
328 break; | |
329 } | |
330 | |
331 case 3: | |
332 /* 24-bit RGB is a slow path, at least for now. */ | |
333 { | |
334 SDL_FillRect3(pixels, dst->pitch, color, dstrect->w, dstrect->h); | |
335 break; | |
336 } | |
337 | |
338 case 4: | |
339 { | |
340 #ifdef __SSE__ | |
341 if (SDL_HasSSE()) { | |
342 SDL_FillRect4SSE(pixels, dst->pitch, color, dstrect->w, | |
343 dstrect->h); | |
344 break; | |
345 } | |
346 #endif | |
347 #ifdef __MMX__ | |
348 if (SDL_HasMMX()) { | |
349 SDL_FillRect4MMX(pixels, dst->pitch, color, dstrect->w, | |
350 dstrect->h); | |
351 break; | |
352 } | |
353 #endif | |
354 SDL_FillRect4(pixels, dst->pitch, color, dstrect->w, dstrect->h); | |
355 break; | |
356 } | |
357 } | |
358 | |
359 SDL_UnlockSurface(dst); | |
360 | |
361 /* We're done! */ | |
362 return (0); | |
363 } | |
364 | |
365 /* vi: set ts=4 sw=4 expandtab: */ |