src/video/SDL_fillrect.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 24 Jan 2010 21:10:53 +0000
changeset 3697 f7b03b6838cb
parent 3536 0267b8b1595c
child 5262 b530ef003506
permissions -rw-r--r--
Fixed bug #926

Updated copyright to LGPL version 2.1 and year 2010
slouken@2888
     1
/*
slouken@2888
     2
    SDL - Simple DirectMedia Layer
slouken@3697
     3
    Copyright (C) 1997-2010 Sam Lantinga
slouken@2888
     4
slouken@2888
     5
    This library is free software; you can redistribute it and/or
slouken@2888
     6
    modify it under the terms of the GNU Lesser General Public
slouken@2888
     7
    License as published by the Free Software Foundation; either
slouken@2888
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@2888
     9
slouken@2888
    10
    This library is distributed in the hope that it will be useful,
slouken@2888
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@2888
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@2888
    13
    Lesser General Public License for more details.
slouken@2888
    14
slouken@2888
    15
    You should have received a copy of the GNU Lesser General Public
slouken@2888
    16
    License along with this library; if not, write to the Free Software
slouken@2888
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@2888
    18
slouken@2888
    19
    Sam Lantinga
slouken@2888
    20
    slouken@libsdl.org
slouken@2888
    21
*/
slouken@2888
    22
#include "SDL_config.h"
slouken@2888
    23
slouken@2888
    24
#include "SDL_video.h"
slouken@2888
    25
#include "SDL_blit.h"
slouken@2888
    26
slouken@2888
    27
slouken@2888
    28
#ifdef __SSE__
slouken@2888
    29
/* *INDENT-OFF* */
slouken@2888
    30
slouken@2888
    31
#ifdef _MSC_VER
slouken@2888
    32
#define SSE_BEGIN \
slouken@2888
    33
    __m128 c128; \
slouken@2888
    34
    c128.m128_u32[0] = color; \
slouken@2888
    35
    c128.m128_u32[1] = color; \
slouken@2888
    36
    c128.m128_u32[2] = color; \
slouken@2888
    37
    c128.m128_u32[3] = color;
slouken@2888
    38
#else
slouken@2888
    39
#define SSE_BEGIN \
slouken@2888
    40
    DECLARE_ALIGNED(Uint32, cccc[4], 16); \
slouken@2888
    41
    cccc[0] = color; \
slouken@2888
    42
    cccc[1] = color; \
slouken@2888
    43
    cccc[2] = color; \
slouken@2888
    44
    cccc[3] = color; \
slouken@2888
    45
    __m128 c128 = *(__m128 *)cccc;
slouken@2888
    46
#endif
slouken@2888
    47
slouken@2888
    48
#define SSE_WORK \
slouken@2888
    49
    for (i = n / 64; i--;) { \
slouken@2888
    50
        _mm_stream_ps((float *)(p+0), c128); \
slouken@2888
    51
        _mm_stream_ps((float *)(p+16), c128); \
slouken@2888
    52
        _mm_stream_ps((float *)(p+32), c128); \
slouken@2888
    53
        _mm_stream_ps((float *)(p+48), c128); \
slouken@2888
    54
        p += 64; \
slouken@2888
    55
    }
slouken@2888
    56
slouken@2888
    57
#define SSE_END
slouken@2888
    58
slouken@2888
    59
#define DEFINE_SSE_FILLRECT(bpp, type) \
slouken@2888
    60
static void \
slouken@2888
    61
