1
0
Эх сурвалжийг харах

metal: Make line drawing match software renderer.

Partially fixes Bugzilla #2711.
Ryan C. Gordon 4 жил өмнө
parent
commit
ba36eb0437

+ 52 - 1
src/render/metal/SDL_render_metal.m

@@ -1044,6 +1044,57 @@ METAL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL
     return 0;
 }
 
+static int
+METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
+{
+    SDL_assert(count >= 2);  /* should have been checked at the higher level. */
+
+    const size_t vertlen = (sizeof (float) * 2) * count;
+    float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
+    if (!verts) {
+        return -1;
+    }
+    cmd->data.draw.count = count;
+    SDL_memcpy(verts, points, vertlen);
+
+    /* If the line segment is completely horizontal or vertical,
+       make it one pixel longer, to satisfy the diamond-exit rule.
+       We should probably do this for diagonal lines too, but we'd have to
+       do some trigonometry to figure out the correct pixel and generally
+       when we have problems with pixel perfection, it's for straight lines
+       that are missing a pixel that frames something and not arbitrary
+       angles. Maybe !!! FIXME for later, though. */
+
+    points += count - 2;  /* update the last line. */
+    verts += count - 2;
+
+    float xstart = /*0.5f +*/ points[0].x;   /* 0.5f to get to the center of the pixel. */
+    float ystart = /*0.5f +*/ points[0].y;
+    float xend = /*0.5f +*/ points[1].x;
+    float yend = /*0.5f +*/ points[1].y;
+
+    if (xstart == xend) {  /* vertical line */
+        if (yend > ystart) {
+            yend += 1.0f;
+        } else {
+            ystart += 1.0f;
+        }
+    } else if (ystart == yend) {  /* horizontal line */
+        if (xend > xstart) {
+            xend += 1.0f;
+        } else {
+            xstart += 1.0f;
+        }
+    }
+
+    *(verts++) = xstart;
+    *(verts++) = ystart;
+    *(verts++) = xend;
+    *(verts++) = yend;
+
+    return 0;
+}
+
 static int
 METAL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
 {
@@ -1813,7 +1864,7 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
     renderer->QueueSetViewport = METAL_QueueSetViewport;
     renderer->QueueSetDrawColor = METAL_QueueSetDrawColor;
     renderer->QueueDrawPoints = METAL_QueueDrawPoints;
-    renderer->QueueDrawLines = METAL_QueueDrawPoints;  // lines and points queue the same way.
+    renderer->QueueDrawLines = METAL_QueueDrawLines;
     renderer->QueueFillRects = METAL_QueueFillRects;
     renderer->QueueCopy = METAL_QueueCopy;
     renderer->QueueCopyEx = METAL_QueueCopyEx;