src/render/software/SDL_drawline.c
author Sam Lantinga
Thu, 03 Feb 2011 15:49:37 -0800
changeset 5166 4d39eeaad00b
parent 5163 d72793305335
child 5226 710d00cb3a6a
permissions -rwxr-xr-x
Added a way to get a framebuffer interface for a window, and also a way to create a software renderer for an arbitrary surface.
The software renderer has been re-routed to use the framebuffer interface, which makes it possible to have software rendering available even on simple ports.
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@2898
    24
#include "SDL_draw.h"
slouken@5163
    25
#include "SDL_drawline.h"
slouken@5166
    26
#include "SDL_drawpoint.h"
slouken@5163
    27
slouken@2890
    28
slouken@3596
    29
static void
slouken@3596
    30
SDL_DrawLine1(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color,
slouken@3596
    31
              SDL_bool draw_end)
slouken@3596
    32
{
slouken@3596
    33
    if (y1 == y2) {
slouken@3671
    34
        //HLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end);
slouken@3671
    35
        int length;
slouken@3671
    36
        int pitch = (dst->pitch / dst->format->BytesPerPixel);
slouken@3671
    37
        Uint8 *pixel;
slouken@3671
    38
        if (x1 <= x2) {
slouken@3671
    39
            pixel = (Uint8 *)dst->pixels + y1 * pitch + x1;
slouken@3671
    40
            length = draw_end ? (x2-x1+1) : (x2-x1);
slouken@3671
    41
        } else {
slouken@3671
    42
            pixel = (Uint8 *)dst->pixels + y1 * pitch + x2;
slouken@3671
    43
            if (!draw_end) {
slouken@3671
    44
                ++pixel;
slouken@3671
    45
            }
slouken@3671
    46
            length = draw_end ? (x1-x2+1) : (x1-x2);
slouken@3671
    47
        }
slouken@3671
    48
        SDL_memset(pixel, color, length);
slouken@3596
    49
    } else if (x1 == x2) {
slouken@3596
    50
        VLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end);
slouken@3596
    51
    } else if (ABS(x1 - x2) == ABS(y1 - y2)) {
slouken@3596
    52
        DLINE(Uint8, DRAW_FASTSETPIXEL1, draw_end);
slouken@3596
    53
    } else {
slouken@3596
    54
        BLINE(x1, y1, x2, y2, DRAW_FASTSETPIXELXY1, draw_end);
slouken@3596
    55
    }
slouken@3596
    56
}
slouken@3596
    57
slouken@3596
    58
static void
slouken@3596
    59
SDL_DrawLine2(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color,
slouken@3596
    60
              SDL_bool draw_end)
slouken@3596
    61
{
slouken@3596
    62
    if (y1 == y2) {
slouken@3596
    63
        HLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end);
slouken@3596
    64
    } else if (x1 == x2) {
slouken@3596
    65
        VLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end);
slouken@3596
    66
    } else if (ABS(x1 - x2) == ABS(y1 - y2)) {
slouken@3596
    67
        DLINE(Uint16, DRAW_FASTSETPIXEL2, draw_end);
slouken@3596
    68
    } else {
slouken@3596
    69
        Uint8 _r, _g, _b, _a;
slouken@3596
    70
        const SDL_PixelFormat * fmt = dst->format;
slouken@3596
    71
        SDL_GetRGBA(color, fmt, &_r, &_g, &_b, &_a);
slouken@3596
    72
        if (fmt->Rmask == 0x7C00) {
slouken@3596
    73
            AALINE(x1, y1, x2, y2,
slouken@3596
    74
                   DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB555,
slouken@3596
    75
                   draw_end);
slouken@3596
    76
        } else if (fmt->Rmask == 0xF800) {
slouken@3596
    77
            AALINE(x1, y1, x2, y2,
slouken@3596
    78
                   DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY_BLEND_RGB565,
slouken@3596
    79
                   draw_end);
slouken@3596
    80
        } else {
slouken@3596
    81
            AALINE(x1, y1, x2, y2,
slouken@3596
    82
                   DRAW_FASTSETPIXELXY2, DRAW_SETPIXELXY2_BLEND_RGB,
slouken@3596
    83
                   draw_end);
slouken@3596
    84
        }
slouken@3596
    85
    }
slouken@3596
    86
}
slouken@3596
    87
slouken@3596
    88
static void
slouken@3596
    89
SDL_DrawLine4(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color,
slouken@3596
    90
              SDL_bool draw_end)
slouken@3596
    91
{
slouken@3596
    92
    if (y1 == y2) {
slouken@3596
    93
        HLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end);
slouken@3596
    94
    } else if (x1 == x2) {
slouken@3596
    95
        VLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end);
slouken@3596
    96
    } else if (ABS(x1 - x2) == ABS(y1 - y2)) {
slouken@3596
    97
        DLINE(Uint32, DRAW_FASTSETPIXEL4, draw_end);
slouken@3596
    98
    } else {
slouken@3596
    99
        Uint8 _r, _g, _b, _a;
slouken@3596
   100
        const SDL_PixelFormat * fmt = dst->format;
slouken@3596
   101
        SDL_GetRGBA(color, fmt, &_r, &_g, &_b, &_a);
slouken@3596
   102
        if (fmt->Rmask == 0x00FF0000) {
slouken@3596
   103
            if (!fmt->Amask) {
slouken@3596
   104
                AALINE(x1, y1, x2, y2,
slouken@3596
   105
                       DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_RGB888,
slouken@3596
   106
                       draw_end);
slouken@3596
   107
            } else {
slouken@3596
   108
                AALINE(x1, y1, x2, y2,
slouken@3596
   109
                       DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY_BLEND_ARGB8888,
slouken@3596
   110
                       draw_end);
slouken@3596
   111
            }
slouken@3596
   112
        } else {
slouken@3596
   113
            AALINE(x1, y1, x2, y2,
slouken@3596
   114
                   DRAW_FASTSETPIXELXY4, DRAW_SETPIXELXY4_BLEND_RGB,
slouken@3596
   115
                   draw_end);
slouken@3596
   116
        }
slouken@3596
   117
    }