SDL_FillRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
slouken@2888
    62
{ \
slouken@2888
    63
    SSE_BEGIN; \
slouken@2888
    64
 \
slouken@2888
    65
    while (h--) { \
slouken@2888
    66
        int i, n = w * bpp; \
slouken@2888
    67
        Uint8 *p = pixels; \
slouken@2888
    68
 \
slouken@3012
    69
        if (n > 63) { \
slouken@2888
    70
            int adjust = 16 - ((uintptr_t)p & 15); \
slouken@2888
    71
            if (adjust < 16) { \
slouken@2888
    72
                n -= adjust; \
slouken@2888
    73
                adjust /= bpp; \
slouken@2888
    74
                while (adjust--) { \
slouken@2888
    75
                    *((type *)p) = (type)color; \
slouken@2888
    76
                    p += bpp; \
slouken@2888
    77
                } \
slouken@2888
    78
            } \
slouken@2888
    79
            SSE_WORK; \
slouken@2888
    80
        } \
slouken@2888
    81
        if (n & 63) { \
slouken@2888
    82
            int remainder = (n & 63); \
slouken@2888
    83
            remainder /= bpp; \
slouken@2888
    84
            while (remainder--) { \
slouken@2888
    85
                *((type *)p) = (type)color; \
slouken@2888
    86
                p += bpp; \
slouken@2888
    87
            } \
slouken@2888
    88
        } \
slouken@2888
    89
        pixels += pitch; \
slouken@2888
    90
    } \
slouken@2888
    91
 \
slouken@2888
    92
    SSE_END; \
slouken@2888
    93
}
slouken@2888
    94
slouken@3012
    95
static void
slouken@3012
    96
SDL_FillRect1SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
slouken@3012
    97
{
slouken@3012
    98
    SSE_BEGIN;
slouken@3012
    99
slouken@3012
   100
    while (h--) {
slouken@3012
   101
        int i, n = w;
slouken@3012
   102
        Uint8 *p = pixels;
slouken@3012
   103
slouken@3012
   104
        if (n > 63) {
slouken@3012
   105
            int adjust = 16 - ((uintptr_t)p & 15);
slouken@3012
   106
            if (adjust) {
slouken@3012
   107
                n -= adjust;
slouken@3012
   108
                SDL_memset(p, color, adjust);
slouken@3012
   109
                p += adjust;
slouken@3012
   110
            }
slouken@3012
   111
            SSE_WORK;
slouken@3012
   112
        }
slouken@3012
   113
        if (n & 63) {
slouken@3012
   114
            int remainder = (n & 63);
slouken@3012
   115
            SDL_memset(p, color, remainder);
slouken@3012
   116
            p += remainder;
slouken@3012
   117
        }
slouken@3012
   118
        pixels += pitch;
slouken@3012
   119
    }
slouken@3012
   120
slouken@3012
   121
    SSE_END;
slouken@3012
   122
}
slouken@3012
   123
/*DEFINE_SSE_FILLRECT(1, Uint8)*/
slouken@2888
   124
DEFINE_SSE_FILLRECT(2, Uint16)
slouken@2888
   125
DEFINE_SSE_FILLRECT(4, Uint32)
slouken@2888
   126
slouken@2888
   127
/* *INDENT-ON* */
slouken@2888
   128
#endif /* __SSE__ */
slouken@2888
   129
slouken@2888
   130
#ifdef __MMX__
slouken@2888
   131
/* *INDENT-OFF* */
slouken@2888
   132
slouken@2888
   133
#define MMX_BEGIN \
slouken@2888
   134
    __m64 c64 = _mm_set_pi32(color, color)
slouken@2888
   135
slouken@2888
   136
#define MMX_WORK \
slouken@2888
   137
    for (i = n / 64; i--;) { \
slouken@2888
   138
        _mm_stream_pi((__m64 *)(p+0), c64); \
slouken@2888
   139
        _mm_stream_pi((__m64 *)(p+8), c64); \
slouken@2888
   140
        _mm_stream_pi((__m64 *)(p+16), c64); \
slouken@2888
   141
        _mm_stream_pi((__m64 *)(p+24), c64); \
slouken@2888
   142
        _mm_stream_pi((__m64 *)(p+32), c64); \
slouken@2888
   143
        _mm_stream_pi((__m64 *)(p+40), c64); \
slouken@2888
   144
        _mm_stream_pi((__m64 *)(p+48), c64); \
slouken@2888
   145
        _mm_stream_pi((__m64 *)(p+56), c64); \
slouken@2888
   146
        p += 64; \
slouken@2888
   147
    }
slouken@2888
   148
slouken@2888
   149
#define MMX_END \
slouken@2888
   150
    _mm_empty()
slouken@2888
   151
slouken@2888
   152
#define DEFINE_MMX_FILLRECT(bpp, type) \
slouken@2888
   153
static void \
slouken@2888
   154
