Added the hint SDL_HINT_RENDER_LINE_METHOD to select the line rendering method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 0e09086..1185f42 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -1060,6 +1060,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.
*
* This variable does not have any effect on the Direct3D 9 based renderer.
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 2f6fe83..a9251c2 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 1500b3a..ff38ed0 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;