src/video/SDL_fillrect.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 09 Apr 2015 22:28:37 -0400
changeset 9541 cf8fab52e33b
parent 9374 b577c4753421
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Merged Alex Szpakowski's iOS-improvement branch to default.

Fixes Bugzilla #2798.
Fixes Bugzilla #2212.
Fixes Bugzilla #2826.
Fixes Bugzilla #2661.
Fixes Bugzilla #1885.
Fixes Bugzilla #1578.
Fixes Bugzilla #2751.

(whew!)

Notable changes, from Alex's notes:

- The SDL_WINDOW_ALLOW_HIGHDPI flag is now needed (along with SDL_GL_GetDrawableSize or SDL_GetRendererOutputSize) to use Retina / high DPI resolutions, bringing SDL’s Retina-related behavior on iOS in line with Mac OS X. Window dimensions and display modes are now in the “points” (non-high DPI) coordinate system rather than pixels, whereas SDL_GL_GetDrawableSize is in pixels.

- Reworked the custom extended launch screen code:
- It now hides after the first SDL_PumpEvents call rather than SDL_CreateWindow, and it fades out in a similar manner to the system launch screen behavior.
- It now mirrors the system launch screen behavior when deciding which image to display: it falls back to using the Launch Images dictionary in Info.plist if the iOS 8+ launch screen nib isn’t available, and if the Launch Images dictionary doesn’t exist it uses the old standard launch image names.
- The extended launch screen can now be disabled via the SDL_IPHONE_LAUNCHSCREEN define in SDL_config_iphoneos.h.

- Added support for SDL_HINT_ACCELEROMETER_AS_JOYSTICK.

- Added access to a window view's renderbuffer and framebuffer to syswm.

- Added OpenGL ES debug labels for the Renderbuffer and Framebuffer Objects created with SDL_GL_CreateContext.

- Added support for sRGB OpenGL ES contexts on iOS 7+.

- Updated OpenGL ES contexts to support native-resolution rendering (when SDL_WINDOW_ALLOW_HIGHDPI is enabled) on the iPhone 6 Plus, i.e. 1080x1920 rather than 1242x2208.

- Updated SDL_GL_CreateContext, SDL_GL_SwapWindow, SDL_GL_MakeCurrent, and SDL_GL_DeleteContext to be more robust.

- Updated SDL windows to display a UIView at all times, even when an OpenGL context is not active. This allows rotation, touch events, and other windowing-related events to work properly without an active OpenGL context. It also makes it easier to use SDL_GetWindowWMInfo after creating a SDL window.

- Updated the iOS-specific Objective-C code to use cleaner and more modern language features and APIs, including ARC instead of manual reference counting.

- Updated SDL_HINT_ORIENTATIONS to allow disabling custom orientations if the hint is set with no valid orientation names.

- Fixed several rotation and orientation bugs with windows and display modes, especially in iOS 8+.

- Fixed SDL_SetWindowFullscreen failing to update the status bar visibility on iOS 7+.

- Fixed the orientation of the offset applied to the window’s view when the onscreen keyboard is shown in iOS 8+.

- Fixed SDL_IsScreenKeyboardShown (patch by Phil Hassey.)

- Fixed several major memory leaks caused by missing autorelease pool blocks in the iOS-specific Objective-C code.

- Removed several dead code paths.

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