SDL_FillRect##bpp##MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
slouken@2888
   155
{ \
slouken@2888
   156
    MMX_BEGIN; \
slouken@2888
   157
 \
slouken@2888
   158
    while (h--) { \
slouken@2888
   159
        int i, n = w * bpp; \
slouken@2888
   160
        Uint8 *p = pixels; \
slouken@2888
   161
 \
slouken@3012
   162
        if (n > 63) { \
slouken@2888
   163
            int adjust = 8 - ((uintptr_t)p & 7); \
slouken@2888
   164
            if (adjust < 8) { \
slouken@2888
   165
                n -= adjust; \
slouken@2888
   166
                adjust /= bpp; \
slouken@2888
   167
                while (adjust--) { \
slouken@2888
   168
                    *((type *)p) = (type)color; \
slouken@2888
   169
                    p += bpp; \
slouken@2888
   170
                } \
slouken@2888
   171
            } \
slouken@2888
   172
            MMX_WORK; \
slouken@2888
   173
        } \
slouken@2888
   174
        if (n & 63) { \
slouken@2888
   175
            int remainder = (n & 63); \
slouken@2888
   176
            remainder /= bpp; \
slouken@2888
   177
            while (remainder--) { \
slouken@2888
   178
                *((type *)p) = (type)color; \
slouken@2888
   179
                p += bpp; \
slouken@2888
   180
            } \
slouken@2888
   181
        } \
slouken@2888
   182
        pixels += pitch; \
slouken@2888
   183
    } \
slouken@2888
   184
 \
slouken@2888
   185
    MMX_END; \
slouken@2888
   186
}
slouken@2888
   187
slouken@3012
   188
static void
slouken@3012
   189
SDL_FillRect1MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h)
slouken@3012
   190
{
slouken@3012
   191
    MMX_BEGIN;
slouken@3012
   192
slouken@3012
   193
    while (h--) {
slouken@3012
   194
        int i, n = w;
slouken@3012
   195
        Uint8 *p = pixels;
slouken@3012
   196
slouken@3012
   197
        if (n > 63) {
slouken@3012
   198
            int adjust = 8 - ((uintptr_t)p & 7);
slouken@3012
   199
            if (adjust) {
slouken@3012
   200
                n -= adjust;
slouken@3012
   201
                SDL_memset(p, color, adjust);
slouken@3012
   202
                p += adjust;
slouken@3012
   203
            }
slouken@3012
   204
            MMX_WORK;
slouken@3012
   205
        }
slouken@3012
   206
        if (n & 63) {
slouken@3012
   207
            int remainder = (n & 63);
slouken@3012
   208
            SDL_memset(p, color, remainder);
slouken@3012
   209
            p += remainder;
slouken@3012
   210
        }
slouken@3012
   211
        pixels += pitch;
slouken@3012
   212
    }
slouken@3012
   213
slouken@3012
   214
    MMX_END;
slouken@3012
   215
}
slouken@3012
   216
/*DEFINE_MMX_FILLRECT(1, Uint8)*/
slouken@2888
   217
DEFINE_MMX_FILLRECT(2, Uint16)
slouken@2888
   218
DEFINE_MMX_FILLRECT(4, Uint32)
slouken@2888
   219
slouken@2888
   220
/* *INDENT-ON* */
slouken@2888
   221
#endif /* __MMX__ */
slouken@2888
   222
slouken@2888
   223
static void
slouken@2888
   224
SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
slouken@2888
   225
{
slouken@2888
   226
    while (h--) {
slouken@2888
   227
        int n = w;
slouken@2888
   228
        Uint8 *p = pixels;
slouken@2888
   229
slouken@2888
   230
        if (n > 3) {
slouken@2888
   231
            switch ((uintptr_t) p & 3) {
slouken@2888
   232
            case 1:
slouken@2888
   233
                *p++ = (Uint8) color;
slouken@2888
   234
                --n;
slouken@2888
   235
            case 2:
slouken@2888
   236
                *p++ = (Uint8) color;
slouken@2888
   237
                --n;
slouken@2888
   238
            case 3:
slouken@2888
   239
                *p++ = (Uint8) color;
slouken@2888
   240
                --n;
slouken@2888
   241
            }
slouken@2888
   242
            SDL_memset4(p, color, (n >> 2));
slouken@2888
   243
        }
slouken@2888
   244
        if (n & 3) {
slouken@2888
   245
            p += (n & ~3);
slouken@2888
   246
            switch (n & 3) {
slouken@2888
   247
            case 3:
slouken@2888
   248
                *p++ = (Uint8) color;
slouken@2888
   249
            case 2:
slouken@2888
   250
                *p++ = (Uint8) color;
slouken@2888
   251
            case 1:
slouken@2888
   252
                *p++ = (Uint8) color;
slouken@2888
   253
            }
slouken@2888
   254
        }
slouken@2888
   255
        pixels += pitch;
slouken@2888
   256
    }
slouken@2888
   257
}
slouken@2888
   258
