SDL 2.0
SDL_fillrect.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "../SDL_internal.h"
22
23#include "SDL_video.h"
24#include "SDL_blit.h"
25
26
27#ifdef __SSE__
28/* *INDENT-OFF* */
29
30#ifdef _MSC_VER
31#define SSE_BEGIN \
32 __m128 c128; \
33 c128.m128_u32[0] = color; \
34 c128.m128_u32[1] = color; \
35 c128.m128_u32[2] = color; \
36 c128.m128_u32[3] = color;
37#else
38#define SSE_BEGIN \
39 __m128 c128; \
40 DECLARE_ALIGNED(Uint32, cccc[4], 16); \
41 cccc[0] = color; \
42 cccc[1] = color; \
43 cccc[2] = color; \
44 cccc[3] = color; \
45 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) \
60static void \
61SDL_FillRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
62{ \
63 int i, n; \
64 Uint8 *p = NULL; \
65 \
66 SSE_BEGIN; \
67 \
68 while (h--) { \
69 n = w * bpp; \
70 p = pixels; \
71 \
72 if (n > 63) { \
73 int adjust = 16 - ((uintptr_t)p & 15); \
74 if (adjust < 16) { \
75 n -= adjust; \
76 adjust /= bpp; \
77 while (adjust--) { \
78 *((type *)p) = (type)color; \
79 p += bpp; \
80 } \
81 } \
82 SSE_WORK; \
83 } \
84 if (n & 63) { \
85 int remainder = (n & 63); \
86 remainder /= bpp; \
87 while (remainder--) { \
88 *((type *)p) = (type)color; \
89 p += bpp; \
90 } \
91 } \
92 pixels += pitch; \
93 } \
94 \
95 SSE_END; \
96}
97
98static void
99SDL_FillRect1SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
100{
101 int i, n;
102
103 SSE_BEGIN;
104 while (h--) {
105 Uint8 *p = pixels;
106 n = w;
107
108 if (n > 63) {
109 int adjust = 16 - ((uintptr_t)p & 15);
110 if (adjust) {
111 n -= adjust;
112 SDL_memset(p, color, adjust);
113 p += adjust;
114 }
115 SSE_WORK;
116 }
117 if (n & 63) {
118 int remainder = (n & 63);
119 SDL_memset(p, color, remainder);
120 }
121 pixels += pitch;
122 }
123
124 SSE_END;
125}
126/* DEFINE_SSE_FILLRECT(1, Uint8) */
127DEFINE_SSE_FILLRECT(2, Uint16)
128DEFINE_SSE_FILLRECT(4, Uint32)
129
130/* *INDENT-ON* */
131#endif /* __SSE__ */
132
133static void
134SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
135{
136 int n;
137 Uint8 *p = NULL;
138
139 while (h--) {
140 n = w;
141 p = pixels;
142
143 if (n > 3) {
144 switch ((uintptr_t) p & 3) {
145 case 1:
146 *p++ = (Uint8) color;
147 --n; /* fallthrough */
148 case 2:
149 *p++ = (Uint8) color;
150 --n; /* fallthrough */
151 case 3:
152 *p++ = (Uint8) color;
153 --n; /* fallthrough */
154 }
155 SDL_memset4(p, color, (n >> 2));
156 }
157 if (n & 3) {
158 p += (n & ~3);
159 switch (n & 3) {
160 case 3:
161 *p++ = (Uint8) color; /* fallthrough */
162 case 2:
163 *p++ = (Uint8) color; /* fallthrough */
164 case 1:
165 *p++ = (Uint8) color; /* fallthrough */
166 }
167 }
168 pixels += pitch;
169 }
170}
171
172static void
173SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
174{
175 int n;
176 Uint16 *p = NULL;
177
178 while (h--) {
179 n = w;
180 p = (Uint16 *) pixels;
181
182 if (n > 1) {
183 if ((uintptr_t) p & 2) {
184 *p++ = (Uint16) color;
185 --n;
186 }
187 SDL_memset4(p, color, (n >> 1));
188 }
189 if (n & 1) {
190 p[n - 1] = (Uint16) color;
191 }
192 pixels += pitch;
193 }
194}
195
196static void
197SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
198{
199#if SDL_BYTEORDER == SDL_LIL_ENDIAN
200 Uint8 b1 = (Uint8) (color & 0xFF);
201 Uint8 b2 = (Uint8) ((color >> 8) & 0xFF);
202 Uint8 b3 = (Uint8) ((color >> 16) & 0xFF);
203#elif SDL_BYTEORDER == SDL_BIG_ENDIAN
204 Uint8 b1 = (Uint8) ((color >> 16) & 0xFF);
205 Uint8 b2 = (Uint8) ((color >> 8) & 0xFF);
206 Uint8 b3 = (Uint8) (color & 0xFF);
207#endif
208 int n;
209 Uint8 *p = NULL;
210
211 while (h--) {
212 n = w;
213 p = pixels;
214
215 while (n--) {
216 *p++ = b1;
217 *p++ = b2;
218 *p++ = b3;
219 }
220 pixels += pitch;
221 }
222}
223
224static void
225SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
226{
227 while (h--) {
229 pixels += pitch;
230 }
231}
232
233/*
234 * This function performs a fast fill of the given rectangle with 'color'
235 */
236int
238{
239 SDL_Rect clipped;
240 Uint8 *pixels;
241
242 if (!dst) {
243 return SDL_SetError("Passed NULL destination surface");
244 }
245
246 /* This function doesn't work on surfaces < 8 bpp */
247 if (dst->format->BitsPerPixel < 8) {
248 return SDL_SetError("SDL_FillRect(): Unsupported surface format");
249 }
250
251 /* If 'rect' == NULL, then fill the whole surface */
252 if (rect) {
253 /* Perform clipping */
254 if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
255 return 0;
256 }
257 rect = &clipped;
258 } else {
259 rect = &dst->clip_rect;
260 /* Don't attempt to fill if the surface's clip_rect is empty */
261 if (SDL_RectEmpty(rect)) {
262 return 0;
263 }
264 }
265
266 /* Perform software fill */
267 if (!dst->pixels) {
268 return SDL_SetError("SDL_FillRect(): You must lock the surface");
269 }
270
271 pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
272 rect->x * dst->format->BytesPerPixel;
273
274 switch (dst->format->BytesPerPixel) {
275 case 1:
276 {
277 color |= (color << 8);
278 color |= (color << 16);
279#ifdef __SSE__
280 if (SDL_HasSSE()) {
281 SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
282 break;
283 }
284#endif
285 SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h);
286 break;
287 }
288
289 case 2:
290 {
291 color |= (color << 16);
292#ifdef __SSE__
293 if (SDL_HasSSE()) {
294 SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h);
295 break;
296 }
297#endif
298 SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
299 break;
300 }
301
302 case 3:
303 /* 24-bit RGB is a slow path, at least for now. */
304 {
305 SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
306 break;
307 }
308
309 case 4:
310 {
311#ifdef __SSE__
312 if (SDL_HasSSE()) {
313 SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
314 break;
315 }
316#endif
317 SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
318 break;
319 }
320 }
321
322 /* We're done! */
323 return 0;
324}
325
326int
329{
330 int i;
331 int status = 0;
332
333 if (!rects) {
334 return SDL_SetError("SDL_FillRects() passed NULL rects");
335 }
336
337 for (i = 0; i < count; ++i) {
338 status += SDL_FillRect(dst, &rects[i], color);
339 }
340 return status;
341}
342
343/* vi: set ts=4 sw=4 expandtab: */
unsigned int uintptr_t
#define SDL_SetError
#define SDL_memset
#define SDL_HasSSE
#define SDL_IntersectRect
static void SDL_FillRect2(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
Definition: SDL_fillrect.c:173
static void SDL_FillRect3(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
Definition: SDL_fillrect.c:197
static void SDL_FillRect1(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
Definition: SDL_fillrect.c:134
static void SDL_FillRect4(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
Definition: SDL_fillrect.c:225
int SDL_FillRect(SDL_Surface *dst, const SDL_Rect *rect, Uint32 color)
Definition: SDL_fillrect.c:237
int SDL_FillRects(SDL_Surface *dst, const SDL_Rect *rects, int count, Uint32 color)
Definition: SDL_fillrect.c:327
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
GLuint color
GLenum GLenum dst
GLfloat GLfloat p
GLdouble n
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r)
Returns true if the rectangle has no area.
Definition: SDL_rect.h:108
SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords)
Definition: SDL_stdinc.h:420
uint32_t Uint32
Definition: SDL_stdinc.h:203
uint16_t Uint16
Definition: SDL_stdinc.h:191
uint8_t Uint8
Definition: SDL_stdinc.h:179
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:167
EGLSurface EGLint * rects
Definition: eglext.h:282
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:78
int h
Definition: SDL_rect.h:80
int w
Definition: SDL_rect.h:80
int y
Definition: SDL_rect.h:79
int x
Definition: SDL_rect.h:79
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
SDL_Rect rect
Definition: testrelative.c:27