Mercurial > sdl-ios-xcode
comparison src/video/SDL_drawrect.c @ 3593:b931bcfd94a0
In the process of adding rectangle drawing
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 18 Dec 2009 07:03:09 +0000 |
parents | |
children | c8bed77b0386 |
comparison
equal
deleted
inserted
replaced
3592:25dc4a86132c | 3593:b931bcfd94a0 |
---|---|
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_DrawRect##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 > 63) { \ | |
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 static void | |
96 SDL_DrawRect1SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) | |
97 { | |
98 SSE_BEGIN; | |
99 | |
100 while (h--) { | |
101 int i, n = w; | |
102 Uint8 *p = pixels; | |
103 | |
104 if (n > 63) { | |
105 int adjust = 16 - ((uintptr_t)p & 15); | |
106 if (adjust) { | |
107 n -= adjust; | |
108 SDL_memset(p, color, adjust); | |
109 p += adjust; | |
110 } | |
111 SSE_WORK; | |
112 } | |
113 if (n & 63) { | |
114 int remainder = (n & 63); | |
115 SDL_memset(p, color, remainder); | |
116 p += remainder; | |
117 } | |
118 pixels += pitch; | |
119 } | |
120 | |
121 SSE_END; | |
122 } | |
123 /*DEFINE_SSE_FILLRECT(1, Uint8)*/ | |
124 DEFINE_SSE_FILLRECT(2, Uint16) | |
125 DEFINE_SSE_FILLRECT(4, Uint32) | |
126 | |
127 /* *INDENT-ON* */ | |
128 #endif /* __SSE__ */ | |
129 | |
130 #ifdef __MMX__ | |
131 /* *INDENT-OFF* */ | |
132 | |
133 #define MMX_BEGIN \ | |
134 __m64 c64 = _mm_set_pi32(color, color) | |
135 | |
136 #define MMX_WORK \ | |
137 for (i = n / 64; i--;) { \ | |
138 _mm_stream_pi((__m64 *)(p+0), c64); \ | |
139 _mm_stream_pi((__m64 *)(p+8), c64); \ | |
140 _mm_stream_pi((__m64 *)(p+16), c64); \ | |
141 _mm_stream_pi((__m64 *)(p+24), c64); \ | |
142 _mm_stream_pi((__m64 *)(p+32), c64); \ | |
143 _mm_stream_pi((__m64 *)(p+40), c64); \ | |
144 _mm_stream_pi((__m64 *)(p+48), c64); \ | |
145 _mm_stream_pi((__m64 *)(p+56), c64); \ | |
146 p += 64; \ | |
147 } | |
148 | |
149 #define MMX_END \ | |
150 _mm_empty() | |
151 | |
152 #define DEFINE_MMX_FILLRECT(bpp, type) \ | |
153 static void \ | |
154 SDL_DrawRect##bpp##MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \ | |
155 { \ | |
156 MMX_BEGIN; \ | |
157 \ | |
158 while (h--) { \ | |
159 int i, n = w * bpp; \ | |
160 Uint8 *p = pixels; \ | |
161 \ | |
162 if (n > 63) { \ | |
163 int adjust = 8 - ((uintptr_t)p & 7); \ | |
164 if (adjust < 8) { \ | |
165 n -= adjust; \ | |
166 adjust /= bpp; \ | |
167 while (adjust--) { \ | |
168 *((type *)p) = (type)color; \ | |
169 p += bpp; \ | |
170 } \ | |
171 } \ | |
172 MMX_WORK; \ | |
173 } \ | |
174 if (n & 63) { \ | |
175 int remainder = (n & 63); \ | |
176 remainder /= bpp; \ | |
177 while (remainder--) { \ | |
178 *((type *)p) = (type)color; \ | |
179 p += bpp; \ | |
180 } \ | |
181 } \ | |
182 pixels += pitch; \ | |
183 } \ | |
184 \ | |
185 MMX_END; \ | |
186 } | |
187 | |
188 static void | |
189 SDL_DrawRect1MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) | |
190 { | |
191 MMX_BEGIN; | |
192 | |
193 while (h--) { | |
194 int i, n = w; | |
195 Uint8 *p = pixels; | |
196 | |
197 if (n > 63) { | |
198 int adjust = 8 - ((uintptr_t)p & 7); | |
199 if (adjust) { | |
200 n -= adjust; | |
201 SDL_memset(p, color, adjust); | |
202 p += adjust; | |
203 } | |
204 MMX_WORK; | |
205 } | |
206 if (n & 63) { | |
207 int remainder = (n & 63); | |
208 SDL_memset(p, color, remainder); | |
209 p += remainder; | |
210 } | |
211 pixels += pitch; | |
212 } | |
213 | |
214 MMX_END; | |
215 } | |
216 /*DEFINE_MMX_FILLRECT(1, Uint8)*/ | |
217 DEFINE_MMX_FILLRECT(2, Uint16) | |
218 DEFINE_MMX_FILLRECT(4, Uint32) | |
219 | |
220 /* *INDENT-ON* */ | |
221 #endif /* __MMX__ */ | |
222 | |
223 static void | |
224 SDL_DrawRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h) | |
225 { | |
226 while (h--) { | |
227 int n = w; | |
228 Uint8 *p = pixels; | |
229 | |
230 if (n > 3) { | |
231 switch ((uintptr_t) p & 3) { | |
232 case 1: | |
233 *p++ = (Uint8) color; | |
234 --n; | |
235 case 2: | |
236 *p++ = (Uint8) color; | |
237 --n; | |
238 case 3: | |
239 *p++ = (Uint8) color; | |
240 --n; | |
241 } | |
242 SDL_memset4(p, color, (n >> 2)); | |
243 } | |
244 if (n & 3) { | |
245 p += (n & ~3); | |
246 switch (n & 3) { | |
247 case 3: | |
248 *p++ = (Uint8) color; | |
249 case 2: | |
250 *p++ = (Uint8) color; | |
251 case 1: | |
252 *p++ = (Uint8) color; | |
253 } | |
254 } | |
255 pixels += pitch; | |
256 } | |
257 } | |
258 | |
259 static void | |
260 SDL_DrawRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h) | |
261 { | |
262 while (h--) { | |
263 int n = w; | |
264 Uint16 *p = (Uint16 *) pixels; | |
265 | |
266 if (n > 1) { | |
267 if ((uintptr_t) p & 2) { | |
268 *p++ = (Uint16) color; | |
269 --n; | |
270 } | |
271 SDL_memset4(p, color, (n >> 1)); | |
272 } | |
273 if (n & 1) { | |
274 p[n - 1] = (Uint16) color; | |
275 } | |
276 pixels += pitch; | |
277 } | |
278 } | |
279 | |
280 static void | |
281 SDL_DrawRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h) | |
282 { | |
283 Uint8 r = (Uint8) ((color >> 16) & 0xFF); | |
284 Uint8 g = (Uint8) ((color >> 8) & 0xFF); | |
285 Uint8 b = (Uint8) (color & 0xFF); | |
286 | |
287 while (h--) { | |
288 int n = w; | |
289 Uint8 *p = pixels; | |
290 | |
291 while (n--) { | |
292 *p++ = r; | |
293 *p++ = g; | |
294 *p++ = b; | |
295 } | |
296 pixels += pitch; | |
297 } | |
298 } | |
299 | |
300 static void | |
301 SDL_DrawRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h) | |
302 { | |
303 while (h--) { | |
304 SDL_memset4(pixels, color, w); | |
305 pixels += pitch; | |
306 } | |
307 } | |
308 | |
309 /* | |
310 * This function performs a fast fill of the given rectangle with 'color' | |
311 */ | |
312 int | |
313 SDL_DrawRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color) | |
314 { | |
315 SDL_Rect clipped; | |
316 Uint8 *pixels; | |
317 | |
318 if (!dst) { | |
319 SDL_SetError("Passed NULL destination surface"); | |
320 return -1; | |
321 } | |
322 | |
323 /* This function doesn't work on surfaces < 8 bpp */ | |
324 if (dst->format->BitsPerPixel < 8) { | |
325 SDL_SetError("SDL_DrawRect(): Unsupported surface format"); | |
326 return -1; | |
327 } | |
328 | |
329 /* If 'rect' == NULL, then fill the whole surface */ | |
330 if (rect) { | |
331 /* Perform clipping */ | |
332 if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) { | |
333 return 0; | |
334 } | |
335 rect = &clipped; | |
336 } else { | |
337 rect = &dst->clip_rect; | |
338 } | |
339 | |
340 /* Perform software fill */ | |
341 if (!dst->pixels) { | |
342 SDL_SetError("SDL_DrawRect(): You must lock the surface"); | |
343 return (-1); | |
344 } | |
345 | |
346 pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch + | |
347 rect->x * dst->format->BytesPerPixel; | |
348 | |
349 switch (dst->format->BytesPerPixel) { | |
350 case 1: | |
351 { | |
352 color |= (color << 8); | |
353 color |= (color << 16); | |
354 #ifdef __SSE__ | |
355 if (SDL_HasSSE()) { | |
356 SDL_DrawRect1SSE(pixels, dst->pitch, color, rect->w, rect->h); | |
357 break; | |
358 } | |
359 #endif | |
360 #ifdef __MMX__ | |
361 if (SDL_HasMMX()) { | |
362 SDL_DrawRect1MMX(pixels, dst->pitch, color, rect->w, rect->h); | |
363 break; | |
364 } | |
365 #endif | |
366 SDL_DrawRect1(pixels, dst->pitch, color, rect->w, rect->h); | |
367 break; | |
368 } | |
369 | |
370 case 2: | |
371 { | |
372 color |= (color << 16); | |
373 #ifdef __SSE__ | |
374 if (SDL_HasSSE()) { | |
375 SDL_DrawRect2SSE(pixels, dst->pitch, color, rect->w, rect->h); | |
376 break; | |
377 } | |
378 #endif | |
379 #ifdef __MMX__ | |
380 if (SDL_HasMMX()) { | |
381 SDL_DrawRect2MMX(pixels, dst->pitch, color, rect->w, rect->h); | |
382 break; | |
383 } | |
384 #endif | |
385 SDL_DrawRect2(pixels, dst->pitch, color, rect->w, rect->h); | |
386 break; | |
387 } | |
388 | |
389 case 3: | |
390 /* 24-bit RGB is a slow path, at least for now. */ | |
391 { | |
392 SDL_DrawRect3(pixels, dst->pitch, color, rect->w, rect->h); | |
393 break; | |
394 } | |
395 | |
396 case 4: | |
397 { | |
398 #ifdef __SSE__ | |
399 if (SDL_HasSSE()) { | |
400 SDL_DrawRect4SSE(pixels, dst->pitch, color, rect->w, rect->h); | |
401 break; | |
402 } | |
403 #endif | |
404 #ifdef __MMX__ | |
405 if (SDL_HasMMX()) { | |
406 SDL_DrawRect4MMX(pixels, dst->pitch, color, rect->w, rect->h); | |
407 break; | |
408 } | |
409 #endif | |
410 SDL_DrawRect4(pixels, dst->pitch, color, rect->w, rect->h); | |
411 break; | |
412 } | |
413 } | |
414 | |
415 /* We're done! */ | |
416 return 0; | |
417 } | |
418 | |
419 int | |
420 SDL_DrawRects(SDL_Surface * dst, const SDL_Rect ** rects, int count, | |
421 Uint32 color) | |
422 { | |
423 int i; | |
424 int status = 0; | |
425 | |
426 for (i = 0; i < count; ++i) { | |
427 status = SDL_DrawRect(dst, rects[i], color); | |
428 } | |
429 return status; | |
430 } | |
431 | |
432 /* vi: set ts=4 sw=4 expandtab: */ |