SDL  2.0
SDL_fillrect.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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) \
60 static void \
61 SDL_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 
98 static void
99 SDL_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) */
127 DEFINE_SSE_FILLRECT(2, Uint16)
128 DEFINE_SSE_FILLRECT(4, Uint32)
129 
130 /* *INDENT-ON* */
131 #endif /* __SSE__ */
132 
133 static void
134 SDL_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 
172 static void
173 SDL_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 
196 static void
197 SDL_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 
224 static void
225 SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
226 {
227  while (h--) {
228  SDL_memset4(pixels, color, w);
229  pixels += pitch;
230  }
231 }
232 
233 /*
234  * This function performs a fast fill of the given rectangle with 'color'
235  */
236 int
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 
326 int
328  Uint32 color)
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: */
GLenum GLenum dst
Uint8 BytesPerPixel
Definition: SDL_pixels.h:320
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
SDL_Rect rect
Definition: testrelative.c:27
GLfloat GLfloat GLfloat GLfloat h
GLfloat GLfloat p
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
uint32_t Uint32
Definition: SDL_stdinc.h:181
#define SDL_IntersectRect
SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r)
Returns true if the rectangle has no area.
Definition: SDL_rect.h:82
static void SDL_FillRect3(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
Definition: SDL_fillrect.c:197
int SDL_FillRects(SDL_Surface *dst, const SDL_Rect *rects, int count, Uint32 color)
Definition: SDL_fillrect.c:327
void * pixels
Definition: SDL_surface.h:75
SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords)
Definition: SDL_stdinc.h:420
uint8_t Uint8
Definition: SDL_stdinc.h:157
Uint8 BitsPerPixel
Definition: SDL_pixels.h:319
GLubyte GLubyte GLubyte GLubyte w
unsigned int uintptr_t
int x
Definition: SDL_rect.h:66
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
int w
Definition: SDL_rect.h:67
SDL_Rect clip_rect
Definition: SDL_surface.h:85
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:164
int SDL_FillRect(SDL_Surface *dst, const SDL_Rect *rect, Uint32 color)
Definition: SDL_fillrect.c:237
SDL_PixelFormat * format
Definition: SDL_surface.h:72
#define SDL_SetError
static void SDL_FillRect2(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
Definition: SDL_fillrect.c:173
int h
Definition: SDL_rect.h:67
GLuint color
GLdouble n
uint16_t Uint16
Definition: SDL_stdinc.h:169
static void SDL_FillRect4(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
Definition: SDL_fillrect.c:225
static void SDL_FillRect1(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
Definition: SDL_fillrect.c:134
EGLSurface EGLint * rects
Definition: eglext.h:282
#define SDL_HasSSE
int y
Definition: SDL_rect.h:66
#define SDL_memset
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64