slouken@3596
   118
}
slouken@3596
   119
slouken@3596
   120
typedef void (*DrawLineFunc) (SDL_Surface * dst,
slouken@3596
   121
                              int x1, int y1, int x2, int y2,
slouken@3596
   122
                              Uint32 color, SDL_bool draw_end);
slouken@3596
   123
slouken@3596
   124
static DrawLineFunc
slouken@3596
   125
SDL_CalculateDrawLineFunc(const SDL_PixelFormat * fmt)
slouken@3596
   126
{
slouken@3596
   127
    switch (fmt->BytesPerPixel) {
slouken@3596
   128
    case 1:
slouken@3596
   129
        if (fmt->BitsPerPixel < 8) {
slouken@3596
   130
            break;
slouken@3596
   131
        }
slouken@3596
   132
        return SDL_DrawLine1;
slouken@3596
   133
    case 2:
slouken@3596
   134
        return SDL_DrawLine2;
slouken@3596
   135
    case 4:
slouken@3596
   136
        return SDL_DrawLine4;
slouken@3596
   137
    }
slouken@3596
   138
    return NULL;
slouken@3596
   139
}
slouken@2890
   140
slouken@2901
   141
int
slouken@2888
   142
SDL_DrawLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color)
slouken@2888
   143
{
slouken@3596
   144
    DrawLineFunc func;
slouken@3596
   145
slouken@3536
   146
    if (!dst) {
slouken@3596
   147
        SDL_SetError("SDL_DrawLine(): Passed NULL destination surface");
slouken@3536
   148
        return -1;
slouken@3536
   149
    }
slouken@3536
   150
slouken@3596
   151
    func = SDL_CalculateDrawLineFunc(dst->format);
slouken@3596
   152
    if (!func) {
slouken@2888
   153
        SDL_SetError("SDL_DrawLine(): Unsupported surface format");
slouken@3536
   154
        return -1;
slouken@2888
   155
    }
slouken@2888
   156
slouken@2888
   157
    /* Perform clipping */
slouken@3536
   158
    /* FIXME: We don't actually want to clip, as it may change line slope */
slouken@2910
   159
    if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
slouken@3596
   160
        return 0;
slouken@2909
   161
    }
slouken@2888
   162
slouken@3596
   163
    func(dst, x1, y1, x2, y2, color, SDL_TRUE);
slouken@2890
   164
    return 0;
slouken@2888
   165
}
slouken@2888
   166
slouken@3536
   167
int
slouken@3536
   168
SDL_DrawLines(SDL_Surface * dst, const SDL_Point * points, int count,
slouken@3536
   169
              Uint32 color)
slouken@3536
   170
{
slouken@3536
   171
    int i;
slouken@3596
   172
    int x1, y1;
slouken@3596
   173
    int x2, y2;
slouken@3596
   174
    SDL_bool draw_end;
slouken@3596
   175
    DrawLineFunc func;
slouken@3536
   176
slouken@3536
   177
    if (!dst) {
slouken@3596
   178
        SDL_SetError("SDL_DrawLines(): Passed NULL destination surface");
slouken@3536
   179
        return -1;
slouken@3536
   180
    }
slouken@3536
   181
slouken@3596
   182
    func = SDL_CalculateDrawLineFunc(dst->format);
slouken@3596
   183
    if (!func) {
slouken@3596
   184
        SDL_SetError("SDL_DrawLines(): Unsupported surface format");
slouken@3536
   185
        return -1;
slouken@3536
   186
    }
slouken@3536
   187
slouken@3536
   188
    for (i = 1; i < count; ++i) {
slouken@3596
   189
        x1 = points[i-1].x;
slouken@3596
   190
        y1 = points[i-1].y;
slouken@3596
   191
        x2 = points[i].x;
slouken@3596
   192
        y2 = points[i].y;
slouken@3536
   193
slouken@3536
   194
        /* Perform clipping */
slouken@3536
   195
        /* FIXME: We don't actually want to clip, as it may change line slope */
slouken@3536
   196
        if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
slouken@3536
   197
            continue;
slouken@3536
   198
        }
slouken@3536
   199
slouken@3596
   200
        /* Draw the end if it was clipped */
slouken@3596
   201
        draw_end = (x2 != points[i].x || y2 != points[i].y);
slouken@3596
   202
slouken@3596
   203
        func(dst, x1, y1, x2, y2, color, draw_end);
slouken@3596
   204
    }
slouken@3596
   205
    if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
slouken@3596
   206
        SDL_DrawPoint(dst, points[count-1].x, points[count-1].y, color);
slouken@3536
   207
    }
slouken@3536
   208
    return 0;
slouken@3536
   209
}
slouken@3536
   210
slouken@2888
   211
/* vi: set ts=4 sw=4 expandtab: */