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: */