From 83d600904b63d4ae7f7f6176cf978d31a53f3f55 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 30 Sep 2021 23:47:37 +0200 Subject: [PATCH] DirectFB: add partial support for RenderGeometry allow to fill triangles with color or texture but only uniform vertex color is handled (not per vertex color) --- src/video/directfb/SDL_DirectFB_render.c | 197 +++++++++++++++++++++++ 1 file changed, 197 insertions(+) diff --git a/src/video/directfb/SDL_DirectFB_render.c b/src/video/directfb/SDL_DirectFB_render.c index 744779a17..90adccb38 100644 --- a/src/video/directfb/SDL_DirectFB_render.c +++ b/src/video/directfb/SDL_DirectFB_render.c @@ -615,6 +615,64 @@ DirectFB_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const return 0; } +static int +DirectFB_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, + const float *xy, int xy_stride, const int *color, int color_stride, const float *uv, int uv_stride, + int num_vertices, const void *indices, int num_indices, int size_indices, + float scale_x, float scale_y) +{ + DirectFB_TextureData *texturedata = NULL; + int i; + int count = indices ? num_indices : num_vertices; + float *verts; + int sz = 2 + 4 + (texture ? 2 : 0); + + verts = (float *) SDL_AllocateRenderVertices(renderer, count * sz * sizeof (float), 0, &cmd->data.draw.first); + if (!verts) { + return -1; + } + + if (texture) { + texturedata = (DirectFB_TextureData *) texture->driverdata; + } + + cmd->data.draw.count = count; + size_indices = indices ? size_indices : 0; + + for (i = 0; i < count; i++) { + int j; + float *xy_; + SDL_Color col_; + if (size_indices == 4) { + j = ((const Uint32 *)indices)[i]; + } else if (size_indices == 2) { + j = ((const Uint16 *)indices)[i]; + } else if (size_indices == 1) { + j = ((const Uint8 *)indices)[i]; + } else { + j = i; + } + + xy_ = (float *)((char*)xy + j * xy_stride); + col_ = *(SDL_Color *)((char*)color + j * color_stride); + + *(verts++) = xy_[0] * scale_x; + *(verts++) = xy_[1] * scale_y; + + *(verts++) = col_.r; + *(verts++) = col_.g; + *(verts++) = col_.b; + *(verts++) = col_.a; + + if (texture) { + float *uv_ = (float *)((char*)uv + j * uv_stride); + *(verts++) = uv_[0]; + *(verts++) = uv_[1]; + } + } + return 0; +} + static int DirectFB_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count) { @@ -814,6 +872,144 @@ DirectFB_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void * break; } + + case SDL_RENDERCMD_GEOMETRY: { + const float *verts = (float *) (((Uint8 *) vertices) + cmd->data.draw.first); + SDL_Texture *texture = cmd->data.draw.texture; + const size_t count = cmd->data.draw.count; + + Uint8 save_r = cmd->data.draw.r; + Uint8 save_g = cmd->data.draw.g; + Uint8 save_b = cmd->data.draw.b; + Uint8 save_a = cmd->data.draw.a; + + int j; + for (j = 0; j < count; j += 3) + { + float x1, y1, r1, g1, b1, a1, u1, v1; + float x2, y2, r2, g2, b2, a2, u2, v2; + float x3, y3, r3, g3, b3, a3, u3, v3; + + x1 = *(verts++); + y1 = *(verts++); + r1 = *(verts++); + g1 = *(verts++); + b1 = *(verts++); + a1 = *(verts++); + if (texture) { + u1 = *(verts++); + v1 = *(verts++); + } + x2 = *(verts++); + y2 = *(verts++); + r2 = *(verts++); + g2 = *(verts++); + b2 = *(verts++); + a2 = *(verts++); + if (texture) { + u2 = *(verts++); + v2 = *(verts++); + } + x3 = *(verts++); + y3 = *(verts++); + r3 = *(verts++); + g3 = *(verts++); + b3 = *(verts++); + a3 = *(verts++); + if (texture) { + u3 = *(verts++); + v3 = *(verts++); + } + + + if (texture) { + DFBVertex vertices[3]; + + DirectFB_TextureData *texturedata = (DirectFB_TextureData *) texture->driverdata; + + DFBSurfaceBlittingFlags flags = 0; + + int r = (r1 + r2 + r3) / 3; + int g = (g1 + g2 + g3) / 3; + int b = (b1 + b2 + b3) / 3; + int a = (a1 + a2 + a3) / 3; + + + if (texturedata->isDirty) { + const SDL_Rect rect = { 0, 0, texture->w, texture->h }; + DirectFB_UpdateTexture(renderer, texture, &rect, texturedata->pixels, texturedata->pitch); + } + + if (a != 0xFF) { + flags |= DSBLIT_BLEND_COLORALPHA; + } + + if ((r & g & b) != 0xFF) { + flags |= DSBLIT_COLORIZE; + } + + destsurf->SetColor(destsurf, r, g, b, a); + + /* ???? flags |= DSBLIT_SRC_PREMULTCOLOR; */ + + SetBlendMode(data, texture->blendMode, texturedata); + + destsurf->SetBlittingFlags(destsurf, data->blitFlags | flags); + +#if (DFB_VERSION_ATLEAST(1,2,0)) + destsurf->SetRenderOptions(destsurf, texturedata->render_options); +#endif + + vertices[0].x = x1; + vertices[0].y = y1; + vertices[0].z = 0; + vertices[0].w = 0; + vertices[0].s = u1; + vertices[0].t = v1; + + vertices[1].x = x2; + vertices[1].y = y2; + vertices[1].z = 0; + vertices[1].w = 0; + vertices[1].s = u2; + vertices[1].t = v2; + + vertices[2].x = x3; + vertices[2].y = y3; + vertices[2].z = 0; + vertices[2].w = 0; + vertices[2].s = u3; + vertices[2].t = v3; + + destsurf->TextureTriangles(destsurf, texturedata->surface, vertices, NULL, 3, DTTF_LIST); + } else { + DFBTriangle tris; + tris.x1 = x1; + tris.y1 = y1; + tris.x2 = x2; + tris.y2 = y2; + tris.x3 = x3; + tris.y3 = y3; + + cmd->data.draw.r = (r1 + r2 + r3) / 3; + cmd->data.draw.g = (g1 + g2 + g3) / 3; + cmd->data.draw.b = (b1 + b2 + b3) / 3; + cmd->data.draw.a = (a1 + a2 + a3) / 3; + + PrepareDraw(renderer, cmd); + + destsurf->FillTriangles(destsurf, &tris, 1); + } + } + + cmd->data.draw.r = save_r; + cmd->data.draw.g = save_g; + cmd->data.draw.b = save_b; + cmd->data.draw.a = save_a; + break; + } + + case SDL_RENDERCMD_COPY_EX: break; /* unsupported */ @@ -984,6 +1180,7 @@ DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->QueueSetDrawColor = DirectFB_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ renderer->QueueDrawPoints = DirectFB_QueueDrawPoints; renderer->QueueDrawLines = DirectFB_QueueDrawPoints; /* lines and points queue vertices the same way. */ + renderer->QueueGeometry = DirectFB_QueueGeometry; renderer->QueueFillRects = DirectFB_QueueFillRects; renderer->QueueCopy = DirectFB_QueueCopy; renderer->QueueCopyEx = DirectFB_QueueCopyEx;