diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 0e0908664..1185f4222 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -1059,6 +1059,19 @@ extern "C" { */ #define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING" +/** + * \brief A variable controlling how the 2D render API renders lines + * + * This variable can be set to the following values: + * "0" - Use the default line drawing method (Bresenham's line algorithm as of SDL 2.0.20) + * "1" - Use the driver point API using Bresenham's line algorithm (correct, draws many points) + * "2" - Use the driver line API (occasionally misses line endpoints based on hardware driver quirks, was the default before 2.0.20) + * "3" - Use the driver geometry API (correct, draws thicker diagonal lines) + * + * This variable should be set when the renderer is created. + */ +#define SDL_HINT_RENDER_LINE_METHOD "SDL_RENDER_LINE_METHOD" + /** * \brief A variable controlling whether to enable Direct3D 11+'s Debug Layer. * diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 2f6fe8345..a9251c274 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -896,6 +896,26 @@ void VerifyDrawQueueFunctions(const SDL_Renderer *renderer) SDL_assert(renderer->RunCommandQueue != NULL); } +static SDL_RenderLineMethod SDL_GetRenderLineMethod() +{ + const char *hint = SDL_GetHint(SDL_HINT_RENDER_LINE_METHOD); + + int method = 0; + if (hint) { + method = SDL_atoi(hint); + } + switch (method) { + case 1: + return SDL_RENDERLINEMETHOD_POINTS; + case 2: + return SDL_RENDERLINEMETHOD_LINES; + case 3: + return SDL_RENDERLINEMETHOD_GEOMETRY; + default: + return SDL_RENDERLINEMETHOD_POINTS; + } +} + SDL_Renderer * SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags) { @@ -1011,6 +1031,8 @@ SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags) renderer->relative_scaling = SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_SCALING, SDL_TRUE); + renderer->line_method = SDL_GetRenderLineMethod(); + if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN|SDL_WINDOW_MINIMIZED)) { renderer->hidden = SDL_TRUE; } else { @@ -1062,6 +1084,9 @@ SDL_CreateSoftwareRenderer(SDL_Surface * surface) /* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */ renderer->render_command_generation = 1; + /* Software renderer always uses line method, for speed */ + renderer->line_method = SDL_RENDERLINEMETHOD_LINES; + SDL_RenderSetViewport(renderer, NULL); } return renderer; @@ -2794,6 +2819,10 @@ static int plotLineLow(SDL_Renderer *renderer, float x0, float y0, float x1, flo SDL_FPoint *points = SDL_small_alloc(SDL_FPoint, count, &isstack); SDL_FPoint *tmp = points; + if (!points) { + return SDL_OutOfMemory(); + } + if (dy < 0) { yi = -1; dy = -dy; @@ -2837,6 +2866,10 @@ static int plotLineHigh(SDL_Renderer *renderer, float x0, float y0, float x1, fl SDL_FPoint *points = SDL_small_alloc(SDL_FPoint, count, &isstack); SDL_FPoint *tmp = points; + if (!points) { + return SDL_OutOfMemory(); + } + if (dx < 0) { xi = -1; dx = -dx; @@ -2999,8 +3032,6 @@ SDL_RenderDrawLinesF(SDL_Renderer * renderer, const SDL_FPoint * points, int count) { int retval = 0; - int use_renderpoints; - int use_rendergeometry; CHECK_RENDERER_MAGIC(renderer, -1); @@ -3018,12 +3049,9 @@ SDL_RenderDrawLinesF(SDL_Renderer * renderer, } #endif - use_renderpoints = 1; - use_rendergeometry = 1; - - if (use_renderpoints) { + if (renderer->line_method == SDL_RENDERLINEMETHOD_POINTS) { retval = RenderDrawLinesWithRectsF(renderer, points, count); - } else if (use_rendergeometry) { + } else if (renderer->line_method == SDL_RENDERLINEMETHOD_GEOMETRY) { SDL_bool isstack1; SDL_bool isstack2; const float scale_x = renderer->scale.x; diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 1500b3a35..ff38ed0dd 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -114,6 +114,14 @@ typedef struct SDL_VertexSolid } SDL_VertexSolid; +typedef enum +{ + SDL_RENDERLINEMETHOD_POINTS, + SDL_RENDERLINEMETHOD_LINES, + SDL_RENDERLINEMETHOD_GEOMETRY, +} SDL_RenderLineMethod; + + /* Define the SDL renderer structure */ struct SDL_Renderer { @@ -214,6 +222,9 @@ struct SDL_Renderer /* Whether or not to scale relative mouse motion */ SDL_bool relative_scaling; + /* The method of drawing lines */ + SDL_RenderLineMethod line_method; + /* Remainder from scaled relative motion */ float xrel; float yrel;