metal: Make line drawing match software renderer.

Partially fixes Bugzilla #2711.
This commit is contained in:
Ryan C. Gordon 2020-10-21 00:03:33 -04:00
parent c33f808354
commit ba36eb0437
1 changed files with 52 additions and 1 deletions

View File

@ -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;