slouken@2888
   259
static void
slouken@2888
   260
SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
slouken@2888
   261
{
slouken@2888
   262
    while (h--) {
slouken@2888
   263
        int n = w;
slouken@2888
   264
        Uint16 *p = (Uint16 *) pixels;
slouken@2888
   265
slouken@2888
   266
        if (n > 1) {
slouken@2888
   267
            if ((uintptr_t) p & 2) {
slouken@2888
   268
                *p++ = (Uint16) color;
slouken@2888
   269
                --n;
slouken@2888
   270
            }
slouken@2888
   271
            SDL_memset4(p, color, (n >> 1));
slouken@2888
   272
        }
slouken@2888
   273
        if (n & 1) {
slouken@2888
   274
            p[n - 1] = (Uint16) color;
slouken@2888
   275
        }
slouken@2888
   276
        pixels += pitch;
slouken@2888
   277
    }
slouken@2888
   278
}
slouken@2888
   279
slouken@2888
   280
static void
slouken@2888
   281
SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
slouken@2888
   282
{
slouken@2888
   283
    Uint8 r = (Uint8) ((color >> 16) & 0xFF);
slouken@2888
   284
    Uint8 g = (Uint8) ((color >> 8) & 0xFF);
slouken@2888
   285
    Uint8 b = (Uint8) (color & 0xFF);
slouken@2888
   286
slouken@2888
   287
    while (h--) {
slouken@2888
   288
        int n = w;
slouken@2888
   289
        Uint8 *p = pixels;
slouken@2888
   290
slouken@2888
   291
        while (n--) {
slouken@2888
   292
            *p++ = r;
slouken@2888
   293
            *p++ = g;
slouken@2888
   294
            *p++ = b;
slouken@2888
   295
        }
slouken@2888
   296
        pixels += pitch;
slouken@2888
   297
    }
slouken@2888
   298
}
slouken@2888
   299
slouken@2888
   300
static void
slouken@2888
   301
SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
slouken@2888
   302
{
slouken@2888
   303
    while (h--) {
slouken@2888
   304
        SDL_memset4(pixels, color, w);
slouken@2888
   305
        pixels += pitch;
slouken@2888
   306
    }
slouken@2888
   307
}
slouken@2888
   308
slouken@2888
   309
/* 
slouken@2888
   310
 * This function performs a fast fill of the given rectangle with 'color'
slouken@2888
   311
 */
slouken@2888
   312
int
slouken@3536
   313
SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
slouken@2888
   314
{
slouken@3536
   315
    SDL_Rect clipped;
slouken@2888
   316
    Uint8 *pixels;
slouken@2888
   317
slouken@3536
   318
    if (!dst) {
slouken@3536
   319
        SDL_SetError("Passed NULL destination surface");
slouken@3536
   320
        return -1;
slouken@3536
   321
    }
slouken@3536
   322
slouken@2888
   323
    /* This function doesn't work on surfaces < 8 bpp */
slouken@2888
   324
    if (dst->format->BitsPerPixel < 8) {
slouken@2888
   325
        SDL_SetError("SDL_FillRect(): Unsupported surface format");
slouken@3536
   326
        return -1;
slouken@2888
   327
    }
slouken@2888
   328
slouken@3536
   329
    /* If 'rect' == NULL, then fill the whole surface */
slouken@3536
   330
    if (rect) {
slouken@2888
   331
        /* Perform clipping */
slouken@3536
   332
        if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
slouken@3536
   333
            return 0;
slouken@2888
   334
        }
slouken@3536
   335
        rect = &clipped;
slouken@2888
   336
    } else {
slouken@3536
   337
        rect = &dst->clip_rect;
slouken@2888
   338
    }
