From 18e4d9fed1b04f45c7af43cbda82b205fe01460d Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 8 Jan 2022 09:02:25 -0800
Subject: [PATCH] Re-enable line drawing path in render drivers
This is still used for scaled line drawing in RenderDrawLinesWithRects()
---
src/render/direct3d/SDL_render_d3d.c | 25 ++++++-
src/render/direct3d11/SDL_render_d3d11.c | 13 +++-
src/render/metal/SDL_render_metal.m | 59 +++++++++++++--
src/render/opengl/SDL_render_gl.c | 54 +++++++++++++-
src/render/opengles/SDL_render_gles.c | 53 +++++++++++++-
src/render/opengles2/SDL_render_gles2.c | 91 +++++++++++++++++++++++-
src/render/psp/SDL_render_psp.c | 18 ++++-
7 files changed, 301 insertions(+), 12 deletions(-)
diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c
index 006e012fca8..deb324c7d79 100644
--- a/src/render/direct3d/SDL_render_d3d.c
+++ b/src/render/direct3d/SDL_render_d3d.c
@@ -1207,8 +1207,30 @@ D3D_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
break;
}
- case SDL_RENDERCMD_DRAW_LINES: /* unused */
+ case SDL_RENDERCMD_DRAW_LINES: {
+ const size_t count = cmd->data.draw.count;
+ const size_t first = cmd->data.draw.first;
+ const Vertex *verts = (Vertex *) (((Uint8 *) vertices) + first);
+
+ /* DirectX 9 has the same line rasterization semantics as GDI,
+ so we need to close the endpoint of the line with a second draw call. */
+ const SDL_bool close_endpoint = ((count == 2) || (verts[0].x != verts[count-1].x) || (verts[0].y != verts[count-1].y));
+
+ SetDrawState(data, cmd);
+
+ if (vbo) {
+ IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_LINESTRIP, (UINT) (first / sizeof (Vertex)), (UINT) (count - 1));
+ if (close_endpoint) {
+ IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_POINTLIST, (UINT) ((first / sizeof (Vertex)) + (count - 1)), 1);
+ }
+ } else {
+ IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, (UINT) (count - 1), verts, sizeof (Vertex));
+ if (close_endpoint) {
+ IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1, &verts[count-1], sizeof (Vertex));
+ }
+ }
break;
+ }
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
@@ -1545,6 +1567,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->QueueSetViewport = D3D_QueueSetViewport;
renderer->QueueSetDrawColor = D3D_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = D3D_QueueDrawPoints;
+ renderer->QueueDrawLines = D3D_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = D3D_QueueGeometry;
renderer->RunCommandQueue = D3D_RunCommandQueue;
renderer->RenderReadPixels = D3D_RenderReadPixels;
diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c
index fb047a24b64..f8d8c7cf55a 100644
--- a/src/render/direct3d11/SDL_render_d3d11.c
+++ b/src/render/direct3d11/SDL_render_d3d11.c
@@ -2122,8 +2122,18 @@ D3D11_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
break;
}
- case SDL_RENDERCMD_DRAW_LINES: /* unused */
+ case SDL_RENDERCMD_DRAW_LINES: {
+ const size_t count = cmd->data.draw.count;
+ const size_t first = cmd->data.draw.first;
+ const size_t start = first / sizeof (VertexPositionColor);
+ const VertexPositionColor *verts = (VertexPositionColor *) (((Uint8 *) vertices) + first);
+ D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
+ D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, start, count);
+ if (verts[0].pos.x != verts[count - 1].pos.x || verts[0].pos.y != verts[count - 1].pos.y) {
+ D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start + (count-1), 1);
+ }
break;
+ }
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
@@ -2376,6 +2386,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->QueueSetViewport = D3D11_QueueSetViewport;
renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = D3D11_QueueDrawPoints;
+ renderer->QueueDrawLines = D3D11_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = D3D11_QueueGeometry;
renderer->RunCommandQueue = D3D11_RunCommandQueue;
renderer->RenderReadPixels = D3D11_RenderReadPixels;
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index 742bd313437..e093fd4d8bf 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -1107,6 +1107,56 @@ - (void)dealloc
return 0;
}
+static int
+METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
+{
+ const SDL_Color color = {
+ cmd->data.draw.r,
+ cmd->data.draw.g,
+ cmd->data.draw.b,
+ cmd->data.draw.a
+ };
+
+ SDL_assert(count >= 2); /* should have been checked at the higher level. */
+
+ const size_t vertlen = (2 * sizeof (float) + sizeof (SDL_Color)) * count;
+ float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
+ if (!verts) {
+ return -1;
+ }
+ cmd->data.draw.count = count;
+
+ for (int i = 0; i < count; i++, points++) {
+ *(verts++) = points->x;
+ *(verts++) = points->y;
+ *((SDL_Color *)verts++) = color;
+ }
+
+ /* 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 -= 2; /* update the last line. */
+ verts -= 2 + 1;
+
+ const float xstart = points[0].x;
+ const float ystart = points[0].y;
+ const float xend = points[1].x;
+ const float yend = points[1].y;
+
+ if (ystart == yend) { /* horizontal line */
+ verts[0] += (xend > xstart) ? 1.0f : -1.0f;
+ } else if (xstart == xend) { /* vertical line */
+ verts[1] += (yend > ystart) ? 1.0f : -1.0f;
+ }
+
+ return 0;
+}
+
static int
METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride,
@@ -1372,17 +1422,15 @@ - (void)dealloc
break;
}
- case SDL_RENDERCMD_DRAW_POINTS: {
+ case SDL_RENDERCMD_DRAW_POINTS:
+ case SDL_RENDERCMD_DRAW_LINES: {
const size_t count = cmd->data.draw.count;
- const MTLPrimitiveType primtype = MTLPrimitiveTypePoint;
+ const MTLPrimitiveType primtype = (cmd->command == SDL_RENDERCMD_DRAW_POINTS) ? MTLPrimitiveTypePoint : MTLPrimitiveTypeLineStrip;
if (SetDrawState(renderer, cmd, SDL_METAL_FRAGMENT_SOLID, CONSTANTS_OFFSET_HALF_PIXEL_TRANSFORM, mtlbufvertex, &statecache)) {
[data.mtlcmdencoder drawPrimitives:primtype vertexStart:0 vertexCount:count];
}
break;
}
-
- case SDL_RENDERCMD_DRAW_LINES: /* unused */
- break;
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
@@ -1838,6 +1886,7 @@ in case we want to use it later (recreating the renderer)
renderer->QueueSetViewport = METAL_QueueSetViewport;
renderer->QueueSetDrawColor = METAL_QueueSetDrawColor;
renderer->QueueDrawPoints = METAL_QueueDrawPoints;
+ renderer->QueueDrawLines = METAL_QueueDrawLines;
renderer->QueueGeometry = METAL_QueueGeometry;
renderer->RunCommandQueue = METAL_RunCommandQueue;
renderer->RenderReadPixels = METAL_RenderReadPixels;
diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c
index 624329995ad..3b3d739f67d 100644
--- a/src/render/opengl/SDL_render_gl.c
+++ b/src/render/opengl/SDL_render_gl.c
@@ -941,6 +941,47 @@ GL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FP
return 0;
}
+static int
+GL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
+{
+ int i;
+ GLfloat prevx, prevy;
+ const size_t vertlen = (sizeof (GLfloat) * 2) * count;
+ GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
+
+ if (!verts) {
+ return -1;
+ }
+ cmd->data.draw.count = count;
+
+ /* 0.5f offset to hit the center of the pixel. */
+ prevx = 0.5f + points->x;
+ prevy = 0.5f + points->y;
+ *(verts++) = prevx;
+ *(verts++) = prevy;
+
+ /* bump the end of each line segment out a quarter of a pixel, to provoke
+ the diamond-exit rule. Without this, you won't just drop the last
+ pixel of the last line segment, but you might also drop pixels at the
+ edge of any given line segment along the way too. */
+ for (i = 1; i < count; i++) {
+ const GLfloat xstart = prevx;
+ const GLfloat ystart = prevy;
+ const GLfloat xend = points[i].x + 0.5f; /* 0.5f to hit pixel center. */
+ const GLfloat yend = points[i].y + 0.5f;
+ /* bump a little in the direction we are moving in. */
+ const GLfloat deltax = xend - xstart;
+ const GLfloat deltay = yend - ystart;
+ const GLfloat angle = SDL_atan2f(deltay, deltax);
+ prevx = xend + (SDL_cosf(angle) * 0.25f);
+ prevy = yend + (SDL_sinf(angle) * 0.25f);
+ *(verts++) = prevx;
+ *(verts++) = prevy;
+ }
+
+ return 0;
+}
+
static int
GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride,
@@ -1070,6 +1111,7 @@ SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader
}
vertex_array = cmd->command == SDL_RENDERCMD_DRAW_POINTS
+ || cmd->command == SDL_RENDERCMD_DRAW_LINES
|| cmd->command == SDL_RENDERCMD_GEOMETRY;
color_array = cmd->command == SDL_RENDERCMD_GEOMETRY;
texture_array = cmd->data.draw.texture != NULL;
@@ -1244,8 +1286,17 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
break;
}
- case SDL_RENDERCMD_DRAW_LINES: /* unused */
+ case SDL_RENDERCMD_DRAW_LINES: {
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ const size_t count = cmd->data.draw.count;
+ SDL_assert(count >= 2);
+ SetDrawState(data, cmd, SHADER_SOLID);
+
+ /* SetDrawState handles glEnableClientState. */
+ data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, verts);
+ data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
break;
+ }
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
@@ -1643,6 +1694,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->QueueSetViewport = GL_QueueSetViewport;
renderer->QueueSetDrawColor = GL_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = GL_QueueDrawPoints;
+ renderer->QueueDrawLines = GL_QueueDrawLines;
renderer->QueueGeometry = GL_QueueGeometry;
renderer->RunCommandQueue = GL_RunCommandQueue;
renderer->RenderReadPixels = GL_RenderReadPixels;
diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c
index 21a3150d1f1..a6b58f2d74c 100644
--- a/src/render/opengles/SDL_render_gles.c
+++ b/src/render/opengles/SDL_render_gles.c
@@ -560,6 +560,47 @@ GLES_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
return 0;
}
+static int
+GLES_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
+{
+ int i;
+ GLfloat prevx, prevy;
+ const size_t vertlen = (sizeof (GLfloat) * 2) * count;
+ GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
+
+ if (!verts) {
+ return -1;
+ }
+ cmd->data.draw.count = count;
+
+ /* 0.5f offset to hit the center of the pixel. */
+ prevx = 0.5f + points->x;
+ prevy = 0.5f + points->y;
+ *(verts++) = prevx;
+ *(verts++) = prevy;
+
+ /* bump the end of each line segment out a quarter of a pixel, to provoke
+ the diamond-exit rule. Without this, you won't just drop the last
+ pixel of the last line segment, but you might also drop pixels at the
+ edge of any given line segment along the way too. */
+ for (i = 1; i < count; i++) {
+ const GLfloat xstart = prevx;
+ const GLfloat ystart = prevy;
+ const GLfloat xend = points[i].x + 0.5f; /* 0.5f to hit pixel center. */
+ const GLfloat yend = points[i].y + 0.5f;
+ /* bump a little in the direction we are moving in. */
+ const GLfloat deltax = xend - xstart;
+ const GLfloat deltay = yend - ystart;
+ const GLfloat angle = SDL_atan2f(deltay, deltax);
+ prevx = xend + (SDL_cosf(angle) * 0.25f);
+ prevy = yend + (SDL_sinf(angle) * 0.25f);
+ *(verts++) = prevx;
+ *(verts++) = prevy;
+ }
+
+ return 0;
+}
+
static int
GLES_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride,
@@ -809,8 +850,15 @@ GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vert
break;
}
- case SDL_RENDERCMD_DRAW_LINES: /* unused */
- break;
+ case SDL_RENDERCMD_DRAW_LINES: {
+ const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+ const size_t count = cmd->data.draw.count;
+ SDL_assert(count >= 2);
+ SetDrawState(data, cmd);
+ data->glVertexPointer(2, GL_FLOAT, 0, verts);
+ data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
+ break;
+ }
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
@@ -1074,6 +1122,7 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->QueueSetViewport = GLES_QueueSetViewport;
renderer->QueueSetDrawColor = GLES_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = GLES_QueueDrawPoints;
+ renderer->QueueDrawLines = GLES_QueueDrawLines;
renderer->QueueGeometry = GLES_QueueGeometry;
renderer->RunCommandQueue = GLES_RunCommandQueue;
renderer->RenderReadPixels = GLES_RenderReadPixels;
diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c
index cbd99c54c8c..3011c2e12d3 100644
--- a/src/render/opengles2/SDL_render_gles2.c
+++ b/src/render/opengles2/SDL_render_gles2.c
@@ -692,6 +692,63 @@ GLES2_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL
return 0;
}
+static int
+GLES2_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
+{
+ const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
+ int i;
+ GLfloat prevx, prevy;
+ SDL_VertexSolid *verts = (SDL_VertexSolid *) SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
+ SDL_Color color;
+ color.r = cmd->data.draw.r;
+ color.g = cmd->data.draw.g;
+ color.b = cmd->data.draw.b;
+ color.a = cmd->data.draw.a;
+
+ if (!verts) {
+ return -1;
+ }
+
+ if (colorswap) {
+ Uint8 r = color.r;
+ color.r = color.b;
+ color.b = r;
+ }
+
+ cmd->data.draw.count = count;
+
+ /* 0.5f offset to hit the center of the pixel. */
+ prevx = 0.5f + points->x;
+ prevy = 0.5f + points->y;
+ verts->position.x = prevx;
+ verts->position.y = prevy;
+ verts->color = color;
+ verts++;
+
+ /* bump the end of each line segment out a quarter of a pixel, to provoke
+ the diamond-exit rule. Without this, you won't just drop the last
+ pixel of the last line segment, but you might also drop pixels at the
+ edge of any given line segment along the way too. */
+ for (i = 1; i < count; i++) {
+ const GLfloat xstart = prevx;
+ const GLfloat ystart = prevy;
+ const GLfloat xend = points[i].x + 0.5f; /* 0.5f to hit pixel center. */
+ const GLfloat yend = points[i].y + 0.5f;
+ /* bump a little in the direction we are moving in. */
+ const GLfloat deltax = xend - xstart;
+ const GLfloat deltay = yend - ystart;
+ const GLfloat angle = SDL_atan2f(deltay, deltax);
+ prevx = xend + (SDL_cosf(angle) * 0.25f);
+ prevy = yend + (SDL_sinf(angle) * 0.25f);
+ verts->position.x = prevx;
+ verts->position.y = prevy;
+ verts->color = color;
+ verts++;
+ }
+
+ return 0;
+}
+
static int
GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
const float *xy, int xy_stride, const SDL_Color *color, int color_stride, const float *uv, int uv_stride,
@@ -1126,8 +1183,39 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
case SDL_RENDERCMD_COPY_EX: /* unused */
break;
- case SDL_RENDERCMD_DRAW_LINES: /* unused */
+ case SDL_RENDERCMD_DRAW_LINES: {
+ if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
+ size_t count = cmd->data.draw.count;
+ if (count > 2) {
+ /* joined lines cannot be grouped */
+ data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)count);
+ } else {
+ /* let's group non joined lines */
+ SDL_RenderCommand *finalcmd = cmd;
+ SDL_RenderCommand *nextcmd = cmd->next;
+ SDL_BlendMode thisblend = cmd->data.draw.blend;
+
+ while (nextcmd != NULL) {
+ const SDL_RenderCommandType nextcmdtype = nextcmd->command;
+ if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
+ break; /* can't go any further on this draw call, different render command up next. */
+ } else if (nextcmd->data.draw.count != 2) {
+ break; /* can't go any further on this draw call, those are joined lines */
+ } else if (nextcmd->data.draw.blend != thisblend) {
+ break; /* can't go any further on this draw call, different blendmode copy up next. */
+ } else {
+ finalcmd = nextcmd; /* we can combine copy operations here. Mark this one as the furthest okay command. */
+ count += cmd->data.draw.count;
+ }
+ nextcmd = nextcmd->next;
+ }
+
+ data->glDrawArrays(GL_LINES, 0, (GLsizei)count);
+ cmd = finalcmd; /* skip any copy commands we just combined in here. */
+ }
+ }
break;
+ }
case SDL_RENDERCMD_DRAW_POINTS:
case SDL_RENDERCMD_GEOMETRY: {
@@ -2007,6 +2095,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueSetViewport = GLES2_QueueSetViewport;
renderer->QueueSetDrawColor = GLES2_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = GLES2_QueueDrawPoints;
+ renderer->QueueDrawLines = GLES2_QueueDrawLines;
renderer->QueueGeometry = GLES2_QueueGeometry;
renderer->RunCommandQueue = GLES2_RunCommandQueue;
renderer->RenderReadPixels = GLES2_RenderReadPixels;
diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c
index 51feabc0b75..e7fca22a51d 100644
--- a/src/render/psp/SDL_render_psp.c
+++ b/src/render/psp/SDL_render_psp.c
@@ -1120,8 +1120,23 @@ PSP_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
break;
}
- case SDL_RENDERCMD_DRAW_LINES: /* unused */
+ case SDL_RENDERCMD_DRAW_LINES: {
+ const size_t count = cmd->data.draw.count;
+ const VertV *verts = (VertV *) (gpumem + cmd->data.draw.first);
+ const Uint8 r = cmd->data.draw.r;
+ const Uint8 g = cmd->data.draw.g;
+ const Uint8 b = cmd->data.draw.b;
+ const Uint8 a = cmd->data.draw.a;
+ PSP_BlendState state = {
+ .color = GU_RGBA(r,g,b,a),
+ .texture = NULL,
+ .mode = cmd->data.draw.blend,
+ .shadeModel = GU_FLAT
+ };
+ PSP_SetBlendState(data, &state);
+ sceGuDrawArray(GU_LINE_STRIP, GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, verts);
break;
+ }
case SDL_RENDERCMD_FILL_RECTS: {
const size_t count = cmd->data.draw.count;
@@ -1324,6 +1339,7 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->QueueSetViewport = PSP_QueueSetViewport;
renderer->QueueSetDrawColor = PSP_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = PSP_QueueDrawPoints;
+ renderer->QueueDrawLines = PSP_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = PSP_QueueGeometry;
renderer->QueueFillRects = PSP_QueueFillRects;
renderer->QueueCopy = PSP_QueueCopy;