slouken@2888
   339
slouken@2888
   340
    /* Perform software fill */
slouken@2888
   341
    if (!dst->pixels) {
slouken@2888
   342
        SDL_SetError("SDL_FillRect(): You must lock the surface");
slouken@2888
   343
        return (-1);
slouken@2888
   344
    }
slouken@2888
   345
slouken@3536
   346
    pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
slouken@3536
   347
                                     rect->x * dst->format->BytesPerPixel;
slouken@2888
   348
slouken@2888
   349
    switch (dst->format->BytesPerPixel) {
slouken@2888
   350
    case 1:
slouken@2888
   351
        {
slouken@2888
   352
            color |= (color << 8);
slouken@2888
   353
            color |= (color << 16);
slouken@2888
   354
#ifdef __SSE__
slouken@2888
   355
            if (SDL_HasSSE()) {
slouken@3536
   356
                SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   357
                break;
slouken@2888
   358
            }
slouken@2888
   359
#endif
slouken@2888
   360
#ifdef __MMX__
slouken@2888
   361
            if (SDL_HasMMX()) {
slouken@3536
   362
                SDL_FillRect1MMX(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   363
                break;
slouken@2888
   364
            }
slouken@2888
   365
#endif
slouken@3536
   366
            SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   367
            break;
slouken@2888
   368
        }
slouken@2888
   369
slouken@2888
   370
    case 2:
slouken@2888
   371
        {
slouken@2888
   372
            color |= (color << 16);
slouken@2888
   373
#ifdef __SSE__
slouken@2888
   374
            if (SDL_HasSSE()) {
slouken@3536
   375
                SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   376
                break;
slouken@2888
   377
            }
slouken@2888
   378
#endif
slouken@2888
   379
#ifdef __MMX__
slouken@2888
   380
            if (SDL_HasMMX()) {
slouken@3536
   381
                SDL_FillRect2MMX(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   382
                break;
slouken@2888
   383
            }
slouken@2888
   384
#endif
slouken@3536
   385
            SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   386
            break;
slouken@2888
   387
        }
slouken@2888
   388
slouken@2888
   389
    case 3:
slouken@2888
   390
        /* 24-bit RGB is a slow path, at least for now. */
slouken@2888
   391
        {
slouken@3536
   392
            SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   393
            break;
slouken@2888
   394
        }
slouken@2888
   395
slouken@2888
   396
    case 4:
slouken@2888
   397
        {
slouken@2888
   398
#ifdef __SSE__
slouken@2888
   399
            if (SDL_HasSSE()) {
slouken@3536
   400
                SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   401
                break;
slouken@2888
   402
            }
slouken@2888
   403
#endif
slouken@2888
   404
#ifdef __MMX__
slouken@2888
   405
            if (SDL_HasMMX()) {
slouken@3536
   406
                SDL_FillRect4MMX(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   407
                break;
slouken@2888
   408
            }
slouken@2888
   409
#endif
slouken@3536
   410
            SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
slouken@2888
   411
            break;
slouken@2888
   412
        }
slouken@2888
   413
    }
slouken@2888
   414
slouken@2888
   415
    /* We're done! */
slouken@3536
   416
    return 0;
slouken@3536
   417
}
slouken@3536
   418
slouken@3536
   419
int
slouken@3536
   420
SDL_FillRects(SDL_Surface * dst, const SDL_Rect ** rects, int count,
slouken@3536
   421
              Uint32 color)
slouken@3536
   422
{
slouken@3536
   423
    int i;
slouken@3536
   424
    int status = 0;
slouken@3536
   425
slouken@3536
   426
    for (i = 0; i < count; ++i) {
slouken@3536
   427
        status = SDL_FillRect(dst, rects[i], color);
slouken@3536
   428
    }
slouken@3536
   429
    return status;
slouken@2888
   430
}
slouken@2888
   431
slouken@2888
   432
/* vi: set ts=4 sw=4 expandtab: */