early-access version 2281

This commit is contained in:
pineappleEA
2021-12-07 02:20:09 +01:00
parent c2ae6d480a
commit c4fa174d53
591 changed files with 36978 additions and 18653 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ struct SDL_Texture
int modMode; /**< The texture modulation mode */
SDL_BlendMode blendMode; /**< The texture blend mode */
SDL_ScaleMode scaleMode; /**< The texture scale mode */
Uint8 r, g, b, a; /**< Texture modulation values */
SDL_Color color; /**< Texture modulation values */
SDL_Renderer *renderer;
@@ -58,6 +58,7 @@ struct SDL_Texture
Uint32 last_command_generation; /* last command queue generation this texture was in. */
void *driverdata; /**< Driver specific texture representation */
void *userdata;
SDL_Texture *prev;
SDL_Texture *next;
@@ -74,7 +75,8 @@ typedef enum
SDL_RENDERCMD_DRAW_LINES,
SDL_RENDERCMD_FILL_RECTS,
SDL_RENDERCMD_COPY,
SDL_RENDERCMD_COPY_EX
SDL_RENDERCMD_COPY_EX,
SDL_RENDERCMD_GEOMETRY
} SDL_RenderCommandType;
typedef struct SDL_RenderCommand
@@ -127,6 +129,11 @@ struct SDL_Renderer
int (*QueueCopyEx) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
int (*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);
int (*RunCommandQueue) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
int (*UpdateTexture) (SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
@@ -154,6 +161,8 @@ struct SDL_Renderer
void (*DestroyRenderer) (SDL_Renderer * renderer);
int (*SetVSync) (SDL_Renderer * renderer, int vsync);
int (*GL_BindTexture) (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
int (*GL_UnbindTexture) (SDL_Renderer * renderer, SDL_Texture *texture);
@@ -207,7 +216,7 @@ struct SDL_Renderer
SDL_Texture *target;
SDL_mutex *target_mutex;
Uint8 r, g, b, a; /**< Color for drawing operations values */
SDL_Color color; /**< Color for drawing operations values */
SDL_BlendMode blendMode; /**< The drawing blend mode */
SDL_bool always_batch;

View File

@@ -51,7 +51,6 @@ typedef struct
SDL_bool cliprect_enabled_dirty;
SDL_Rect cliprect;
SDL_bool cliprect_dirty;
SDL_bool is_copy_ex;
LPDIRECT3DPIXELSHADER9 shader;
} D3D_DrawStateCache;
@@ -833,190 +832,55 @@ D3D_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_F
}
static int
D3D_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
D3D_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)
{
const DWORD color = D3DCOLOR_ARGB(cmd->data.draw.a, cmd->data.draw.r, cmd->data.draw.g, cmd->data.draw.b);
const size_t vertslen = count * sizeof (Vertex) * 4;
Vertex *verts = (Vertex *) SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first);
int i;
int count = indices ? num_indices : num_vertices;
Vertex *verts = (Vertex *) SDL_AllocateRenderVertices(renderer, count * sizeof (Vertex), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
SDL_memset(verts, '\0', vertslen);
cmd->data.draw.count = count;
size_indices = indices ? size_indices : 0;
for (i = 0; i < count; i++) {
const SDL_FRect *rect = &rects[i];
const float minx = rect->x;
const float maxx = rect->x + rect->w;
const float miny = rect->y;
const float maxy = rect->y + rect->h;
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;
}
verts->x = minx;
verts->y = miny;
verts->color = color;
verts++;
xy_ = (float *)((char*)xy + j * xy_stride);
col_ = *(SDL_Color *)((char*)color + j * color_stride);
verts->x = maxx;
verts->y = miny;
verts->color = color;
verts++;
verts->x = xy_[0] * scale_x - 0.5f;
verts->y = xy_[1] * scale_y - 0.5f;
verts->z = 0.0f;
verts->color = D3DCOLOR_ARGB(col_.a, col_.r, col_.g, col_.b);
verts->x = maxx;
verts->y = maxy;
verts->color = color;
verts++;
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
verts->u = uv_[0];
verts->v = uv_[1];
} else {
verts->u = 0.0f;
verts->v = 0.0f;
}
verts->x = minx;
verts->y = maxy;
verts->color = color;
verts++;
verts += 1;
}
return 0;
}
static int
D3D_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
const DWORD color = D3DCOLOR_ARGB(cmd->data.draw.a, cmd->data.draw.r, cmd->data.draw.g, cmd->data.draw.b);
float minx, miny, maxx, maxy;
float minu, maxu, minv, maxv;
const size_t vertslen = sizeof (Vertex) * 4;
Vertex *verts = (Vertex *) SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
minx = dstrect->x - 0.5f;
miny = dstrect->y - 0.5f;
maxx = dstrect->x + dstrect->w - 0.5f;
maxy = dstrect->y + dstrect->h - 0.5f;
minu = (float) srcrect->x / texture->w;
maxu = (float) (srcrect->x + srcrect->w) / texture->w;
minv = (float) srcrect->y / texture->h;
maxv = (float) (srcrect->y + srcrect->h) / texture->h;
verts->x = minx;
verts->y = miny;
verts->z = 0.0f;
verts->color = color;
verts->u = minu;
verts->v = minv;
verts++;
verts->x = maxx;
verts->y = miny;
verts->z = 0.0f;
verts->color = color;
verts->u = maxu;
verts->v = minv;
verts++;
verts->x = maxx;
verts->y = maxy;
verts->z = 0.0f;
verts->color = color;
verts->u = maxu;
verts->v = maxv;
verts++;
verts->x = minx;
verts->y = maxy;
verts->z = 0.0f;
verts->color = color;
verts->u = minu;
verts->v = maxv;
verts++;
return 0;
}
static int
D3D_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
const DWORD color = D3DCOLOR_ARGB(cmd->data.draw.a, cmd->data.draw.r, cmd->data.draw.g, cmd->data.draw.b);
float minx, miny, maxx, maxy;
float minu, maxu, minv, maxv;
const size_t vertslen = sizeof (Vertex) * 5;
Vertex *verts = (Vertex *) SDL_AllocateRenderVertices(renderer, vertslen, 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
minx = -center->x;
maxx = dstrect->w - center->x;
miny = -center->y;
maxy = dstrect->h - center->y;
if (flip & SDL_FLIP_HORIZONTAL) {
minu = (float) (srcquad->x + srcquad->w) / texture->w;
maxu = (float) srcquad->x / texture->w;
} else {
minu = (float) srcquad->x / texture->w;
maxu = (float) (srcquad->x + srcquad->w) / texture->w;
}
if (flip & SDL_FLIP_VERTICAL) {
minv = (float) (srcquad->y + srcquad->h) / texture->h;
maxv = (float) srcquad->y / texture->h;
} else {
minv = (float) srcquad->y / texture->h;
maxv = (float) (srcquad->y + srcquad->h) / texture->h;
}
verts->x = minx;
verts->y = miny;
verts->z = 0.0f;
verts->color = color;
verts->u = minu;
verts->v = minv;
verts++;
verts->x = maxx;
verts->y = miny;
verts->z = 0.0f;
verts->color = color;
verts->u = maxu;
verts->v = minv;
verts++;
verts->x = maxx;
verts->y = maxy;
verts->z = 0.0f;
verts->color = color;
verts->u = maxu;
verts->v = maxv;
verts++;
verts->x = minx;
verts->y = maxy;
verts->z = 0.0f;
verts->color = color;
verts->u = minu;
verts->v = maxv;
verts++;
verts->x = dstrect->x + center->x - 0.5f; /* X translation */
verts->y = dstrect->y + center->y - 0.5f; /* Y translation */
verts->z = (float)(M_PI * (float) angle / 180.0f); /* rotation */
verts->color = 0;
verts->u = 0.0f;
verts->v = 0.0f;
verts++;
return 0;
}
@@ -1119,8 +983,6 @@ SetupTextureState(D3D_RenderData *data, SDL_Texture * texture, LPDIRECT3DPIXELSH
static int
SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
{
const SDL_bool was_copy_ex = data->drawstate.is_copy_ex;
const SDL_bool is_copy_ex = (cmd->command == SDL_RENDERCMD_COPY_EX);
SDL_Texture *texture = cmd->data.draw.texture;
const SDL_BlendMode blend = cmd->data.draw.blend;
@@ -1179,14 +1041,6 @@ SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
data->drawstate.blend = blend;
}
if (is_copy_ex != was_copy_ex) {
if (!is_copy_ex) { /* SDL_RENDERCMD_COPY_EX will set this, we only want to reset it here if necessary. */
const Float4X4 d3dmatrix = MatrixIdentity();
IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*) &d3dmatrix);
}
data->drawstate.is_copy_ex = is_copy_ex;
}
if (data->drawstate.viewport_dirty) {
const SDL_Rect *viewport = &data->drawstate.viewport;
const D3DVIEWPORT9 d3dviewport = { viewport->x, viewport->y, viewport->w, viewport->h, 0.0f, 1.0f };
@@ -1231,7 +1085,6 @@ D3D_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
const int vboidx = data->currentVertexBuffer;
IDirect3DVertexBuffer9 *vbo = NULL;
const SDL_bool istarget = renderer->target != NULL;
size_t i;
if (D3D_ActivateRenderer(renderer) < 0) {
return -1;
@@ -1377,58 +1230,24 @@ D3D_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
break;
}
case SDL_RENDERCMD_FILL_RECTS: {
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
case SDL_RENDERCMD_COPY: /* unused */
break;
case SDL_RENDERCMD_COPY_EX: /* unused */
break;
case SDL_RENDERCMD_GEOMETRY: {
const size_t count = cmd->data.draw.count;
const size_t first = cmd->data.draw.first;
SetDrawState(data, cmd);
if (vbo) {
size_t offset = 0;
for (i = 0; i < count; ++i, offset += 4) {
IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_TRIANGLEFAN, (UINT) ((first / sizeof (Vertex)) + offset), 2);
}
IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_TRIANGLELIST, (UINT) (first / sizeof (Vertex)), (UINT) count / 3);
} else {
const Vertex *verts = (Vertex *) (((Uint8 *) vertices) + first);
for (i = 0; i < count; ++i, verts += 4) {
IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2, verts, sizeof (Vertex));
}
}
break;
}
case SDL_RENDERCMD_COPY: {
const size_t count = cmd->data.draw.count;
const size_t first = cmd->data.draw.first;
SetDrawState(data, cmd);
if (vbo) {
size_t offset = 0;
for (i = 0; i < count; ++i, offset += 4) {
IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_TRIANGLEFAN, (UINT) ((first / sizeof (Vertex)) + offset), 2);
}
} else {
const Vertex *verts = (Vertex *) (((Uint8 *) vertices) + first);
for (i = 0; i < count; ++i, verts += 4) {
IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2, verts, sizeof (Vertex));
}
}
break;
}
case SDL_RENDERCMD_COPY_EX: {
const size_t first = cmd->data.draw.first;
const Vertex *verts = (Vertex *) (((Uint8 *) vertices) + first);
const Vertex *transvert = verts + 4;
const float translatex = transvert->x;
const float translatey = transvert->y;
const float rotation = transvert->z;
const Float4X4 d3dmatrix = MatrixMultiply(MatrixRotationZ(rotation), MatrixTranslation(translatex, translatey, 0));
SetDrawState(data, cmd);
IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&d3dmatrix);
if (vbo) {
IDirect3DDevice9_DrawPrimitive(data->device, D3DPT_TRIANGLEFAN, (UINT) (first / sizeof (Vertex)), 2);
} else {
IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2, verts, sizeof (Vertex));
const Vertex* verts = (Vertex*)(((Uint8*)vertices) + first);
IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLELIST, (UINT) count / 3, verts, sizeof(Vertex));
}
break;
}
@@ -1606,6 +1425,12 @@ D3D_Reset(SDL_Renderer * renderer)
SDL_Texture *texture;
int i;
/* Cancel any scene that we've started */
if (!data->beginScene) {
IDirect3DDevice9_EndScene(data->device);
data->beginScene = SDL_TRUE;
}
/* Release the default render target before reset */
if (data->defaultRenderTarget) {
IDirect3DSurface9_Release(data->defaultRenderTarget);
@@ -1660,7 +1485,6 @@ D3D_Reset(SDL_Renderer * renderer)
data->drawstate.texture = NULL;
data->drawstate.shader = NULL;
data->drawstate.blend = SDL_BLENDMODE_INVALID;
data->drawstate.is_copy_ex = SDL_FALSE;
IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, (D3DMATRIX*)&d3dmatrix);
/* Let the application know that render targets were reset */
@@ -1673,6 +1497,24 @@ D3D_Reset(SDL_Renderer * renderer)
return 0;
}
static int
D3D_SetVSync(SDL_Renderer * renderer, const int vsync)
{
D3D_RenderData *data = renderer->driverdata;
if (vsync) {
data->pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
data->pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
if (D3D_Reset(renderer) < 0) {
/* D3D_Reset will call SDL_SetError() */
return -1;
}
return 0;
}
SDL_Renderer *
D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
{
@@ -1724,14 +1566,13 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
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->QueueFillRects = D3D_QueueFillRects;
renderer->QueueCopy = D3D_QueueCopy;
renderer->QueueCopyEx = D3D_QueueCopyEx;
renderer->QueueGeometry = D3D_QueueGeometry;
renderer->RunCommandQueue = D3D_RunCommandQueue;
renderer->RenderReadPixels = D3D_RenderReadPixels;
renderer->RenderPresent = D3D_RenderPresent;
renderer->DestroyTexture = D3D_DestroyTexture;
renderer->DestroyRenderer = D3D_DestroyRenderer;
renderer->SetVSync = D3D_SetVSync;
renderer->info = D3D_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->driverdata = data;
@@ -1816,9 +1657,6 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
IDirect3DDevice9_GetDeviceCaps(data->device, &caps);
renderer->info.max_texture_width = caps.MaxTextureWidth;
renderer->info.max_texture_height = caps.MaxTextureHeight;
if (caps.NumSimultaneousRTs >= 2) {
renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
}
if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) {
data->enableSeparateAlphaBlend = SDL_TRUE;

View File

@@ -770,7 +770,11 @@ D3D11_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
if (usingXAML) {
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
} else {
swapChainDesc.Scaling = DXGI_SCALING_NONE;
if (WIN_IsWindows8OrGreater()) {
swapChainDesc.Scaling = DXGI_SCALING_NONE;
} else {
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
}
}
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; /* All Windows Store apps must use this SwapEffect. */
#endif
@@ -953,11 +957,13 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
*
* TODO, WinRT: reexamine the docs for IDXGISwapChain1::SetRotation, see if might be available, usable, and prudent-to-call on WinPhone 8.1
*/
if (data->swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
result = IDXGISwapChain1_SetRotation(data->swapChain, data->rotation);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain1::SetRotation"), result);
goto done;
if (WIN_IsWindows8OrGreater()) {
if (data->swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
result = IDXGISwapChain1_SetRotation(data->swapChain, data->rotation);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain1::SetRotation"), result);
goto done;
}
}
}
#endif
@@ -1634,238 +1640,61 @@ D3D11_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL
}
static int
D3D11_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
D3D11_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)
{
VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, count * 4 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
const float r = (float)(cmd->data.draw.r / 255.0f);
const float g = (float)(cmd->data.draw.g / 255.0f);
const float b = (float)(cmd->data.draw.b / 255.0f);
const float a = (float)(cmd->data.draw.a / 255.0f);
int i;
int count = indices ? num_indices : num_vertices;
VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, count * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
size_indices = indices ? size_indices : 0;
for (i = 0; i < count; i++) {
verts->pos.x = rects[i].x;
verts->pos.y = rects[i].y;
verts->pos.z = 0.0f;
verts->tex.x = 0.0f;
verts->tex.y = 0.0f;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts++;
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;
}
verts->pos.x = rects[i].x;
verts->pos.y = rects[i].y + rects[i].h;
verts->pos.z = 0.0f;
verts->tex.x = 0.0f;
verts->tex.y = 0.0f;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts++;
xy_ = (float *)((char*)xy + j * xy_stride);
col_ = *(SDL_Color *)((char*)color + j * color_stride);
verts->pos.x = rects[i].x + rects[i].w;
verts->pos.y = rects[i].y;
verts->pos.x = xy_[0] * scale_x;
verts->pos.y = xy_[1] * scale_y;
verts->pos.z = 0.0f;
verts->tex.x = 0.0f;
verts->tex.y = 0.0f;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts++;
verts->color.x = col_.r / 255.0f;
verts->color.y = col_.g / 255.0f;
verts->color.z = col_.b / 255.0f;
verts->color.w = col_.a / 255.0f;
verts->pos.x = rects[i].x + rects[i].w;
verts->pos.y = rects[i].y + rects[i].h;
verts->pos.z = 0.0f;
verts->tex.x = 0.0f;
verts->tex.y = 0.0f;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts++;
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
verts->tex.x = uv_[0];
verts->tex.y = uv_[1];
} else {
verts->tex.x = 0.0f;
verts->tex.y = 0.0f;
}
verts += 1;
}
return 0;
}
static int
D3D11_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, 4 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
const float r = (float)(cmd->data.draw.r / 255.0f);
const float g = (float)(cmd->data.draw.g / 255.0f);
const float b = (float)(cmd->data.draw.b / 255.0f);
const float a = (float)(cmd->data.draw.a / 255.0f);
const float minu = (float) srcrect->x / texture->w;
const float maxu = (float) (srcrect->x + srcrect->w) / texture->w;
const float minv = (float) srcrect->y / texture->h;
const float maxv = (float) (srcrect->y + srcrect->h) / texture->h;
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
verts->pos.x = dstrect->x;
verts->pos.y = dstrect->y;
verts->pos.z = 0.0f;
verts->tex.x = minu;
verts->tex.y = minv;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts++;
verts->pos.x = dstrect->x;
verts->pos.y = dstrect->y + dstrect->h;
verts->pos.z = 0.0f;
verts->tex.x = minu;
verts->tex.y = maxv;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts++;
verts->pos.x = dstrect->x + dstrect->w;
verts->pos.y = dstrect->y;
verts->pos.z = 0.0f;
verts->tex.x = maxu;
verts->tex.y = minv;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts++;
verts->pos.x = dstrect->x + dstrect->w;
verts->pos.y = dstrect->y + dstrect->h;
verts->pos.z = 0.0f;
verts->tex.x = maxu;
verts->tex.y = maxv;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts++;
return 0;
}
static int
D3D11_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, 5 * sizeof (VertexPositionColor), 0, &cmd->data.draw.first);
const float r = (float)(cmd->data.draw.r / 255.0f);
const float g = (float)(cmd->data.draw.g / 255.0f);
const float b = (float)(cmd->data.draw.b / 255.0f);
const float a = (float)(cmd->data.draw.a / 255.0f);
float minx, miny, maxx, maxy;
float minu, maxu, minv, maxv;
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
minx = -center->x;
maxx = dstrect->w - center->x;
miny = -center->y;
maxy = dstrect->h - center->y;
if (flip & SDL_FLIP_HORIZONTAL) {
minu = (float) (srcrect->x + srcrect->w) / texture->w;
maxu = (float) srcrect->x / texture->w;
} else {
minu = (float) srcrect->x / texture->w;
maxu = (float) (srcrect->x + srcrect->w) / texture->w;
}
if (flip & SDL_FLIP_VERTICAL) {
minv = (float) (srcrect->y + srcrect->h) / texture->h;
maxv = (float) srcrect->y / texture->h;
} else {
minv = (float) srcrect->y / texture->h;
maxv = (float) (srcrect->y + srcrect->h) / texture->h;
}
verts->pos.x = minx;
verts->pos.y = miny;
verts->pos.z = 0.0f;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts->tex.x = minu;
verts->tex.y = minv;
verts++;
verts->pos.x = minx;
verts->pos.y = maxy;
verts->pos.z = 0.0f;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts->tex.x = minu;
verts->tex.y = maxv;
verts++;
verts->pos.x = maxx;
verts->pos.y = miny;
verts->pos.z = 0.0f;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts->tex.x = maxu;
verts->tex.y = minv;
verts++;
verts->pos.x = maxx;
verts->pos.y = maxy;
verts->pos.z = 0.0f;
verts->color.x = r;
verts->color.y = g;
verts->color.z = b;
verts->color.w = a;
verts->tex.x = maxu;
verts->tex.y = maxv;
verts++;
verts->pos.x = dstrect->x + center->x; /* X translation */
verts->pos.y = dstrect->y + center->y; /* Y translation */
verts->pos.z = (float)(M_PI * (float) angle / 180.0f); /* rotation */
verts->color.x = 0;
verts->color.y = 0;
verts->color.z = 0;
verts->color.w = 0;
verts->tex.x = 0.0f;
verts->tex.y = 0.0f;
verts++;
return 0;
}
static int
D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
const void * vertexData, size_t dataSizeInBytes)
@@ -2241,7 +2070,6 @@ D3D11_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
{
D3D11_RenderData *rendererData = (D3D11_RenderData *) renderer->driverdata;
const int viewportRotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
size_t i;
if (rendererData->currentViewportRotation != viewportRotation) {
rendererData->currentViewportRotation = viewportRotation;
@@ -2313,37 +2141,28 @@ D3D11_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
break;
}
case SDL_RENDERCMD_FILL_RECTS: {
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
case SDL_RENDERCMD_COPY: /* unused */
break;
case SDL_RENDERCMD_COPY_EX: /* unused */
break;
case SDL_RENDERCMD_GEOMETRY: {
SDL_Texture *texture = cmd->data.draw.texture;
const size_t count = cmd->data.draw.count;
const size_t first = cmd->data.draw.first;
const size_t start = first / sizeof (VertexPositionColor);
size_t offset = 0;
D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
for (i = 0; i < count; i++, offset += 4) {
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start + offset, 4);
if (texture) {
D3D11_SetCopyState(renderer, cmd, NULL);
} else {
D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_SOLID], 0, NULL, NULL, NULL);
}
break;
}
case SDL_RENDERCMD_COPY: {
const size_t first = cmd->data.draw.first;
const size_t start = first / sizeof (VertexPositionColor);
D3D11_SetCopyState(renderer, cmd, NULL);
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start, 4);
break;
}
case SDL_RENDERCMD_COPY_EX: {
const size_t first = cmd->data.draw.first;
const size_t start = first / sizeof (VertexPositionColor);
const VertexPositionColor *verts = (VertexPositionColor *) (((Uint8 *) vertices) + first);
const VertexPositionColor *transvert = verts + 4;
const float translatex = transvert->pos.x;
const float translatey = transvert->pos.y;
const float rotation = transvert->pos.z;
const Float4X4 matrix = MatrixMultiply(MatrixRotationZ(rotation), MatrixTranslation(translatex, translatey, 0));
D3D11_SetCopyState(renderer, cmd, &matrix);
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, start, 4);
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, start, count);
break;
}
@@ -2523,6 +2342,21 @@ D3D11_RenderPresent(SDL_Renderer * renderer)
}
}
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
/* no-op. */
#else
static int
D3D11_SetVSync(SDL_Renderer * renderer, const int vsync)
{
if (vsync) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
return 0;
}
#endif
SDL_Renderer *
D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
{
@@ -2559,9 +2393,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
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->QueueFillRects = D3D11_QueueFillRects;
renderer->QueueCopy = D3D11_QueueCopy;
renderer->QueueCopyEx = D3D11_QueueCopyEx;
renderer->QueueGeometry = D3D11_QueueGeometry;
renderer->RunCommandQueue = D3D11_RunCommandQueue;
renderer->RenderReadPixels = D3D11_RenderReadPixels;
renderer->RenderPresent = D3D11_RenderPresent;
@@ -2588,6 +2420,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
if ((flags & SDL_RENDERER_PRESENTVSYNC)) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
renderer->SetVSync = D3D11_SetVSync;
#endif
/* HACK: make sure the SDL_Renderer references the SDL_Window data now, in

View File

@@ -279,26 +279,35 @@ MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
switch (cache->vertexFunction) {
case SDL_METAL_VERTEX_SOLID:
/* position (float2) */
vertdesc.layouts[0].stride = sizeof(float) * 2;
/* position (float2), color (uchar4normalized) */
vertdesc.layouts[0].stride = sizeof(float) * 2 + sizeof (int);
vertdesc.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
vertdesc.attributes[0].format = MTLVertexFormatFloat2;
vertdesc.attributes[0].offset = 0;
vertdesc.attributes[0].bufferIndex = 0;
vertdesc.attributes[1].format = MTLVertexFormatUChar4Normalized;
vertdesc.attributes[1].offset = sizeof (float) * 2;
vertdesc.attributes[1].bufferIndex = 0;
break;
case SDL_METAL_VERTEX_COPY:
/* position (float2), texcoord (float2) */
vertdesc.layouts[0].stride = sizeof(float) * 4;
/* position (float2), color (uchar4normalized), texcoord (float2) */
vertdesc.layouts[0].stride = sizeof(float) * 2 + sizeof (int) + sizeof (float) * 2;
vertdesc.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
vertdesc.attributes[0].format = MTLVertexFormatFloat2;
vertdesc.attributes[0].offset = 0;
vertdesc.attributes[0].bufferIndex = 0;
vertdesc.attributes[1].format = MTLVertexFormatFloat2;
vertdesc.attributes[1].offset = sizeof(float) * 2;
vertdesc.attributes[1].format = MTLVertexFormatUChar4Normalized;
vertdesc.attributes[1].offset = sizeof (float) * 2;
vertdesc.attributes[1].bufferIndex = 0;
vertdesc.attributes[2].format = MTLVertexFormatFloat2;
vertdesc.attributes[2].offset = sizeof(float) * 2 + sizeof (int);
vertdesc.attributes[2].bufferIndex = 0;
break;
}
@@ -450,7 +459,7 @@ ChoosePipelineState(METAL_RenderData *data, METAL_ShaderPipelines *pipelines, SD
return MakePipelineState(data, cache, [NSString stringWithFormat:@" (blend=custom 0x%x)", blendmode], blendmode);
}
static void
static SDL_bool
METAL_ActivateRenderCommandEncoder(SDL_Renderer * renderer, MTLLoadAction load, MTLClearColor *clear_color, id<MTLBuffer> vertex_buffer)
{
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
@@ -472,10 +481,16 @@ METAL_ActivateRenderCommandEncoder(SDL_Renderer * renderer, MTLLoadAction load,
load = MTLLoadActionDontCare;
}
}
mtltexture = data.mtlbackbuffer.texture;
if (data.mtlbackbuffer != nil) {
mtltexture = data.mtlbackbuffer.texture;
}
}
SDL_assert(mtltexture);
/* mtltexture can be nil here if macOS refused to give us a drawable,
which apparently can happen for minimized windows, etc. */
if (mtltexture == nil) {
return SDL_FALSE;
}
if (load == MTLLoadActionClear) {
SDL_assert(clear_color != NULL);
@@ -508,6 +523,8 @@ METAL_ActivateRenderCommandEncoder(SDL_Renderer * renderer, MTLLoadAction load,
// or whatever. This means we can _always_ batch rendering commands!
[data.mtlcmdbuffer enqueue];
}
return SDL_TRUE;
}
static void
@@ -1020,13 +1037,6 @@ METAL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
}}
// normalize a value from 0.0f to len into 0.0f to 1.0f.
static inline float
normtex(const float _val, const float len)
{
return _val / len;
}
static int
METAL_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
{
@@ -1060,38 +1070,56 @@ METAL_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
if (!verts) {
return -1;
}
/*
* FIXME: not needed anymore, some cleanup to do
*
*(verts++) = ((float)cmd->data.color.r) / 255.0f;
*(verts++) = ((float)cmd->data.color.g) / 255.0f;
*(verts++) = ((float)cmd->data.color.b) / 255.0f;
*(verts++) = ((float)cmd->data.color.a) / 255.0f;
*/
return 0;
}
static int
METAL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
{
const size_t vertlen = (sizeof (float) * 2) * count;
const int color = (cmd->data.draw.r << 0) | (cmd->data.draw.g << 8) | (cmd->data.draw.b << 16) | ((Uint32)cmd->data.draw.a << 24);
const size_t vertlen = (2 * sizeof (float) + sizeof (int)) * 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);
for (int i = 0; i < count; i++, points++) {
*(verts++) = points->x;
*(verts++) = points->y;
*((int *)verts++) = color;
}
return 0;
}
static int
METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
{
const int color = (cmd->data.draw.r << 0) | (cmd->data.draw.g << 8) | (cmd->data.draw.b << 16) | ((Uint32)cmd->data.draw.a << 24);
SDL_assert(count >= 2); /* should have been checked at the higher level. */
const size_t vertlen = (sizeof (float) * 2) * count;
const size_t vertlen = (2 * sizeof (float) + sizeof (int)) * 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);
for (int i = 0; i < count; i++, points++) {
*(verts++) = points->x;
*(verts++) = points->y;
*((int *)verts++) = color;
}
/* If the line segment is completely horizontal or vertical,
make it one pixel longer, to satisfy the diamond-exit rule.
@@ -1101,8 +1129,8 @@ METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
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) - 2;
points -= 2; /* update the last line. */
verts -= 2 + 1;
const float xstart = points[0].x;
const float ystart = points[0].y;
@@ -1119,161 +1147,51 @@ METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
}
static int
METAL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
METAL_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)
{
const size_t vertlen = (sizeof (float) * 8) * count;
int count = indices ? num_indices : num_vertices;
const size_t vertlen = (2 * sizeof (float) + sizeof (int) + (texture ? 2 : 0) * sizeof (float)) * count;
float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
size_indices = indices ? size_indices : 0;
/* Quads in the following vertex order (matches the quad index buffer):
* 1---3
* | \ |
* 0---2
*/
for (int i = 0; i < count; i++, rects++) {
if ((rects->w <= 0.0f) || (rects->h <= 0.0f)) {
cmd->data.draw.count--;
for (int i = 0; i < count; i++) {
int j;
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 {
*(verts++) = rects->x;
*(verts++) = rects->y + rects->h;
*(verts++) = rects->x;
*(verts++) = rects->y;
*(verts++) = rects->x + rects->w;
*(verts++) = rects->y + rects->h;
*(verts++) = rects->x + rects->w;
*(verts++) = rects->y;
j = i;
}
float *xy_ = (float *)((char*)xy + j * xy_stride);
int col_ = *(int *)((char*)color + j * color_stride);
*(verts++) = xy_[0] * scale_x;
*(verts++) = xy_[1] * scale_y;
*((int *)verts++) = col_;
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
*(verts++) = uv_[0];
*(verts++) = uv_[1];
}
}
if (cmd->data.draw.count == 0) {
cmd->command = SDL_RENDERCMD_NO_OP; // nothing to do, just skip this one later.
}
return 0;
}
static int
METAL_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
const float texw = (float) texture->w;
const float texh = (float) texture->h;
// !!! FIXME: use an index buffer
const size_t vertlen = (sizeof (float) * 16);
float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
/* Interleaved positions and texture coordinates */
*(verts++) = dstrect->x;
*(verts++) = dstrect->y + dstrect->h;
*(verts++) = normtex(srcrect->x, texw);
*(verts++) = normtex(srcrect->y + srcrect->h, texh);
*(verts++) = dstrect->x;
*(verts++) = dstrect->y;
*(verts++) = normtex(srcrect->x, texw);
*(verts++) = normtex(srcrect->y, texh);
*(verts++) = dstrect->x + dstrect->w;
*(verts++) = dstrect->y + dstrect->h;
*(verts++) = normtex(srcrect->x + srcrect->w, texw);
*(verts++) = normtex(srcrect->y + srcrect->h, texh);
*(verts++) = dstrect->x + dstrect->w;
*(verts++) = dstrect->y;
*(verts++) = normtex(srcrect->x + srcrect->w, texw);
*(verts++) = normtex(srcrect->y, texh);
return 0;
}
static int
METAL_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
const float texw = (float) texture->w;
const float texh = (float) texture->h;
const float rads = (float)(M_PI * (float) angle / 180.0f);
const float c = cosf(rads), s = sinf(rads);
float minu, maxu, minv, maxv;
const size_t vertlen = (sizeof (float) * 32);
float *verts;
// cheat and store this offset in (count) because it needs to be aligned in ways other fields don't and we aren't using count otherwise.
verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, CONSTANT_ALIGN(16), &cmd->data.draw.count);
if (!verts) {
return -1;
}
// transform matrix
SDL_memset(verts, '\0', sizeof (*verts) * 16);
verts[10] = verts[15] = 1.0f;
// rotation
verts[0] = c;
verts[1] = s;
verts[4] = -s;
verts[5] = c;
// translation
verts[12] = dstrect->x + center->x;
verts[13] = dstrect->y + center->y;
// rest of the vertices don't need the aggressive alignment. Pack them in.
verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
if (!verts) {
return -1;
}
minu = normtex(srcquad->x, texw);
maxu = normtex(srcquad->x + srcquad->w, texw);
minv = normtex(srcquad->y, texh);
maxv = normtex(srcquad->y + srcquad->h, texh);
if (flip & SDL_FLIP_HORIZONTAL) {
float tmp = maxu;
maxu = minu;
minu = tmp;
}
if (flip & SDL_FLIP_VERTICAL) {
float tmp = maxv;
maxv = minv;
minv = tmp;
}
/* Interleaved positions and texture coordinates */
*(verts++) = -center->x;
*(verts++) = dstrect->h - center->y;
*(verts++) = minu;
*(verts++) = maxv;
*(verts++) = -center->x;
*(verts++) = -center->y;
*(verts++) = minu;
*(verts++) = minv;
*(verts++) = dstrect->w - center->x;
*(verts++) = dstrect->h - center->y;
*(verts++) = maxu;
*(verts++) = maxv;
*(verts++) = dstrect->w - center->x;
*(verts++) = -center->y;
*(verts++) = maxu;
*(verts++) = minv;
return 0;
}
typedef struct
{
#if __has_feature(objc_arc)
@@ -1295,7 +1213,7 @@ typedef struct
size_t color_offset;
} METAL_DrawStateCache;
static void
static SDL_bool
SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_MetalFragmentFunction shader,
const size_t constants_offset, id<MTLBuffer> mtlbufvertex, METAL_DrawStateCache *statecache)
{
@@ -1304,7 +1222,9 @@ SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Met
size_t first = cmd->data.draw.first;
id<MTLRenderPipelineState> newpipeline;
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, statecache->vertex_buffer);
if (!METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, statecache->vertex_buffer)) {
return SDL_FALSE;
}
if (statecache->viewport_dirty) {
MTLViewport viewport;
@@ -1358,9 +1278,10 @@ SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Met
}
[data.mtlcmdencoder setVertexBufferOffset:first atIndex:0]; /* position/texcoords */
return SDL_TRUE;
}
static void
static SDL_bool
SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t constants_offset,
id<MTLBuffer> mtlbufvertex, METAL_DrawStateCache *statecache)
{
@@ -1368,7 +1289,9 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t
SDL_Texture *texture = cmd->data.draw.texture;
METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata;
SetDrawState(renderer, cmd, texturedata.fragmentFunction, constants_offset, mtlbufvertex, statecache);
if (!SetDrawState(renderer, cmd, texturedata.fragmentFunction, constants_offset, mtlbufvertex, statecache)) {
return SDL_FALSE;
}
if (texture != statecache->texture) {
METAL_TextureData *oldtexturedata = NULL;
@@ -1386,6 +1309,7 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t
}
statecache->texture = texture;
}
return SDL_TRUE;
}
static int
@@ -1483,6 +1407,7 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
MTLClearColor color = MTLClearColorMake(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
// get new command encoder, set up with an initial clear operation.
// (this might fail, and future draw operations will notice.)
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, mtlbufvertex);
break;
}
@@ -1491,44 +1416,34 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
case SDL_RENDERCMD_DRAW_LINES: {
const size_t count = cmd->data.draw.count;
const MTLPrimitiveType primtype = (cmd->command == SDL_RENDERCMD_DRAW_POINTS) ? MTLPrimitiveTypePoint : MTLPrimitiveTypeLineStrip;
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_FILL_RECTS: {
const size_t count = cmd->data.draw.count;
const size_t maxcount = UINT16_MAX / 4;
SetDrawState(renderer, cmd, SDL_METAL_FRAGMENT_SOLID, CONSTANTS_OFFSET_IDENTITY, mtlbufvertex, &statecache);
if (count == 1) {
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
} else {
/* Our index buffer has 16 bit indices, so we can only draw
* 65k vertices (16k rects) at a time. */
for (size_t i = 0; i < count; i += maxcount) {
/* Set the vertex buffer offset for our current positions.
* The vertex buffer itself was bound in SetDrawState. */
[data.mtlcmdencoder setVertexBufferOffset:cmd->data.draw.first + i*sizeof(float)*8 atIndex:0];
[data.mtlcmdencoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:SDL_min(maxcount, count - i) * 6
indexType:MTLIndexTypeUInt16
indexBuffer:data.mtlbufquadindices
indexBufferOffset:0];
}
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_COPY: {
SetCopyState(renderer, cmd, CONSTANTS_OFFSET_IDENTITY, mtlbufvertex, &statecache);
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
}
case SDL_RENDERCMD_COPY_EX: {
SetCopyState(renderer, cmd, CONSTANTS_OFFSET_INVALID, mtlbufvertex, &statecache);
[data.mtlcmdencoder setVertexBuffer:mtlbufvertex offset:cmd->data.draw.count atIndex:3]; // transform
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
case SDL_RENDERCMD_COPY: /* unused */
break;
case SDL_RENDERCMD_COPY_EX: /* unused */
break;
case SDL_RENDERCMD_GEOMETRY: {
const size_t count = cmd->data.draw.count;
SDL_Texture *texture = cmd->data.draw.texture;
if (texture) {
if (SetCopyState(renderer, cmd, CONSTANTS_OFFSET_IDENTITY, mtlbufvertex, &statecache)) {
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:count];
}
} else {
if (SetDrawState(renderer, cmd, SDL_METAL_FRAGMENT_SOLID, CONSTANTS_OFFSET_IDENTITY, mtlbufvertex, &statecache)) {
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:count];
}
}
break;
}
@@ -1546,7 +1461,9 @@ METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 pixel_format, void * pixels, int pitch)
{ @autoreleasepool {
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
if (!METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil)) {
return SDL_SetError("Failed to activate render command encoder (is your window in the background?");
}
[data.mtlcmdencoder endEncoding];
id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
@@ -1591,20 +1508,28 @@ static void
METAL_RenderPresent(SDL_Renderer * renderer)
{ @autoreleasepool {
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
SDL_bool ready = SDL_TRUE;
// If we don't have a command buffer, we can't present, so activate to get one.
if (data.mtlcmdencoder == nil) {
// We haven't even gotten a backbuffer yet? Clear it to black. Otherwise, load the existing data.
if (data.mtlbackbuffer == nil) {
MTLClearColor color = MTLClearColorMake(0.0f, 0.0f, 0.0f, 1.0f);
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, nil);
ready = METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, nil);
} else {
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
ready = METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
}
}
[data.mtlcmdencoder endEncoding];
[data.mtlcmdbuffer presentDrawable:data.mtlbackbuffer];
// If we don't have a drawable to present, don't try to present it.
// But we'll still try to commit the command buffer in case it was already enqueued.
if (ready) {
SDL_assert(data.mtlbackbuffer != nil);
[data.mtlcmdbuffer presentDrawable:data.mtlbackbuffer];
}
[data.mtlcmdbuffer commit];
data.mtlcmdencoder = nil;
@@ -1647,11 +1572,34 @@ METAL_GetMetalLayer(SDL_Renderer * renderer)
static void *
METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
{ @autoreleasepool {
// note that data.mtlcmdencoder can be nil if METAL_ActivateRenderCommandEncoder fails.
// Before SDL 2.0.18, it might have returned a non-nil encoding that might not have been
// usable for presentation. Check your return values!
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
return (__bridge void*)data.mtlcmdencoder;
}}
static int
METAL_SetVSync(SDL_Renderer * renderer, const int vsync)
{
#if (defined(__MACOSX__) && defined(MAC_OS_X_VERSION_10_13)) || TARGET_OS_MACCATALYST
if (@available(macOS 10.13, *)) {
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
if (vsync) {
data.mtllayer.displaySyncEnabled = YES;
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
data.mtllayer.displaySyncEnabled = NO;
renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
return 0;
}
#endif
return SDL_SetError("This Apple OS does not support displaySyncEnabled!");
}
static SDL_Renderer *
METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
{ @autoreleasepool {
@@ -1891,14 +1839,13 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->QueueSetDrawColor = METAL_QueueSetDrawColor;
renderer->QueueDrawPoints = METAL_QueueDrawPoints;
renderer->QueueDrawLines = METAL_QueueDrawLines;
renderer->QueueFillRects = METAL_QueueFillRects;
renderer->QueueCopy = METAL_QueueCopy;
renderer->QueueCopyEx = METAL_QueueCopyEx;
renderer->QueueGeometry = METAL_QueueGeometry;
renderer->RunCommandQueue = METAL_RunCommandQueue;
renderer->RenderReadPixels = METAL_RenderReadPixels;
renderer->RenderPresent = METAL_RenderPresent;
renderer->DestroyTexture = METAL_DestroyTexture;
renderer->DestroyRenderer = METAL_DestroyRenderer;
renderer->SetVSync = METAL_SetVSync;
renderer->GetMetalLayer = METAL_GetMetalLayer;
renderer->GetMetalCommandEncoder = METAL_GetMetalCommandEncoder;

View File

@@ -6,11 +6,13 @@ using namespace metal;
struct SolidVertexInput
{
float2 position [[attribute(0)]];
float4 color [[attribute(1)]];
};
struct SolidVertexOutput
{
float4 position [[position]];
float4 color;
float pointSize [[point_size]];
};
@@ -20,24 +22,27 @@ vertex SolidVertexOutput SDL_Solid_vertex(SolidVertexInput in [[stage_in]],
{
SolidVertexOutput v;
v.position = (projection * transform) * float4(in.position, 0.0f, 1.0f);
v.color = in.color;
v.pointSize = 1.0f;
return v;
}
fragment float4 SDL_Solid_fragment(const device float4 &col [[buffer(0)]])
fragment float4 SDL_Solid_fragment(SolidVertexInput in [[stage_in]])
{
return col;
return in.color;
}
struct CopyVertexInput
{
float2 position [[attribute(0)]];
float2 texcoord [[attribute(1)]];
float4 color [[attribute(1)]];
float2 texcoord [[attribute(2)]];
};
struct CopyVertexOutput
{
float4 position [[position]];
float4 color;
float2 texcoord;
};
@@ -47,16 +52,16 @@ vertex CopyVertexOutput SDL_Copy_vertex(CopyVertexInput in [[stage_in]],
{
CopyVertexOutput v;
v.position = (projection * transform) * float4(in.position, 0.0f, 1.0f);
v.color = in.color;
v.texcoord = in.texcoord;
return v;
}
fragment float4 SDL_Copy_fragment(CopyVertexOutput vert [[stage_in]],
const device float4 &col [[buffer(0)]],
texture2d<float> tex [[texture(0)]],
sampler s [[sampler(0)]])
{
return tex.sample(s, vert.texcoord) * col;
return tex.sample(s, vert.texcoord) * vert.color;
}
struct YUVDecode
@@ -68,7 +73,6 @@ struct YUVDecode
};
fragment float4 SDL_YUV_fragment(CopyVertexOutput vert [[stage_in]],
const device float4 &col [[buffer(0)]],
constant YUVDecode &decode [[buffer(1)]],
texture2d<float> texY [[texture(0)]],
texture2d_array<float> texUV [[texture(1)]],
@@ -81,11 +85,10 @@ fragment float4 SDL_YUV_fragment(CopyVertexOutput vert [[stage_in]],
yuv += decode.offset;
return col * float4(dot(yuv, decode.Rcoeff), dot(yuv, decode.Gcoeff), dot(yuv, decode.Bcoeff), 1.0);
return vert.color * float4(dot(yuv, decode.Rcoeff), dot(yuv, decode.Gcoeff), dot(yuv, decode.Bcoeff), 1.0);
}
fragment float4 SDL_NV12_fragment(CopyVertexOutput vert [[stage_in]],
const device float4 &col [[buffer(0)]],
constant YUVDecode &decode [[buffer(1)]],
texture2d<float> texY [[texture(0)]],
texture2d<float> texUV [[texture(1)]],
@@ -97,11 +100,10 @@ fragment float4 SDL_NV12_fragment(CopyVertexOutput vert [[stage_in]],
yuv += decode.offset;
return col * float4(dot(yuv, decode.Rcoeff), dot(yuv, decode.Gcoeff), dot(yuv, decode.Bcoeff), 1.0);
return vert.color * float4(dot(yuv, decode.Rcoeff), dot(yuv, decode.Gcoeff), dot(yuv, decode.Bcoeff), 1.0);
}
fragment float4 SDL_NV21_fragment(CopyVertexOutput vert [[stage_in]],
const device float4 &col [[buffer(0)]],
constant YUVDecode &decode [[buffer(1)]],
texture2d<float> texY [[texture(0)]],
texture2d<float> texUV [[texture(1)]],
@@ -113,5 +115,6 @@ fragment float4 SDL_NV21_fragment(CopyVertexOutput vert [[stage_in]],
yuv += decode.offset;
return col * float4(dot(yuv, decode.Rcoeff), dot(yuv, decode.Gcoeff), dot(yuv, decode.Bcoeff), 1.0);
return vert.color * float4(dot(yuv, decode.Rcoeff), dot(yuv, decode.Gcoeff), dot(yuv, decode.Bcoeff), 1.0);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -159,7 +159,7 @@ SDL_PROC_UNUSED(void, glGetBooleanv, (GLenum pname, GLboolean * params))
SDL_PROC_UNUSED(void, glGetClipPlane, (GLenum plane, GLdouble * equation))
SDL_PROC_UNUSED(void, glGetDoublev, (GLenum pname, GLdouble * params))
SDL_PROC(GLenum, glGetError, (void))
SDL_PROC_UNUSED(void, glGetFloatv, (GLenum pname, GLfloat * params))
SDL_PROC(void, glGetFloatv, (GLenum pname, GLfloat * params))
SDL_PROC(void, glGetIntegerv, (GLenum pname, GLint * params))
SDL_PROC_UNUSED(void, glGetLightfv,
(GLenum light, GLenum pname, GLfloat * params))
@@ -302,14 +302,14 @@ SDL_PROC_UNUSED(void, glPolygonOffset, (GLfloat factor, GLfloat units))
SDL_PROC_UNUSED(void, glPolygonStipple, (const GLubyte * mask))
SDL_PROC_UNUSED(void, glPopAttrib, (void))
SDL_PROC_UNUSED(void, glPopClientAttrib, (void))
SDL_PROC(void, glPopMatrix, (void))
SDL_PROC_UNUSED(void, glPopMatrix, (void))
SDL_PROC_UNUSED(void, glPopName, (void))
SDL_PROC_UNUSED(void, glPrioritizeTextures,
(GLsizei n, const GLuint * textures,
const GLclampf * priorities))
SDL_PROC_UNUSED(void, glPushAttrib, (GLbitfield mask))
SDL_PROC_UNUSED(void, glPushClientAttrib, (GLbitfield mask))
SDL_PROC(void, glPushMatrix, (void))
SDL_PROC_UNUSED(void, glPushMatrix, (void))
SDL_PROC_UNUSED(void, glPushName, (GLuint name))
SDL_PROC_UNUSED(void, glRasterPos2d, (GLdouble x, GLdouble y))
SDL_PROC_UNUSED(void, glRasterPos2dv, (const GLdouble * v))
@@ -354,7 +354,7 @@ SDL_PROC_UNUSED(void, glRects,
(GLshort x1, GLshort y1, GLshort x2, GLshort y2))
SDL_PROC_UNUSED(void, glRectsv, (const GLshort * v1, const GLshort * v2))
SDL_PROC_UNUSED(GLint, glRenderMode, (GLenum mode))
SDL_PROC(void, glRotated,
SDL_PROC_UNUSED(void, glRotated,
(GLdouble angle, GLdouble x, GLdouble y, GLdouble z))
SDL_PROC(void, glRotatef,
(GLfloat angle, GLfloat x, GLfloat y, GLfloat z))
@@ -442,7 +442,7 @@ SDL_PROC(void, glTexSubImage2D,
GLsizei width, GLsizei height, GLenum format, GLenum type,
const GLvoid * pixels))
SDL_PROC_UNUSED(void, glTranslated, (GLdouble x, GLdouble y, GLdouble z))
SDL_PROC(void, glTranslatef, (GLfloat x, GLfloat y, GLfloat z))
SDL_PROC_UNUSED(void, glTranslatef, (GLfloat x, GLfloat y, GLfloat z))
SDL_PROC_UNUSED(void, glVertex2d, (GLdouble x, GLdouble y))
SDL_PROC_UNUSED(void, glVertex2dv, (const GLdouble * v))
SDL_PROC(void, glVertex2f, (GLfloat x, GLfloat y))

View File

@@ -21,7 +21,6 @@
#include "../../SDL_internal.h"
#if SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED
#include "SDL_hints.h"
#include "SDL_opengl.h"
#include "../SDL_sysrender.h"
@@ -124,6 +123,7 @@ typedef struct
GLfloat texh;
GLenum format;
GLenum formattype;
GL_Shader shader;
void *pixels;
int pitch;
SDL_Rect locked_rect;
@@ -631,6 +631,57 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
}
#endif
if (texture->format == SDL_PIXELFORMAT_ABGR8888 || texture->format == SDL_PIXELFORMAT_ARGB8888) {
data->shader = SHADER_RGBA;
} else {
data->shader = SHADER_RGB;
}
#if SDL_HAVE_YUV
if (data->yuv || data->nv12) {
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
case SDL_YUV_CONVERSION_JPEG:
if (data->yuv) {
data->shader = SHADER_YUV_JPEG;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
data->shader = SHADER_NV12_JPEG;
} else {
data->shader = SHADER_NV21_JPEG;
}
break;
case SDL_YUV_CONVERSION_BT601:
if (data->yuv) {
data->shader = SHADER_YUV_BT601;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
data->shader = SHADER_NV12_RG_BT601;
} else {
data->shader = SHADER_NV12_RA_BT601;
}
} else {
data->shader = SHADER_NV21_BT601;
}
break;
case SDL_YUV_CONVERSION_BT709:
if (data->yuv) {
data->shader = SHADER_YUV_BT709;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
data->shader = SHADER_NV12_RG_BT709;
} else {
data->shader = SHADER_NV12_RA_BT709;
}
} else {
data->shader = SHADER_NV21_BT709;
}
break;
default:
SDL_assert(!"unsupported YUV conversion mode");
break;
}
}
#endif /* SDL_HAVE_YUV */
return GL_CheckError("", renderer);
}
@@ -891,164 +942,98 @@ 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;
/* Offset to hit the center of the pixel. */
for (i = 0; i < count; i++) {
*(verts++) = 0.5f + points[i].x;
*(verts++) = 0.5f + points[i].y;
/* 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;
}
/* Make the last line segment one pixel longer, to satisfy the
diamond-exit rule. */
verts -= 4;
{
const GLfloat xstart = verts[0];
const GLfloat ystart = verts[1];
const GLfloat xend = verts[2];
const GLfloat yend = verts[3];
return 0;
}
if (ystart == yend) { /* horizontal line */
verts[(xend > xstart) ? 2 : 0] += 1.0f;
} else if (xstart == xend) { /* vertical line */
verts[(yend > ystart) ? 3 : 1] += 1.0f;
} else { /* bump a pixel in the direction we are moving in. */
const GLfloat deltax = xend - xstart;
const GLfloat deltay = yend - ystart;
const GLfloat angle = SDL_atan2f(deltay, deltax);
verts[2] += SDL_cosf(angle);
verts[3] += SDL_sinf(angle);
static int
GL_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)
{
GL_TextureData *texturedata = NULL;
int i;
int count = indices ? num_indices : num_vertices;
GLfloat *verts;
int sz = 2 + 4 + (texture ? 2 : 0);
verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * sz * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
if (texture) {
texturedata = (GL_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 * inv255f;
*(verts++) = col_.g * inv255f;
*(verts++) = col_.b * inv255f;
*(verts++) = col_.a * inv255f;
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
*(verts++) = uv_[0] * texturedata->texw;
*(verts++) = uv_[1] * texturedata->texh;
}
}
return 0;
}
static int
GL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
{
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 4 * sizeof (GLfloat), 0, &cmd->data.draw.first);
int i;
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
for (i = 0; i < count; i++) {
const SDL_FRect *rect = &rects[i];
*(verts++) = rect->x;
*(verts++) = rect->y;
*(verts++) = rect->x + rect->w;
*(verts++) = rect->y + rect->h;
}
return 0;
}
static int
GL_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
GLfloat minx, miny, maxx, maxy;
GLfloat minu, maxu, minv, maxv;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
minx = dstrect->x;
miny = dstrect->y;
maxx = dstrect->x + dstrect->w;
maxy = dstrect->y + dstrect->h;
minu = (GLfloat) srcrect->x / texture->w;
minu *= texturedata->texw;
maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
maxu *= texturedata->texw;
minv = (GLfloat) srcrect->y / texture->h;
minv *= texturedata->texh;
maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
maxv *= texturedata->texh;
cmd->data.draw.count = 1;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = maxy;
*(verts++) = minu;
*(verts++) = maxu;
*(verts++) = minv;
*(verts++) = maxv;
return 0;
}
static int
GL_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
GLfloat minx, miny, maxx, maxy;
GLfloat centerx, centery;
GLfloat minu, maxu, minv, maxv;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 11 * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
centerx = center->x;
centery = center->y;
if (flip & SDL_FLIP_HORIZONTAL) {
minx = dstrect->w - centerx;
maxx = -centerx;
}
else {
minx = -centerx;
maxx = dstrect->w - centerx;
}
if (flip & SDL_FLIP_VERTICAL) {
miny = dstrect->h - centery;
maxy = -centery;
}
else {
miny = -centery;
maxy = dstrect->h - centery;
}
minu = (GLfloat) srcrect->x / texture->w;
minu *= texturedata->texw;
maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
maxu *= texturedata->texw;
minv = (GLfloat) srcrect->y / texture->h;
minv *= texturedata->texh;
maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
maxv *= texturedata->texh;
cmd->data.draw.count = 1;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = maxy;
*(verts++) = minu;
*(verts++) = maxu;
*(verts++) = minv;
*(verts++) = maxv;
*(verts++) = (GLfloat) dstrect->x + centerx;
*(verts++) = (GLfloat) dstrect->y + centery;
*(verts++) = (GLfloat) angle;
return 0;
}
@@ -1128,71 +1113,33 @@ SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
{
SDL_Texture *texture = cmd->data.draw.texture;
const GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
GL_Shader shader;
if (texture->format == SDL_PIXELFORMAT_ABGR8888 || texture->format == SDL_PIXELFORMAT_ARGB8888) {
shader = SHADER_RGBA;
} else {
shader = SHADER_RGB;
}
#if SDL_HAVE_YUV
if (data->shaders) {
if (texturedata->yuv || texturedata->nv12) {
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
case SDL_YUV_CONVERSION_JPEG:
if (texturedata->yuv) {
shader = SHADER_YUV_JPEG;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
shader = SHADER_NV12_JPEG;
} else {
shader = SHADER_NV21_JPEG;
}
break;
case SDL_YUV_CONVERSION_BT601:
if (texturedata->yuv) {
shader = SHADER_YUV_BT601;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
shader = SHADER_NV12_BT601;
} else {
shader = SHADER_NV21_BT601;
}
break;
case SDL_YUV_CONVERSION_BT709:
if (texturedata->yuv) {
shader = SHADER_YUV_BT709;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
shader = SHADER_NV12_BT709;
} else {
shader = SHADER_NV21_BT709;
}
break;
default:
SDL_assert(!"unsupported YUV conversion mode");
break;
}
}
}
#endif
SetDrawState(data, cmd, shader);
SetDrawState(data, cmd, texturedata->shader);
if (texture != data->drawstate.texture) {
const GLenum textype = data->textype;
#if SDL_HAVE_YUV
if (texturedata->yuv) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
}
data->glBindTexture(textype, texturedata->vtexture);
data->glActiveTextureARB(GL_TEXTURE1_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, texturedata->utexture);
}
if (texturedata->nv12) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, texturedata->utexture);
}
#endif
data->glActiveTextureARB(GL_TEXTURE0_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
data->glBindTexture(textype, texturedata->texture);
data->drawstate.texture = texture;
@@ -1212,9 +1159,22 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
data->drawstate.target = renderer->target;
if (!data->drawstate.target) {
SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
int w, h;
SDL_GL_GetDrawableSize(renderer->window, &w, &h);
if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
data->drawstate.viewport_dirty = SDL_TRUE; // if the window dimensions changed, invalidate the current viewport, etc.
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.drawablew = w;
data->drawstate.drawableh = h;
}
}
#ifdef __MACOSX__
// On macOS, moving the window seems to invalidate the OpenGL viewport state,
// so don't bother trying to persist it across frames; always reset it.
// Workaround for: https://github.com/libsdl-org/SDL/issues/1504
data->drawstate.viewport_dirty = SDL_TRUE;
#endif
while (cmd) {
switch (cmd->command) {
@@ -1223,7 +1183,7 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.color) {
data->glColor4f((GLfloat) r * inv255f,
(GLfloat) g * inv255f,
@@ -1261,7 +1221,7 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.clear_color) {
const GLfloat fr = ((GLfloat) r) * inv255f;
const GLfloat fg = ((GLfloat) g) * inv255f;
@@ -1306,72 +1266,56 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
break;
}
case SDL_RENDERCMD_FILL_RECTS: {
const size_t count = cmd->data.draw.count;
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
case SDL_RENDERCMD_COPY: /* unused */
break;
case SDL_RENDERCMD_COPY_EX: /* unused */
break;
case SDL_RENDERCMD_GEOMETRY: {
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
SetDrawState(data, cmd, SHADER_SOLID);
for (i = 0; i < count; ++i, verts += 4) {
data->glRectf(verts[0], verts[1], verts[2], verts[3]);
SDL_Texture *texture = cmd->data.draw.texture;
const size_t count = cmd->data.draw.count;
if (texture) {
SetCopyState(data, cmd);
} else {
SetDrawState(data, cmd, SHADER_SOLID);
}
{
size_t j;
float currentColor[4];
data->glGetFloatv(GL_CURRENT_COLOR, currentColor);
data->glBegin(GL_TRIANGLES);
for (j = 0; j < count; ++j)
{
const GLfloat x = *(verts++);
const GLfloat y = *(verts++);
const GLfloat r = *(verts++);
const GLfloat g = *(verts++);
const GLfloat b = *(verts++);
const GLfloat a = *(verts++);
data->glColor4f(r, g, b, a);
if (texture) {
GLfloat u = *(verts++);
GLfloat v = *(verts++);
data->glTexCoord2f(u,v);
}
data->glVertex2f(x, y);
}
data->glEnd();
data->glColor4f(currentColor[0], currentColor[1], currentColor[2], currentColor[3]);
}
break;
}
}
case SDL_RENDERCMD_COPY: {
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
const GLfloat minx = verts[0];
const GLfloat miny = verts[1];
const GLfloat maxx = verts[2];
const GLfloat maxy = verts[3];
const GLfloat minu = verts[4];
const GLfloat maxu = verts[5];
const GLfloat minv = verts[6];
const GLfloat maxv = verts[7];
SetCopyState(data, cmd);
data->glBegin(GL_TRIANGLE_STRIP);
data->glTexCoord2f(minu, minv);
data->glVertex2f(minx, miny);
data->glTexCoord2f(maxu, minv);
data->glVertex2f(maxx, miny);
data->glTexCoord2f(minu, maxv);
data->glVertex2f(minx, maxy);
data->glTexCoord2f(maxu, maxv);
data->glVertex2f(maxx, maxy);
data->glEnd();
break;
}
case SDL_RENDERCMD_COPY_EX: {
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
const GLfloat minx = verts[0];
const GLfloat miny = verts[1];
const GLfloat maxx = verts[2];
const GLfloat maxy = verts[3];
const GLfloat minu = verts[4];
const GLfloat maxu = verts[5];
const GLfloat minv = verts[6];
const GLfloat maxv = verts[7];
const GLfloat translatex = verts[8];
const GLfloat translatey = verts[9];
const GLdouble angle = verts[10];
SetCopyState(data, cmd);
/* Translate to flip, rotate, translate to position */
data->glPushMatrix();
data->glTranslatef(translatex, translatey, 0.0f);
data->glRotated(angle, 0.0, 0.0, 1.0);
data->glBegin(GL_TRIANGLE_STRIP);
data->glTexCoord2f(minu, minv);
data->glVertex2f(minx, miny);
data->glTexCoord2f(maxu, minv);
data->glVertex2f(maxx, miny);
data->glTexCoord2f(minu, maxv);
data->glVertex2f(minx, maxy);
data->glTexCoord2f(maxu, maxv);
data->glVertex2f(maxx, maxy);
data->glEnd();
data->glPopMatrix();
break;
}
case SDL_RENDERCMD_NO_OP:
break;
@@ -1544,13 +1488,29 @@ GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, floa
data->glEnable(textype);
#if SDL_HAVE_YUV
if (texturedata->yuv) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
}
data->glBindTexture(textype, texturedata->vtexture);
data->glActiveTextureARB(GL_TEXTURE1_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, texturedata->utexture);
data->glActiveTextureARB(GL_TEXTURE0_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
}
if (texturedata->nv12) {
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, texturedata->utexture);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
}
#endif
data->glBindTexture(textype, texturedata->texture);
@@ -1558,9 +1518,12 @@ GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, floa
data->drawstate.texturing = SDL_TRUE;
data->drawstate.texture = texture;
if(texw) *texw = (float)texturedata->texw;
if(texh) *texh = (float)texturedata->texh;
if (texw) {
*texw = (float)texturedata->texw;
}
if (texh) {
*texh = (float)texturedata->texh;
}
return 0;
}
@@ -1575,16 +1538,35 @@ GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
#if SDL_HAVE_YUV
if (texturedata->yuv) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE2_ARB);
}
data->glBindTexture(textype, 0);
data->glDisable(textype);
data->glActiveTextureARB(GL_TEXTURE1_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, 0);
data->glDisable(textype);
data->glActiveTextureARB(GL_TEXTURE0_ARB);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
}
if (texturedata->nv12) {
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE1_ARB);
}
data->glBindTexture(textype, 0);
data->glDisable(textype);
if (data->GL_ARB_multitexture_supported) {
data->glActiveTextureARB(GL_TEXTURE0_ARB);
}
}
#endif
data->glBindTexture(textype, 0);
data->glDisable(textype);
data->drawstate.texturing = SDL_FALSE;
@@ -1593,6 +1575,26 @@ GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
return 0;
}
static int
GL_SetVSync(SDL_Renderer * renderer, const int vsync)
{
int retval;
if (vsync) {
retval = SDL_GL_SetSwapInterval(1);
} else {
retval = SDL_GL_SetSwapInterval(0);
}
if (retval != 0) {
return retval;
}
if (SDL_GL_GetSwapInterval() > 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
return retval;
}
static SDL_Renderer *
GL_CreateRenderer(SDL_Window * window, Uint32 flags)
@@ -1651,14 +1653,13 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->QueueSetDrawColor = GL_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = GL_QueueDrawPoints;
renderer->QueueDrawLines = GL_QueueDrawLines;
renderer->QueueFillRects = GL_QueueFillRects;
renderer->QueueCopy = GL_QueueCopy;
renderer->QueueCopyEx = GL_QueueCopyEx;
renderer->QueueGeometry = GL_QueueGeometry;
renderer->RunCommandQueue = GL_RunCommandQueue;
renderer->RenderReadPixels = GL_RenderReadPixels;
renderer->RenderPresent = GL_RenderPresent;
renderer->DestroyTexture = GL_DestroyTexture;
renderer->DestroyRenderer = GL_DestroyRenderer;
renderer->SetVSync = GL_SetVSync;
renderer->GL_BindTexture = GL_BindTexture;
renderer->GL_UnbindTexture = GL_UnbindTexture;
renderer->info = GL_RenderDriver.info;

View File

@@ -149,7 +149,7 @@ struct GL_ShaderContext
"uniform sampler2D tex1; // U/V \n" \
"\n" \
#define NV12_SHADER_BODY \
#define NV12_RA_SHADER_BODY \
"\n" \
"void main()\n" \
"{\n" \
@@ -174,6 +174,31 @@ struct GL_ShaderContext
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \
"}" \
#define NV12_RG_SHADER_BODY \
"\n" \
"void main()\n" \
"{\n" \
" vec2 tcoord;\n" \
" vec3 yuv, rgb;\n" \
"\n" \
" // Get the Y value \n" \
" tcoord = v_texCoord;\n" \
" yuv.x = texture2D(tex0, tcoord).r;\n" \
"\n" \
" // Get the U and V values \n" \
" tcoord *= UVCoordScale;\n" \
" yuv.yz = texture2D(tex1, tcoord).rg;\n" \
"\n" \
" // Do the color transform \n" \
" yuv += offset;\n" \
" rgb.r = dot(yuv, Rcoeff);\n" \
" rgb.g = dot(yuv, Gcoeff);\n" \
" rgb.b = dot(yuv, Bcoeff);\n" \
"\n" \
" // That was easy. :) \n" \
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \
"}" \
#define NV21_SHADER_PROLOGUE \
"varying vec4 v_color;\n" \
"varying vec2 v_texCoord;\n" \
@@ -294,25 +319,43 @@ static const char *shader_source[NUM_SHADERS][2] =
/* fragment shader */
NV12_SHADER_PROLOGUE
JPEG_SHADER_CONSTANTS
NV12_SHADER_BODY
NV12_RA_SHADER_BODY
},
/* SHADER_NV12_BT601 */
/* SHADER_NV12_RA_BT601 */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV12_SHADER_PROLOGUE
BT601_SHADER_CONSTANTS
NV12_SHADER_BODY
NV12_RA_SHADER_BODY
},
/* SHADER_NV12_BT709 */
/* SHADER_NV12_RG_BT601 */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV12_SHADER_PROLOGUE
BT601_SHADER_CONSTANTS
NV12_RG_SHADER_BODY
},
/* SHADER_NV12_RA_BT709 */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV12_SHADER_PROLOGUE
BT709_SHADER_CONSTANTS
NV12_SHADER_BODY
NV12_RA_SHADER_BODY
},
/* SHADER_NV12_RG_BT709 */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV12_SHADER_PROLOGUE
BT709_SHADER_CONSTANTS
NV12_RG_SHADER_BODY
},
/* SHADER_NV21_JPEG */
{

View File

@@ -36,8 +36,10 @@ typedef enum {
SHADER_YUV_BT601,
SHADER_YUV_BT709,
SHADER_NV12_JPEG,
SHADER_NV12_BT601,
SHADER_NV12_BT709,
SHADER_NV12_RA_BT601,
SHADER_NV12_RG_BT601,
SHADER_NV12_RA_BT709,
SHADER_NV12_RG_BT709,
SHADER_NV21_JPEG,
SHADER_NV21_BT601,
SHADER_NV21_BT709,

View File

@@ -27,6 +27,7 @@ SDL_PROC_OES(void, glBlendFuncSeparateOES, (GLenum, GLenum, GLenum, GLenum))
SDL_PROC(void, glClear, (GLbitfield))
SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))
SDL_PROC(void, glColor4f, (GLfloat, GLfloat, GLfloat, GLfloat))
SDL_PROC(void, glColorPointer, (GLint, GLenum, GLsizei, const GLvoid *))
SDL_PROC(void, glDeleteTextures, (GLsizei, const GLuint *))
SDL_PROC(void, glDisable, (GLenum))
SDL_PROC(void, glDisableClientState, (GLenum array))
@@ -56,10 +57,6 @@ SDL_PROC(void, glViewport, (GLint, GLint, GLsizei, GLsizei))
SDL_PROC_OES(void, glBindFramebufferOES, (GLenum, GLuint))
SDL_PROC_OES(void, glFramebufferTexture2DOES, (GLenum, GLenum, GLenum, GLuint, GLint))
SDL_PROC_OES(GLenum, glCheckFramebufferStatusOES, (GLenum))
SDL_PROC(void, glPushMatrix, (void))
SDL_PROC(void, glTranslatef, (GLfloat, GLfloat, GLfloat))
SDL_PROC(void, glRotatef, (GLfloat, GLfloat, GLfloat, GLfloat))
SDL_PROC(void, glPopMatrix, (void))
SDL_PROC_OES(void, glDeleteFramebuffersOES, (GLsizei, const GLuint*))
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -564,194 +564,98 @@ 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;
/* Offset to hit the center of the pixel. */
for (i = 0; i < count; i++) {
*(verts++) = 0.5f + points[i].x;
*(verts++) = 0.5f + points[i].y;
/* 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;
}
/* Make the last line segment one pixel longer, to satisfy the
diamond-exit rule. */
verts -= 4;
{
const GLfloat xstart = verts[0];
const GLfloat ystart = verts[1];
const GLfloat xend = verts[2];
const GLfloat yend = verts[3];
return 0;
}
if (ystart == yend) { /* horizontal line */
verts[(xend > xstart) ? 2 : 0] += 1.0f;
} else if (xstart == xend) { /* vertical line */
verts[(yend > ystart) ? 3 : 1] += 1.0f;
} else { /* bump a pixel in the direction we are moving in. */
const GLfloat deltax = xend - xstart;
const GLfloat deltay = yend - ystart;
const GLfloat angle = SDL_atan2f(deltay, deltax);
verts[2] += SDL_cosf(angle);
verts[3] += SDL_sinf(angle);
static int
GLES_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)
{
GLES_TextureData *texturedata = NULL;
int i;
int count = indices ? num_indices : num_vertices;
GLfloat *verts;
int sz = 2 + 4 + (texture ? 2 : 0);
verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * sz * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
if (texture) {
texturedata = (GLES_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 * inv255f;
*(verts++) = col_.g * inv255f;
*(verts++) = col_.b * inv255f;
*(verts++) = col_.a * inv255f;
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
*(verts++) = uv_[0] * texturedata->texw;
*(verts++) = uv_[1] * texturedata->texh;
}
}
return 0;
}
static int
GLES_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
{
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
int i;
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
for (i = 0; i < count; i++) {
const SDL_FRect *rect = &rects[i];
const GLfloat minx = rect->x;
const GLfloat maxx = rect->x + rect->w;
const GLfloat miny = rect->y;
const GLfloat maxy = rect->y + rect->h;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = miny;
*(verts++) = minx;
*(verts++) = maxy;
*(verts++) = maxx;
*(verts++) = maxy;
}
return 0;
}
static int
GLES_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
GLfloat minx, miny, maxx, maxy;
GLfloat minu, maxu, minv, maxv;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
minx = dstrect->x;
miny = dstrect->y;
maxx = dstrect->x + dstrect->w;
maxy = dstrect->y + dstrect->h;
minu = (GLfloat) srcrect->x / texture->w;
minu *= texturedata->texw;
maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
maxu *= texturedata->texw;
minv = (GLfloat) srcrect->y / texture->h;
minv *= texturedata->texh;
maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
maxv *= texturedata->texh;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = miny;
*(verts++) = minx;
*(verts++) = maxy;
*(verts++) = maxx;
*(verts++) = maxy;
*(verts++) = minu;
*(verts++) = minv;
*(verts++) = maxu;
*(verts++) = minv;
*(verts++) = minu;
*(verts++) = maxv;
*(verts++) = maxu;
*(verts++) = maxv;
return 0;
}
static int
GLES_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
GLfloat minx, miny, maxx, maxy;
GLfloat centerx, centery;
GLfloat minu, maxu, minv, maxv;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 19 * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
centerx = center->x;
centery = center->y;
if (flip & SDL_FLIP_HORIZONTAL) {
minx = dstrect->w - centerx;
maxx = -centerx;
}
else {
minx = -centerx;
maxx = dstrect->w - centerx;
}
if (flip & SDL_FLIP_VERTICAL) {
miny = dstrect->h - centery;
maxy = -centery;
}
else {
miny = -centery;
maxy = dstrect->h - centery;
}
minu = (GLfloat) srcquad->x / texture->w;
minu *= texturedata->texw;
maxu = (GLfloat) (srcquad->x + srcquad->w) / texture->w;
maxu *= texturedata->texw;
minv = (GLfloat) srcquad->y / texture->h;
minv *= texturedata->texh;
maxv = (GLfloat) (srcquad->y + srcquad->h) / texture->h;
maxv *= texturedata->texh;
cmd->data.draw.count = 1;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = miny;
*(verts++) = minx;
*(verts++) = maxy;
*(verts++) = maxx;
*(verts++) = maxy;
*(verts++) = minu;
*(verts++) = minv;
*(verts++) = maxu;
*(verts++) = minv;
*(verts++) = minu;
*(verts++) = maxv;
*(verts++) = maxu;
*(verts++) = maxv;
*(verts++) = (GLfloat) dstrect->x + centerx;
*(verts++) = (GLfloat) dstrect->y + centery;
*(verts++) = (GLfloat) angle;
return 0;
}
@@ -763,7 +667,7 @@ SetDrawState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
const Uint8 a = cmd->data.draw.a;
const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.color) {
const GLfloat fr = ((GLfloat) r) * inv255f;
@@ -865,7 +769,6 @@ static int
GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
size_t i;
if (GLES_ActivateRenderer(renderer) < 0) {
return -1;
@@ -874,7 +777,15 @@ GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vert
data->drawstate.target = renderer->target;
if (!renderer->target) {
SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
int w, h;
SDL_GL_GetDrawableSize(renderer->window, &w, &h);
if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
data->drawstate.viewport_dirty = SDL_TRUE; // if the window dimensions changed, invalidate the current viewport, etc.
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.drawablew = w;
data->drawstate.drawableh = h;
}
}
while (cmd) {
@@ -910,7 +821,7 @@ GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vert
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.clear_color) {
const GLfloat fr = ((GLfloat) r) * inv255f;
const GLfloat fg = ((GLfloat) g) * inv255f;
@@ -949,42 +860,38 @@ GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vert
break;
}
case SDL_RENDERCMD_FILL_RECTS: {
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
case SDL_RENDERCMD_COPY: /* unused */
break;
case SDL_RENDERCMD_COPY_EX: /* unused */
break;
case SDL_RENDERCMD_GEOMETRY: {
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
SDL_Texture *texture = cmd->data.draw.texture;
const size_t count = cmd->data.draw.count;
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
GLsizei offset = 0;
SetDrawState(data, cmd);
data->glVertexPointer(2, GL_FLOAT, 0, verts);
for (i = 0; i < count; ++i, offset += 4) {
data->glDrawArrays(GL_TRIANGLE_STRIP, offset, 4);
int stride = (2 + 4 + (texture ? 2 : 0)) * sizeof (float);
if (texture) {
SetCopyState(data, cmd);
} else {
SetDrawState(data, cmd);
}
break;
}
case SDL_RENDERCMD_COPY: {
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
SetCopyState(data, cmd);
data->glVertexPointer(2, GL_FLOAT, 0, verts);
data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
break;
}
data->glEnableClientState(GL_COLOR_ARRAY);
case SDL_RENDERCMD_COPY_EX: {
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
const GLfloat translatex = verts[16];
const GLfloat translatey = verts[17];
const GLfloat angle = verts[18];
SetCopyState(data, cmd);
data->glVertexPointer(2, GL_FLOAT, 0, verts);
data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
data->glVertexPointer(2, GL_FLOAT, stride, verts);
data->glColorPointer(4, GL_FLOAT, stride, verts + 2);
if (texture) {
data->glTexCoordPointer(2, GL_FLOAT, stride, verts + 2 + 4);
}
/* Translate to flip, rotate, translate to position */
data->glPushMatrix();
data->glTranslatef(translatex, translatey, 0.0f);
data->glRotatef(angle, 0.0, 0.0, 1.0);
data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
data->glPopMatrix();
data->glDrawArrays(GL_TRIANGLES, 0, (GLsizei) count);
data->glDisableClientState(GL_COLOR_ARRAY);
break;
}
@@ -1141,6 +1048,27 @@ static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
return 0;
}
static int
GLES_SetVSync(SDL_Renderer * renderer, const int vsync)
{
int retval;
if (vsync) {
retval = SDL_GL_SetSwapInterval(1);
} else {
retval = SDL_GL_SetSwapInterval(0);
}
if (retval != 0) {
return retval;
}
if (SDL_GL_GetSwapInterval() > 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
return retval;
}
static SDL_Renderer *
GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
{
@@ -1195,14 +1123,13 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->QueueSetDrawColor = GLES_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = GLES_QueueDrawPoints;
renderer->QueueDrawLines = GLES_QueueDrawLines;
renderer->QueueFillRects = GLES_QueueFillRects;
renderer->QueueCopy = GLES_QueueCopy;
renderer->QueueCopyEx = GLES_QueueCopyEx;
renderer->QueueGeometry = GLES_QueueGeometry;
renderer->RunCommandQueue = GLES_RunCommandQueue;
renderer->RenderReadPixels = GLES_RenderReadPixels;
renderer->RenderPresent = GLES_RenderPresent;
renderer->DestroyTexture = GLES_DestroyTexture;
renderer->DestroyRenderer = GLES_DestroyRenderer;
renderer->SetVSync = GLES_SetVSync;
renderer->GL_BindTexture = GLES_BindTexture;
renderer->GL_UnbindTexture = GLES_UnbindTexture;
renderer->info = GLES_RenderDriver.info;

View File

@@ -74,7 +74,6 @@ typedef struct GLES2_ProgramCacheEntry
GLuint vertex_shader;
GLuint fragment_shader;
GLuint uniform_locations[16];
Uint32 color;
GLfloat projection[4][4];
struct GLES2_ProgramCacheEntry *prev;
struct GLES2_ProgramCacheEntry *next;
@@ -90,16 +89,14 @@ typedef struct GLES2_ProgramCache
typedef enum
{
GLES2_ATTRIBUTE_POSITION = 0,
GLES2_ATTRIBUTE_TEXCOORD = 1,
GLES2_ATTRIBUTE_ANGLE = 2,
GLES2_ATTRIBUTE_CENTER = 3,
GLES2_ATTRIBUTE_COLOR = 1,
GLES2_ATTRIBUTE_TEXCOORD = 2,
} GLES2_Attribute;
typedef enum
{
GLES2_UNIFORM_PROJECTION,
GLES2_UNIFORM_TEXTURE,
GLES2_UNIFORM_COLOR,
GLES2_UNIFORM_TEXTURE_U,
GLES2_UNIFORM_TEXTURE_V
} GLES2_Uniform;
@@ -130,8 +127,6 @@ typedef struct
SDL_bool cliprect_dirty;
SDL_Rect cliprect;
SDL_bool texturing;
SDL_bool is_copy_ex;
Uint32 color;
Uint32 clear_color;
int drawablew;
int drawableh;
@@ -422,9 +417,8 @@ GLES2_CacheProgram(GLES2_RenderData *data, GLuint vertex, GLuint fragment)
data->glAttachShader(entry->id, vertex);
data->glAttachShader(entry->id, fragment);
data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_COLOR, "a_color");
data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle");
data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center");
data->glLinkProgram(entry->id);
data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
if (!linkSuccessful) {
@@ -443,10 +437,6 @@ GLES2_CacheProgram(GLES2_RenderData *data, GLuint vertex, GLuint fragment)
data->glGetUniformLocation(entry->id, "u_texture_u");
entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
data->glGetUniformLocation(entry->id, "u_texture");
entry->uniform_locations[GLES2_UNIFORM_COLOR] =
data->glGetUniformLocation(entry->id, "u_color");
entry->color = 0;
data->glUseProgram(entry->id);
if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] != -1) {
@@ -461,9 +451,6 @@ GLES2_CacheProgram(GLES2_RenderData *data, GLuint vertex, GLuint fragment)
if (entry->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
}
if (entry->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 0.0f, 0.0f, 0.0f, 0.0f);
}
/* Cache the linked program */
if (data->program_cache.head) {
@@ -582,10 +569,18 @@ GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG;
break;
case SDL_YUV_CONVERSION_BT601:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601;
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT601;
} else {
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT601;
}
break;
case SDL_YUV_CONVERSION_BT709:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709;
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT709;
} else {
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT709;
}
break;
default:
SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
@@ -667,17 +662,27 @@ GLES2_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
static int
GLES2_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
{
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
int color;
const size_t vertlen = (2 * sizeof (float) + sizeof (int)) * count;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
int i;
if (!verts) {
return -1;
}
if (colorswap == 0) {
color = (cmd->data.draw.r << 0) | (cmd->data.draw.g << 8) | (cmd->data.draw.b << 16) | ((Uint32)cmd->data.draw.a << 24);
} else {
color = (cmd->data.draw.r << 16) | (cmd->data.draw.g << 8) | (cmd->data.draw.b << 0) | ((Uint32)cmd->data.draw.a << 24);
}
cmd->data.draw.count = count;
for (i = 0; i < count; i++) {
*(verts++) = 0.5f + points[i].x;
*(verts++) = 0.5f + points[i].y;
*((int *)verts++) = color;
}
return 0;
@@ -686,211 +691,122 @@ GLES2_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL
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 color;
int i;
const size_t vertlen = (sizeof (GLfloat) * 2) * count;
GLfloat prevx, prevy;
const size_t vertlen = ((2 * sizeof (float)) + sizeof (int)) * count;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
/* Offset to hit the center of the pixel. */
for (i = 0; i < count; i++) {
*(verts++) = 0.5f + points[i].x;
*(verts++) = 0.5f + points[i].y;
if (colorswap == 0) {
color = (cmd->data.draw.r << 0) | (cmd->data.draw.g << 8) | (cmd->data.draw.b << 16) | ((Uint32)cmd->data.draw.a << 24);
} else {
color = (cmd->data.draw.r << 16) | (cmd->data.draw.g << 8) | (cmd->data.draw.b << 0) | ((Uint32)cmd->data.draw.a << 24);
}
/* Make the last line segment one pixel longer, to satisfy the
diamond-exit rule. */
verts -= 4;
{
const GLfloat xstart = verts[0];
const GLfloat ystart = verts[1];
const GLfloat xend = verts[2];
const GLfloat yend = verts[3];
cmd->data.draw.count = count;
if (ystart == yend) { /* horizontal line */
verts[(xend > xstart) ? 2 : 0] += 1.0f;
} else if (xstart == xend) { /* vertical line */
verts[(yend > ystart) ? 3 : 1] += 1.0f;
} else { /* bump a pixel in the direction we are moving in. */
const GLfloat deltax = xend - xstart;
const GLfloat deltay = yend - ystart;
const GLfloat angle = SDL_atan2f(deltay, deltax);
verts[2] += SDL_cosf(angle);
verts[3] += SDL_sinf(angle);
/* 0.5f offset to hit the center of the pixel. */
prevx = 0.5f + points->x;
prevy = 0.5f + points->y;
*(verts++) = prevx;
*(verts++) = prevy;
*((int *)verts++) = color;
/* 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;
*((int *)verts++) = color;
}
return 0;
}
static int
GLES2_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)
{
int i;
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
int count = indices ? num_indices : num_vertices;
const size_t vertlen = (2 * sizeof (float) + sizeof (int) + (texture ? 2 : 0) * sizeof (float)) * count;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
size_indices = indices ? size_indices : 0;
for (i = 0; i < count; i++) {
int j;
float *xy_;
int 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_ = *(int *)((char*)color + j * color_stride);
*(verts++) = xy_[0] * scale_x;
*(verts++) = xy_[1] * scale_y;
if (colorswap == 0) {
*((int *)verts++) = col_;
} else {
Uint8 r, g, b, a;
r = (col_ >> 0) & 0xff;
g = (col_ >> 8) & 0xff;
b = (col_ >> 16) & 0xff;
a = (col_ >> 24) & 0xff;
col_ = (r << 16) | (g << 8) | (b << 0) | ((Uint32)a << 24);
*((int *)verts++) = col_;
}
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
*(verts++) = uv_[0];
*(verts++) = uv_[1];
}
}
return 0;
}
static int
GLES2_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
{
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
int i;
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
for (i = 0; i < count; i++) {
const SDL_FRect *rect = &rects[i];
const GLfloat minx = rect->x;
const GLfloat maxx = rect->x + rect->w;
const GLfloat miny = rect->y;
const GLfloat maxy = rect->y + rect->h;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = miny;
*(verts++) = minx;
*(verts++) = maxy;
*(verts++) = maxx;
*(verts++) = maxy;
}
return 0;
}
static int
GLES2_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
GLfloat minx, miny, maxx, maxy;
GLfloat minu, maxu, minv, maxv;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
minx = dstrect->x;
miny = dstrect->y;
maxx = dstrect->x + dstrect->w;
maxy = dstrect->y + dstrect->h;
minu = (GLfloat) srcrect->x / texture->w;
maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
minv = (GLfloat) srcrect->y / texture->h;
maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = miny;
*(verts++) = minx;
*(verts++) = maxy;
*(verts++) = maxx;
*(verts++) = maxy;
*(verts++) = minu;
*(verts++) = minv;
*(verts++) = maxu;
*(verts++) = minv;
*(verts++) = minu;
*(verts++) = maxv;
*(verts++) = maxu;
*(verts++) = maxv;
return 0;
}
static int
GLES2_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
/* render expects cos value - 1 (see GLES2_Vertex_Default) */
const float radian_angle = (float)(M_PI * (360.0 - angle) / 180.0);
const GLfloat s = (GLfloat) SDL_sin(radian_angle);
const GLfloat c = (GLfloat) SDL_cos(radian_angle) - 1.0f;
const GLfloat centerx = center->x + dstrect->x;
const GLfloat centery = center->y + dstrect->y;
GLfloat minx, miny, maxx, maxy;
GLfloat minu, maxu, minv, maxv;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 32 * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
if (flip & SDL_FLIP_HORIZONTAL) {
minx = dstrect->x + dstrect->w;
maxx = dstrect->x;
} else {
minx = dstrect->x;
maxx = dstrect->x + dstrect->w;
}
if (flip & SDL_FLIP_VERTICAL) {
miny = dstrect->y + dstrect->h;
maxy = dstrect->y;
} else {
miny = dstrect->y;
maxy = dstrect->y + dstrect->h;
}
minu = ((GLfloat) srcquad->x) / ((GLfloat) texture->w);
maxu = ((GLfloat) (srcquad->x + srcquad->w)) / ((GLfloat) texture->w);
minv = ((GLfloat) srcquad->y) / ((GLfloat) texture->h);
maxv = ((GLfloat) (srcquad->y + srcquad->h)) / ((GLfloat) texture->h);
cmd->data.draw.count = 1;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = miny;
*(verts++) = minx;
*(verts++) = maxy;
*(verts++) = maxx;
*(verts++) = maxy;
*(verts++) = minu;
*(verts++) = minv;
*(verts++) = maxu;
*(verts++) = minv;
*(verts++) = minu;
*(verts++) = maxv;
*(verts++) = maxu;
*(verts++) = maxv;
*(verts++) = s;
*(verts++) = c;
*(verts++) = s;
*(verts++) = c;
*(verts++) = s;
*(verts++) = c;
*(verts++) = s;
*(verts++) = c;
*(verts++) = centerx;
*(verts++) = centery;
*(verts++) = centerx;
*(verts++) = centery;
*(verts++) = centerx;
*(verts++) = centery;
*(verts++) = centerx;
*(verts++) = centery;
return 0;
}
static int
SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc)
{
const SDL_bool was_copy_ex = data->drawstate.is_copy_ex;
const SDL_bool is_copy_ex = (cmd->command == SDL_RENDERCMD_COPY_EX);
SDL_Texture *texture = cmd->data.draw.texture;
const SDL_BlendMode blend = cmd->data.draw.blend;
GLES2_ProgramCacheEntry *program;
int stride = sizeof (GLfloat) * 2 /* position */ + sizeof (int) /* color */;
SDL_assert((texture != NULL) == (imgsrc != GLES2_IMAGESOURCE_SOLID));
@@ -961,7 +877,11 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I
}
if (texture) {
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (uintptr_t) (cmd->data.draw.first + (sizeof (GLfloat) * 8)));
stride += sizeof (GLfloat) * 2; /* tex coord */
}
if (texture) {
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *) (uintptr_t) (cmd->data.draw.first + sizeof (GLfloat) * (2 + 1)));
}
if (GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) {
@@ -977,17 +897,6 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I
}
}
if (program->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
if (data->drawstate.color != program->color) {
const Uint8 r = (data->drawstate.color >> 16) & 0xFF;
const Uint8 g = (data->drawstate.color >> 8) & 0xFF;
const Uint8 b = (data->drawstate.color >> 0) & 0xFF;
const Uint8 a = (data->drawstate.color >> 24) & 0xFF;
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
program->color = data->drawstate.color;
}
}
if (blend != data->drawstate.blend) {
if (blend == SDL_BLENDMODE_NONE) {
data->glDisable(GL_BLEND);
@@ -1004,23 +913,8 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I
}
/* all drawing commands use this */
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (uintptr_t) cmd->data.draw.first);
if (is_copy_ex != was_copy_ex) {
if (is_copy_ex) {
data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
} else {
data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
}
data->drawstate.is_copy_ex = is_copy_ex;
}
if (is_copy_ex) {
data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (uintptr_t) (cmd->data.draw.first + (sizeof (GLfloat) * 16)));
data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (uintptr_t) (cmd->data.draw.first + (sizeof (GLfloat) * 24)));
}
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *) (uintptr_t) cmd->data.draw.first);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE /* Normalized */, stride, (const GLvoid *) (uintptr_t) (cmd->data.draw.first + sizeof (GLfloat) * 2));
return 0;
}
@@ -1146,7 +1040,6 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
const int vboidx = data->current_vertex_buffer;
const GLuint vbo = data->vertex_buffers[vboidx];
size_t i;
if (GLES2_ActivateRenderer(renderer) < 0) {
return -1;
@@ -1154,7 +1047,14 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
data->drawstate.target = renderer->target;
if (!data->drawstate.target) {
SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
int w, h;
SDL_GL_GetDrawableSize(renderer->window, &w, &h);
if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
data->drawstate.viewport_dirty = SDL_TRUE; // if the window dimensions changed, invalidate the current viewport, etc.
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.drawablew = w;
data->drawstate.drawableh = h;
}
}
/* upload the new VBO data for this set of commands. */
@@ -1175,11 +1075,6 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
while (cmd) {
switch (cmd->command) {
case SDL_RENDERCMD_SETDRAWCOLOR: {
const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r;
const Uint8 g = cmd->data.color.g;
const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
data->drawstate.color = ((a << 24) | (r << 16) | (g << 8) | b);
break;
}
@@ -1211,7 +1106,7 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
const Uint8 g = cmd->data.color.g;
const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.clear_color) {
const GLfloat fr = ((GLfloat) r) * inv255f;
const GLfloat fg = ((GLfloat) g) * inv255f;
@@ -1230,38 +1125,88 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
break;
}
case SDL_RENDERCMD_DRAW_POINTS: {
if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
data->glDrawArrays(GL_POINTS, 0, (GLsizei) cmd->data.draw.count);
}
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
case SDL_RENDERCMD_COPY: /* unused */
break;
case SDL_RENDERCMD_COPY_EX: /* unused */
break;
}
case SDL_RENDERCMD_DRAW_LINES: {
const size_t count = cmd->data.draw.count;
SDL_assert(count >= 2);
if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
}
break;
}
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;
case SDL_RENDERCMD_FILL_RECTS: {
const size_t count = cmd->data.draw.count;
size_t offset = 0;
if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
for (i = 0; i < count; ++i, offset += 4) {
data->glDrawArrays(GL_TRIANGLE_STRIP, (GLsizei) offset, 4);
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_COPY:
case SDL_RENDERCMD_COPY_EX: {
if (SetCopyState(renderer, cmd) == 0) {
data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
case SDL_RENDERCMD_DRAW_POINTS:
case SDL_RENDERCMD_GEOMETRY: {
/* as long as we have the same copy command in a row, with the
same texture, we can combine them all into a single draw call. */
SDL_Texture *thistexture = cmd->data.draw.texture;
SDL_BlendMode thisblend = cmd->data.draw.blend;
const SDL_RenderCommandType thiscmdtype = cmd->command;
SDL_RenderCommand *finalcmd = cmd;
SDL_RenderCommand *nextcmd = cmd->next;
size_t count = cmd->data.draw.count;
int ret;
while (nextcmd != NULL) {
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != thiscmdtype) {
break; /* can't go any further on this draw call, different render command up next. */
} else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
break; /* can't go any further on this draw call, different texture/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;
}
if (thistexture) {
ret = SetCopyState(renderer, cmd);
} else {
ret = SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID);
}
if (ret == 0) {
int op = GL_TRIANGLES; /* SDL_RENDERCMD_GEOMETRY */
if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) {
op = GL_POINTS;
}
data->glDrawArrays(op, 0, (GLsizei) count);
}
cmd = finalcmd; /* skip any copy commands we just combined in here. */
break;
}
@@ -1882,6 +1827,26 @@ GLES2_RenderPresent(SDL_Renderer *renderer)
SDL_GL_SwapWindow(renderer->window);
}
static int
GLES2_SetVSync(SDL_Renderer * renderer, const int vsync)
{
int retval;
if (vsync) {
retval = SDL_GL_SetSwapInterval(1);
} else {
retval = SDL_GL_SetSwapInterval(0);
}
if (retval != 0) {
return retval;
}
if (SDL_GL_GetSwapInterval() > 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
return retval;
}
/*************************************************************************************************
* Bind/unbinding of textures
@@ -2056,14 +2021,13 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueSetDrawColor = GLES2_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = GLES2_QueueDrawPoints;
renderer->QueueDrawLines = GLES2_QueueDrawLines;
renderer->QueueFillRects = GLES2_QueueFillRects;
renderer->QueueCopy = GLES2_QueueCopy;
renderer->QueueCopyEx = GLES2_QueueCopyEx;
renderer->QueueGeometry = GLES2_QueueGeometry;
renderer->RunCommandQueue = GLES2_RunCommandQueue;
renderer->RenderReadPixels = GLES2_RenderReadPixels;
renderer->RenderPresent = GLES2_RenderPresent;
renderer->DestroyTexture = GLES2_DestroyTexture;
renderer->DestroyRenderer = GLES2_DestroyRenderer;
renderer->SetVSync = GLES2_SetVSync;
renderer->GL_BindTexture = GLES2_BindTexture;
renderer->GL_UnbindTexture = GLES2_UnbindTexture;
@@ -2081,12 +2045,12 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_COLOR);
data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
data->drawstate.blend = SDL_BLENDMODE_INVALID;
data->drawstate.color = 0xFFFFFFFF;
data->drawstate.clear_color = 0xFFFFFFFF;
data->drawstate.projection[3][0] = -1.0f;
data->drawstate.projection[3][3] = 1.0f;

View File

@@ -30,52 +30,43 @@
/*************************************************************************************************
* Vertex/fragment shader source *
*************************************************************************************************/
/* Notes on a_angle:
* It is a vector containing sin and cos for rotation matrix
* To get correct rotation for most cases when a_angle is disabled cos
value is decremented by 1.0 to get proper output with 0.0 which is
default value
*/
static const Uint8 GLES2_Vertex_Default[] = " \
uniform mat4 u_projection; \
attribute vec2 a_position; \
attribute vec4 a_color; \
attribute vec2 a_texCoord; \
attribute vec2 a_angle; \
attribute vec2 a_center; \
varying vec2 v_texCoord; \
varying vec4 v_color; \
\
void main() \
{ \
float s = a_angle[0]; \
float c = a_angle[1] + 1.0; \
mat2 rotationMatrix = mat2(c, -s, s, c); \
vec2 position = rotationMatrix * (a_position - a_center) + a_center; \
v_texCoord = a_texCoord; \
gl_Position = u_projection * vec4(position, 0.0, 1.0);\
gl_Position = u_projection * vec4(a_position, 0.0, 1.0);\
gl_PointSize = 1.0; \
v_color = a_color; \
} \
";
static const Uint8 GLES2_Fragment_Solid[] = " \
precision mediump float; \
uniform vec4 u_color; \
varying vec4 v_color; \
\
void main() \
{ \
gl_FragColor = u_color; \
gl_FragColor = v_color; \
} \
";
static const Uint8 GLES2_Fragment_TextureABGR[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform vec4 u_color; \
varying vec4 v_color; \
varying vec2 v_texCoord; \
\
void main() \
{ \
gl_FragColor = texture2D(u_texture, v_texCoord); \
gl_FragColor *= u_color; \
gl_FragColor *= v_color; \
} \
";
@@ -83,7 +74,7 @@ static const Uint8 GLES2_Fragment_TextureABGR[] = " \
static const Uint8 GLES2_Fragment_TextureARGB[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform vec4 u_color; \
varying vec4 v_color; \
varying vec2 v_texCoord; \
\
void main() \
@@ -92,7 +83,7 @@ static const Uint8 GLES2_Fragment_TextureARGB[] = " \
gl_FragColor = abgr; \
gl_FragColor.r = abgr.b; \
gl_FragColor.b = abgr.r; \
gl_FragColor *= u_color; \
gl_FragColor *= v_color; \
} \
";
@@ -100,7 +91,7 @@ static const Uint8 GLES2_Fragment_TextureARGB[] = " \
static const Uint8 GLES2_Fragment_TextureRGB[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform vec4 u_color; \
varying vec4 v_color; \
varying vec2 v_texCoord; \
\
void main() \
@@ -110,7 +101,7 @@ static const Uint8 GLES2_Fragment_TextureRGB[] = " \
gl_FragColor.r = abgr.b; \
gl_FragColor.b = abgr.r; \
gl_FragColor.a = 1.0; \
gl_FragColor *= u_color; \
gl_FragColor *= v_color; \
} \
";
@@ -118,7 +109,7 @@ static const Uint8 GLES2_Fragment_TextureRGB[] = " \
static const Uint8 GLES2_Fragment_TextureBGR[] = " \
precision mediump float; \
uniform sampler2D u_texture; \
uniform vec4 u_color; \
varying vec4 v_color; \
varying vec2 v_texCoord; \
\
void main() \
@@ -126,7 +117,7 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
vec4 abgr = texture2D(u_texture, v_texCoord); \
gl_FragColor = abgr; \
gl_FragColor.a = 1.0; \
gl_FragColor *= u_color; \
gl_FragColor *= v_color; \
} \
";
@@ -163,7 +154,7 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
"uniform sampler2D u_texture;\n" \
"uniform sampler2D u_texture_u;\n" \
"uniform sampler2D u_texture_v;\n" \
"uniform vec4 u_color;\n" \
"varying vec4 v_color;\n" \
"varying vec2 v_texCoord;\n" \
"\n" \
@@ -185,10 +176,10 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
"\n" \
" // That was easy. :) \n" \
" gl_FragColor = vec4(rgb, 1);\n" \
" gl_FragColor *= u_color;\n" \
" gl_FragColor *= v_color;\n" \
"}" \
#define NV12_SHADER_BODY \
#define NV12_RA_SHADER_BODY \
"\n" \
"void main()\n" \
"{\n" \
@@ -205,7 +196,27 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
"\n" \
" // That was easy. :) \n" \
" gl_FragColor = vec4(rgb, 1);\n" \
" gl_FragColor *= u_color;\n" \
" gl_FragColor *= v_color;\n" \
"}" \
#define NV12_RG_SHADER_BODY \
"\n" \
"void main()\n" \
"{\n" \
" mediump vec3 yuv;\n" \
" lowp vec3 rgb;\n" \
"\n" \
" // Get the YUV values \n" \
" yuv.x = texture2D(u_texture, v_texCoord).r;\n" \
" yuv.yz = texture2D(u_texture_u, v_texCoord).rg;\n" \
"\n" \
" // Do the color transform \n" \
" yuv += offset;\n" \
" rgb = matrix * yuv;\n" \
"\n" \
" // That was easy. :) \n" \
" gl_FragColor = vec4(rgb, 1);\n" \
" gl_FragColor *= v_color;\n" \
"}" \
#define NV21_SHADER_BODY \
@@ -225,7 +236,7 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
"\n" \
" // That was easy. :) \n" \
" gl_FragColor = vec4(rgb, 1);\n" \
" gl_FragColor *= u_color;\n" \
" gl_FragColor *= v_color;\n" \
"}" \
/* YUV to ABGR conversion */
@@ -249,17 +260,27 @@ static const Uint8 GLES2_Fragment_TextureYUVBT709[] = \
static const Uint8 GLES2_Fragment_TextureNV12JPEG[] = \
YUV_SHADER_PROLOGUE \
JPEG_SHADER_CONSTANTS \
NV12_SHADER_BODY \
NV12_RA_SHADER_BODY \
;
static const Uint8 GLES2_Fragment_TextureNV12BT601[] = \
static const Uint8 GLES2_Fragment_TextureNV12BT601_RA[] = \
YUV_SHADER_PROLOGUE \
BT601_SHADER_CONSTANTS \
NV12_SHADER_BODY \
NV12_RA_SHADER_BODY \
;
static const Uint8 GLES2_Fragment_TextureNV12BT709[] = \
static const Uint8 GLES2_Fragment_TextureNV12BT601_RG[] = \
YUV_SHADER_PROLOGUE \
BT601_SHADER_CONSTANTS \
NV12_RG_SHADER_BODY \
;
static const Uint8 GLES2_Fragment_TextureNV12BT709_RA[] = \
YUV_SHADER_PROLOGUE \
BT709_SHADER_CONSTANTS \
NV12_SHADER_BODY \
NV12_RA_SHADER_BODY \
;
static const Uint8 GLES2_Fragment_TextureNV12BT709_RG[] = \
YUV_SHADER_PROLOGUE \
BT709_SHADER_CONSTANTS \
NV12_RG_SHADER_BODY \
;
/* NV21 to ABGR conversion */
@@ -284,13 +305,13 @@ static const Uint8 GLES2_Fragment_TextureExternalOES[] = " \
#extension GL_OES_EGL_image_external : require\n\
precision mediump float; \
uniform samplerExternalOES u_texture; \
uniform vec4 u_color; \
varying vec4 v_color; \
varying vec2 v_texCoord; \
\
void main() \
{ \
gl_FragColor = texture2D(u_texture, v_texCoord); \
gl_FragColor *= u_color; \
gl_FragColor *= v_color; \
} \
";
@@ -322,10 +343,14 @@ const Uint8 *GLES2_GetShader(GLES2_ShaderType type)
return GLES2_Fragment_TextureYUVBT709;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG:
return GLES2_Fragment_TextureNV12JPEG;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601:
return GLES2_Fragment_TextureNV12BT601;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709:
return GLES2_Fragment_TextureNV12BT709;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT601:
return GLES2_Fragment_TextureNV12BT601_RA;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT601:
return GLES2_Fragment_TextureNV12BT601_RG;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT709:
return GLES2_Fragment_TextureNV12BT709_RA;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT709:
return GLES2_Fragment_TextureNV12BT709_RG;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG:
return GLES2_Fragment_TextureNV21JPEG;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601:

View File

@@ -38,16 +38,17 @@ typedef enum
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601,
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709,
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG,
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601,
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709,
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT601,
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT601,
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA_BT709,
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG_BT709,
GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG,
GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601,
GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709,
GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES
GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES,
GLES2_SHADER_COUNT
} GLES2_ShaderType;
#define GLES2_SHADER_COUNT 16
const Uint8 *GLES2_GetShader(GLES2_ShaderType type);
#endif /* SDL_VIDEO_RENDER_OGL_ES2 */

View File

@@ -56,6 +56,15 @@ static unsigned int __attribute__((aligned(16))) DisplayList[262144];
#define COL4444(r,g,b,a) ((r>>4) | ((g>>4)<<4) | ((b>>4)<<8) | ((a>>4)<<12))
#define COL8888(r,g,b,a) ((r) | ((g)<<8) | ((b)<<16) | ((a)<<24))
typedef struct
{
SDL_bool viewport_dirty;
SDL_Rect viewport;
SDL_bool cliprect_enabled_dirty;
SDL_bool cliprect_enabled;
SDL_bool cliprect_dirty;
SDL_Rect cliprect;
} PSP_DrawStateCache;
typedef struct
{
@@ -70,6 +79,7 @@ typedef struct
unsigned int currentColor;
int currentBlendMode;
PSP_DrawStateCache drawstate;
} PSP_RenderData;
@@ -98,9 +108,22 @@ typedef struct
{
float u, v;
float x, y, z;
} VertTV;
typedef struct
{
int col;
float x, y, z;
} VertCV;
typedef struct
{
float u, v;
int col;
float x, y, z;
} VertTCV;
#define PI 3.14159265358979f
#define radToDeg(x) ((x)*180.f/PI)
@@ -198,7 +221,7 @@ TextureSwizzle(PSP_TextureData *psp_texture)
unsigned int *src = (unsigned int*) psp_texture->data;
unsigned char *data = NULL;
data = malloc(psp_texture->size);
data = SDL_malloc(psp_texture->size);
int j;
@@ -223,7 +246,7 @@ TextureSwizzle(PSP_TextureData *psp_texture)
blockaddress += rowblocksadd;
}
free(psp_texture->data);
SDL_free(psp_texture->data);
psp_texture->data = data;
psp_texture->swizzled = SDL_TRUE;
@@ -249,7 +272,7 @@ int TextureUnswizzle(PSP_TextureData *psp_texture)
unsigned char *data = NULL;
data = malloc(psp_texture->size);
data = SDL_malloc(psp_texture->size);
if(!data)
return 0;
@@ -285,7 +308,7 @@ int TextureUnswizzle(PSP_TextureData *psp_texture)
ydst += dstrow;
}
free(psp_texture->data);
SDL_free(psp_texture->data);
psp_texture->data = data;
@@ -346,12 +369,6 @@ PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
return 0;
}
static int
PSP_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
return SDL_Unsupported();
}
void
TextureActivate(SDL_Texture * texture)
{
@@ -373,6 +390,9 @@ TextureActivate(SDL_Texture * texture)
sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
}
static int
PSP_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, void **pixels, int *pitch);
static int
PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
@@ -466,10 +486,98 @@ PSP_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_F
return 0;
}
static int
PSP_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)
{
int i;
int count = indices ? num_indices : num_vertices;
cmd->data.draw.count = count;
size_indices = indices ? size_indices : 0;
if (texture == NULL) {
VertCV *verts;
verts = (VertCV *) SDL_AllocateRenderVertices(renderer, count * sizeof (VertCV), 4, &cmd->data.draw.first);
if (!verts) {
return -1;
}
for (i = 0; i < count; i++) {
int j;
float *xy_;
int 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_ = *(int *)((char*)color + j * color_stride);
verts->x = xy_[0] * scale_x;
verts->y = xy_[1] * scale_y;
verts->z = 0;
verts->col = col_;
verts++;
}
} else {
PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
VertTCV *verts;
verts = (VertTCV *) SDL_AllocateRenderVertices(renderer, count * sizeof (VertTCV), 4, &cmd->data.draw.first);
if (!verts) {
return -1;
}
for (i = 0; i < count; i++) {
int j;
float *xy_;
int col_;
float *uv_;
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_ = *(int *)((char*)color + j * color_stride);
uv_ = (float *)((char*)uv + j * uv_stride);
verts->x = xy_[0] * scale_x;
verts->y = xy_[1] * scale_y;
verts->z = 0;
verts->col = col_;
verts->u = uv_[0] * psp_texture->textureWidth;
verts->v = uv_[1] * psp_texture->textureHeight;
verts++;
}
}
return 0;
}
static int
PSP_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
{
VertV *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (VertV), 4, &cmd->data.draw.first);
VertV *verts = (VertV *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (VertV), 4, &cmd->data.draw.first);
int i;
if (!verts) {
@@ -691,7 +799,6 @@ static int
PSP_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
size_t i;
StartDrawing(renderer);
@@ -740,7 +847,7 @@ PSP_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = ((a << 24) | (b << 16) | (g << 8) | r);
const Uint32 color = (((Uint32)a << 24) | (b << 16) | (g << 8) | r);
/* !!! FIXME: we could cache drawstate like clear color */
sceGuClearColor(color);
sceGuClearDepth(0);
@@ -755,7 +862,7 @@ PSP_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
const Uint8 a = cmd->data.draw.a;
const Uint32 color = ((a << 24) | (b << 16) | (g << 8) | r);
const Uint32 color = (((Uint32)a << 24) | (b << 16) | (g << 8) | r);
/* !!! FIXME: we could cache draw state like color, texturing, etc */
sceGuColor(color);
sceGuDisable(GU_TEXTURE_2D);
@@ -773,7 +880,7 @@ PSP_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
const Uint8 a = cmd->data.draw.a;
const Uint32 color = ((a << 24) | (b << 16) | (g << 8) | r);
const Uint32 color = (((Uint32)a << 24) | (b << 16) | (g << 8) | r);
/* !!! FIXME: we could cache draw state like color, texturing, etc */
sceGuColor(color);
sceGuDisable(GU_TEXTURE_2D);
@@ -791,7 +898,7 @@ PSP_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
const Uint8 a = cmd->data.draw.a;
const Uint32 color = ((a << 24) | (b << 16) | (g << 8) | r);
const Uint32 color = (((Uint32)a << 24) | (b << 16) | (g << 8) | r);
/* !!! FIXME: we could cache draw state like color, texturing, etc */
sceGuColor(color);
sceGuDisable(GU_TEXTURE_2D);
@@ -847,6 +954,25 @@ PSP_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
break;
}
case SDL_RENDERCMD_GEOMETRY: {
const size_t count = cmd->data.draw.count;
if (cmd->data.draw.texture == NULL) {
const VertCV *verts = (VertCV *) (gpumem + cmd->data.draw.first);
sceGuDisable(GU_TEXTURE_2D);
/* In GU_SMOOTH mode */
sceGuDrawArray(GU_TRIANGLES, GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, verts);
sceGuEnable(GU_TEXTURE_2D);
} else {
const VertTCV *verts = (VertTCV *) (gpumem + cmd->data.draw.first);
TextureActivate(cmd->data.draw.texture);
/* Need to force refresh of blending mode, probably something to FIXME */
PSP_SetBlendMode(renderer, SDL_BLENDMODE_INVALID);
PSP_SetBlendMode(renderer, cmd->data.draw.blend);
sceGuDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF|GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, verts);
}
break;
}
case SDL_RENDERCMD_NO_OP:
break;
}
@@ -921,6 +1047,14 @@ PSP_DestroyRenderer(SDL_Renderer * renderer)
SDL_free(renderer);
}
static int
PSP_SetVSync(SDL_Renderer * renderer, const int vsync)
{
PSP_RenderData *data = renderer->driverdata;
data->vsync = vsync;
return 0;
}
SDL_Renderer *
PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
{
@@ -944,7 +1078,6 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->WindowEvent = PSP_WindowEvent;
renderer->CreateTexture = PSP_CreateTexture;
renderer->SetTextureColorMod = PSP_SetTextureColorMod;
renderer->UpdateTexture = PSP_UpdateTexture;
renderer->LockTexture = PSP_LockTexture;
renderer->UnlockTexture = PSP_UnlockTexture;
@@ -954,6 +1087,7 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
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;
renderer->QueueCopyEx = PSP_QueueCopyEx;
@@ -962,6 +1096,7 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->RenderPresent = PSP_RenderPresent;
renderer->DestroyTexture = PSP_DestroyTexture;
renderer->DestroyRenderer = PSP_DestroyRenderer;
renderer->SetVSync = PSP_SetVSync;
renderer->info = PSP_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->driverdata = data;
@@ -1014,8 +1149,11 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
sceGuEnable(GU_SCISSOR_TEST);
/* Backface culling */
/*
FIXME: Culling probably un-needed ? It can conflict with SDL_RENDERCMD_GEOMETRY
sceGuFrontFace(GU_CCW);
sceGuEnable(GU_CULL_FACE);
*/
/* Texturing */
sceGuEnable(GU_TEXTURE_2D);

View File

@@ -618,10 +618,10 @@ do { \
while (height--) { \
{ int n = (width+3)/4; \
switch (width & 3) { \
case 0: do { op; pixel++; /* fallthrough */ \
case 3: op; pixel++; /* fallthrough */ \
case 2: op; pixel++; /* fallthrough */ \
case 1: op; pixel++; /* fallthrough */ \
case 0: do { op; pixel++; SDL_FALLTHROUGH; \
case 3: op; pixel++; SDL_FALLTHROUGH; \
case 2: op; pixel++; SDL_FALLTHROUGH; \
case 1: op; pixel++; \
} while ( --n > 0 ); \
} \
} \

View File

@@ -193,8 +193,8 @@ SDL_DrawLines(SDL_Surface * dst, const SDL_Point * points, int count,
continue;
}
/* Draw the end if it was clipped */
draw_end = (x2 != points[i].x || y2 != points[i].y);
/* Draw the end if the whole line is a single point or it was clipped */
draw_end = ((x1 == x2) && (y1 == y2)) || (x2 != points[i].x || y2 != points[i].y);
func(dst, x1, y1, x2, y2, color, draw_end);
}

View File

@@ -33,6 +33,7 @@
#include "SDL_drawline.h"
#include "SDL_drawpoint.h"
#include "SDL_rotate.h"
#include "SDL_triangle.h"
/* SDL surface based renderer implementation */
@@ -116,9 +117,8 @@ SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
texture->driverdata =
SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
Bmask, Amask);
SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
texture->b);
SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
SDL_SetSurfaceColorMod(texture->driverdata, texture->color.r, texture->color.g, texture->color.b);
SDL_SetSurfaceAlphaMod(texture->driverdata, texture->color.a);
SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
/* Only RLE encode textures without an alpha channel since the RLE coder
@@ -560,6 +560,104 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
return retval;
}
typedef struct GeometryFillData
{
SDL_Point dst;
SDL_Color color;
} GeometryFillData;
typedef struct GeometryCopyData
{
SDL_Point src;
SDL_Point dst;
SDL_Color color;
} GeometryCopyData;
static int
SW_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)
{
int i;
int count = indices ? num_indices : num_vertices;
void *verts;
int sz = texture ? sizeof (GeometryCopyData) : sizeof (GeometryFillData);
verts = (void *) SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
size_indices = indices ? size_indices : 0;
if (texture) {
GeometryCopyData *ptr = (GeometryCopyData *) verts;
for (i = 0; i < count; i++) {
int j;
float *xy_;
SDL_Color col_;
float *uv_;
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);
uv_ = (float *)((char*)uv + j * uv_stride);
ptr->src.x = (int)(uv_[0] * texture->w);
ptr->src.y = (int)(uv_[1] * texture->h);
ptr->dst.x = (int)(xy_[0] * scale_x + renderer->viewport.x);
ptr->dst.y = (int)(xy_[1] * scale_y + renderer->viewport.y);
trianglepoint_2_fixedpoint(&ptr->dst);
ptr->color = col_;
ptr++;
}
} else {
GeometryFillData *ptr = (GeometryFillData *) verts;
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);
ptr->dst.x = (int)(xy_[0] * scale_x + renderer->viewport.x);
ptr->dst.y = (int)(xy_[1] * scale_y + renderer->viewport.y);
trianglepoint_2_fixedpoint(&ptr->dst);
ptr->color = col_;
ptr++;
}
}
return 0;
}
static void
PrepTextureForCopy(const SDL_RenderCommand *cmd)
{
@@ -634,7 +732,7 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
}
case SDL_RENDERCMD_SETCLIPRECT: {
drawstate.cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
drawstate.cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
drawstate.surface_cliprect_dirty = SDL_TRUE;
break;
}
@@ -734,6 +832,38 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
break;
}
case SDL_RENDERCMD_GEOMETRY: {
int i;
SDL_Rect *verts = (SDL_Rect *) (((Uint8 *) vertices) + cmd->data.draw.first);
const int count = (int) cmd->data.draw.count;
SDL_Texture *texture = cmd->data.draw.texture;
const SDL_BlendMode blend = cmd->data.draw.blend;
SetDrawState(surface, &drawstate);
if (texture) {
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
GeometryCopyData *ptr = (GeometryCopyData *) verts;
PrepTextureForCopy(cmd);
for (i = 0; i < count; i += 3, ptr += 3) {
SDL_SW_BlitTriangle(
src,
&(ptr[0].src), &(ptr[1].src), &(ptr[2].src),
surface,
&(ptr[0].dst), &(ptr[1].dst), &(ptr[2].dst),
ptr[0].color, ptr[1].color, ptr[2].color);
}
} else {
GeometryFillData *ptr = (GeometryFillData *) verts;
for (i = 0; i < count; i += 3, ptr += 3) {
SDL_SW_FillTriangle(surface, &(ptr[0].dst), &(ptr[1].dst), &(ptr[2].dst), blend, ptr[0].color, ptr[1].color, ptr[2].color);
}
}
break;
}
case SDL_RENDERCMD_NO_OP:
break;
}
@@ -843,6 +973,7 @@ SW_CreateRendererForSurface(SDL_Surface * surface)
renderer->QueueFillRects = SW_QueueFillRects;
renderer->QueueCopy = SW_QueueCopy;
renderer->QueueCopyEx = SW_QueueCopyEx;
renderer->QueueGeometry = SW_QueueGeometry;
renderer->RunCommandQueue = SW_RunCommandQueue;
renderer->RenderReadPixels = SW_RenderReadPixels;
renderer->RenderPresent = SW_RenderPresent;
@@ -859,9 +990,22 @@ SW_CreateRendererForSurface(SDL_Surface * surface)
static SDL_Renderer *
SW_CreateRenderer(SDL_Window * window, Uint32 flags)
{
const char *hint;
SDL_Surface *surface;
/* Set the vsync hint based on our flags, if it's not already set */
hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC);
if (!hint || !*hint) {
SDL_SetHint(SDL_HINT_RENDER_VSYNC, (flags & SDL_RENDERER_PRESENTVSYNC) ? "1" : "0");
}
surface = SDL_GetWindowSurface(window);
/* Reset the vsync hint if we set it above */
if (!hint || !*hint) {
SDL_SetHint(SDL_HINT_RENDER_VSYNC, "");
}
if (!surface) {
return NULL;
}
@@ -872,7 +1016,7 @@ SDL_RenderDriver SW_RenderDriver = {
SW_CreateRenderer,
{
"software",
SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE,
SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
8,
{
SDL_PIXELFORMAT_ARGB8888,

View File

@@ -184,7 +184,7 @@ computeSourceIncrements90(SDL_Surface * src, int bpp, int angle, int flipx, int
if (signy < 0) sp += (src->h-1)*src->pitch; \
\
for (dy = 0; dy < dst->h; sp += sincy, dp += dincy, dy++) { \
if (sincx == sizeof(pixelType)) { /* if advancing src and dest equally, use memcpy */ \
if (sincx == sizeof(pixelType)) { /* if advancing src and dest equally, use SDL_memcpy */ \
SDL_memcpy(dp, sp, dst->w*sizeof(pixelType)); \
sp += dst->w*sizeof(pixelType); \
dp += dst->w*sizeof(pixelType); \
@@ -439,7 +439,7 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
if (!(is8bit || (src->format->BitsPerPixel == 32 && src->format->Amask)))
return NULL;
/* Calculate target factors from sin/cos and zoom */
/* Calculate target factors from sine/cosine and zoom */
sangleinv = sangle*65536.0;
cangleinv = cangle*65536.0;

View File

@@ -0,0 +1,828 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_RENDER_SW && !SDL_RENDER_DISABLED
#include "SDL_surface.h"
#include "SDL_triangle.h"
#include "../../video/SDL_blit.h"
/* fixed points bits precision
* Set to 1, so that it can start rendering wth middle of a pixel precision.
* It doesn't need to be increased.
* But, if increased too much, it overflows (srcx, srcy) coordinates used for filling with texture.
* (which could be turned to int64).
*/
#define FP_BITS 1
#define COLOR_EQ(c1, c2) ((c1).r == (c2).r && (c1).g == (c2).g && (c1).b == (c2).b && (c1).a == (c2).a)
static void SDL_BlitTriangle_Slow(SDL_BlitInfo * info,
SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2,
int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x,
int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row,
SDL_Color c0, SDL_Color c1, SDL_Color c2, int is_uniform);
#if 0
int SDL_BlitTriangle(SDL_Surface *src, const SDL_Point srcpoints[3], SDL_Surface *dst, const SDL_Point dstpoints[3])
{
int i;
SDL_Point points[6];
if (src == NULL || dst == NULL) {
return -1;
}
for (i = 0; i < 3; i++) {
if (srcpoints[i].x < 0 || srcpoints[i].y < 0 || srcpoints[i].x >= src->w || srcpoints[i].y >= src->h) {
return SDL_SetError("Values of 'srcpoints' out of bounds");
}
}
points[0] = srcpoints[0];
points[1] = dstpoints[0];
points[2] = srcpoints[1];
points[3] = dstpoints[1];
points[4] = srcpoints[2];
points[5] = dstpoints[2];
for (i = 0; i < 3; i++) {
trianglepoint_2_fixedpoint(&points[2 * i + 1]);
}
return SDL_SW_BlitTriangle(src, dst, points);
}
int SDL_FillTriangle(SDL_Surface *dst, const SDL_Point points[3], Uint32 color)
{
int i;
SDL_Point points_tmp[3];
if (dst == NULL) {
return -1;
}
for (i = 0; i < 3; i++) {
points_tmp[i] = points[i];
trianglepoint_2_fixedpoint(&points_tmp[i]);
}
return SDL_SW_FillTriangle(dst, points_tmp, SDL_BLENDMODE_NONE, color);
}
#endif
/* cross product AB x AC */
static int cross_product(const SDL_Point *a, const SDL_Point *b, int c_x, int c_y)
{
return (b->x - a->x) * (c_y - a->y) - (b->y - a->y) * (c_x - a->x);
}
/* check for top left rules */
static int is_top_left(const SDL_Point *a, const SDL_Point *b, int is_clockwise)
{
if (is_clockwise) {
if (a->y == b->y && a->x < b->x) {
return 1;
}
if (b->y < a->y) {
return 1;
}
} else {
if (a->y == b->y && b->x < a->x) {
return 1;
}
if (a->y < b->y) {
return 1;
}
}
return 0;
}
void trianglepoint_2_fixedpoint(SDL_Point *a) {
a->x <<= FP_BITS;
a->y <<= FP_BITS;
}
/* bounding rect of three points */
static void bounding_rect(const SDL_Point *a, const SDL_Point *b, const SDL_Point *c, SDL_Rect *r)
{
int min_x = SDL_min(a->x, SDL_min(b->x, c->x));
int max_x = SDL_max(a->x, SDL_max(b->x, c->x));
int min_y = SDL_min(a->y, SDL_min(b->y, c->y));
int max_y = SDL_max(a->y, SDL_max(b->y, c->y));
/* points are in fixed point, shift back */
r->x = min_x >> FP_BITS;
r->y = min_y >> FP_BITS;
r->w = (max_x - min_x) >> FP_BITS;
r->h = (max_y - min_y) >> FP_BITS;
}
/* Triangle rendering, using Barycentric coordinates (w0, w1, w2)
*
* The cross product isn't computed from scratch at each iteration,
* but optimized using constant step increments
*
*/
#define TRIANGLE_BEGIN_LOOP \
{ \
int x, y; \
for (y = 0; y < dstrect.h; y++) { \
/* y start */ \
int w0 = w0_row; \
int w1 = w1_row; \
int w2 = w2_row; \
for (x = 0; x < dstrect.w; x++) { \
/* In triangle */ \
if (w0 + bias_w0 >= 0 && w1 + bias_w1 >= 0 && w2 + bias_w2 >= 0) { \
Uint8 *dptr = (Uint8 *) dst_ptr + x * dstbpp; \
/* Use 64 bits precision to prevent overflow when interpolating color / texture with wide triangles */
#define TRIANGLE_GET_TEXTCOORD \
int srcx = (int)(((Sint64)w0 * s2s0_x + (Sint64)w1 * s2s1_x + s2_x_area.x) / area); \
int srcy = (int)(((Sint64)w0 * s2s0_y + (Sint64)w1 * s2s1_y + s2_x_area.y) / area); \
#define TRIANGLE_GET_MAPPED_COLOR \
int r = (int)(((Sint64)w0 * c0.r + (Sint64)w1 * c1.r + (Sint64)w2 * c2.r) / area); \
int g = (int)(((Sint64)w0 * c0.g + (Sint64)w1 * c1.g + (Sint64)w2 * c2.g) / area); \
int b = (int)(((Sint64)w0 * c0.b + (Sint64)w1 * c1.b + (Sint64)w2 * c2.b) / area); \
int a = (int)(((Sint64)w0 * c0.a + (Sint64)w1 * c1.a + (Sint64)w2 * c2.a) / area); \
int color = SDL_MapRGBA(format, r, g, b, a); \
#define TRIANGLE_GET_COLOR \
int r = (int)(((Sint64)w0 * c0.r + (Sint64)w1 * c1.r + (Sint64)w2 * c2.r) / area); \
int g = (int)(((Sint64)w0 * c0.g + (Sint64)w1 * c1.g + (Sint64)w2 * c2.g) / area); \
int b = (int)(((Sint64)w0 * c0.b + (Sint64)w1 * c1.b + (Sint64)w2 * c2.b) / area); \
int a = (int)(((Sint64)w0 * c0.a + (Sint64)w1 * c1.a + (Sint64)w2 * c2.a) / area); \
#define TRIANGLE_END_LOOP \
} \
/* x += 1 */ \
w0 += d2d1_y; \
w1 += d0d2_y; \
w2 += d1d0_y; \
} \
/* y += 1 */ \
w0_row += d1d2_x; \
w1_row += d2d0_x; \
w2_row += d0d1_x; \
dst_ptr += dst_pitch; \
} \
} \
int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, SDL_BlendMode blend, SDL_Color c0, SDL_Color c1, SDL_Color c2)
{
int ret = 0;
int dst_locked = 0;
SDL_Rect dstrect;
int dstbpp;
Uint8 *dst_ptr;
int dst_pitch;
int area, is_clockwise;
int d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x;
int w0_row, w1_row, w2_row;
int bias_w0, bias_w1, bias_w2;
int is_uniform;
SDL_Surface *tmp = NULL;
if (dst == NULL) {
return -1;
}
area = cross_product(d0, d1, d2->x, d2->y);
is_uniform = COLOR_EQ(c0, c1) && COLOR_EQ(c1, c2);
/* Flat triangle */
if (area == 0) {
return 0;
}
/* Lock the destination, if needed */
if (SDL_MUSTLOCK(dst)) {
if (SDL_LockSurface(dst) < 0) {
ret = -1;
goto end;
} else {
dst_locked = 1;
}
}
bounding_rect(d0, d1, d2, &dstrect);
{
/* Clip triangle rect with surface rect */
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = dst->w;
rect.h = dst->h;
SDL_IntersectRect(&dstrect, &rect, &dstrect);
}
{
/* Clip triangle with surface clip rect */
SDL_Rect rect;
SDL_GetClipRect(dst, &rect);
SDL_IntersectRect(&dstrect, &rect, &dstrect);
}
if (blend != SDL_BLENDMODE_NONE) {
int format = dst->format->format;
/* need an alpha format */
if (! dst->format->Amask) {
format = SDL_PIXELFORMAT_ARGB8888;
}
/* Use an intermediate surface */
tmp = SDL_CreateRGBSurfaceWithFormat(0, dstrect.w, dstrect.h, 0, format);
if (tmp == NULL) {
ret = -1;
goto end;
}
if (blend == SDL_BLENDMODE_MOD) {
Uint32 c = SDL_MapRGBA(tmp->format, 255, 255, 255, 255);
SDL_FillRect(tmp, NULL, c);
}
SDL_SetSurfaceBlendMode(tmp, blend);
dstbpp = tmp->format->BytesPerPixel;
dst_ptr = tmp->pixels;
dst_pitch = tmp->pitch;
} else {
/* Write directly to destination surface */
dstbpp = dst->format->BytesPerPixel;
dst_ptr = (Uint8 *)dst->pixels + dstrect.x * dstbpp + dstrect.y * dst->pitch;
dst_pitch = dst->pitch;
}
is_clockwise = area > 0;
area = SDL_abs(area);
d2d1_y = (d1->y - d2->y) << FP_BITS;
d0d2_y = (d2->y - d0->y) << FP_BITS;
d1d0_y = (d0->y - d1->y) << FP_BITS;
d1d2_x = (d2->x - d1->x) << FP_BITS;
d2d0_x = (d0->x - d2->x) << FP_BITS;
d0d1_x = (d1->x - d0->x) << FP_BITS;
/* Starting point for rendering, at the middle of a pixel */
{
SDL_Point p;
p.x = dstrect.x;
p.y = dstrect.y;
trianglepoint_2_fixedpoint(&p);
p.x += (1 << FP_BITS) / 2;
p.y += (1 << FP_BITS) / 2;
w0_row = cross_product(d1, d2, p.x, p.y);
w1_row = cross_product(d2, d0, p.x, p.y);
w2_row = cross_product(d0, d1, p.x, p.y);
}
/* Handle anti-clockwise triangles */
if (! is_clockwise) {
d2d1_y *= -1;
d0d2_y *= -1;
d1d0_y *= -1;
d1d2_x *= -1;
d2d0_x *= -1;
d0d1_x *= -1;
w0_row *= -1;
w1_row *= -1;
w2_row *= -1;
}
/* Add a bias to respect top-left rasterization rule */
bias_w0 = (is_top_left(d1, d2, is_clockwise) ? 0 : -1);
bias_w1 = (is_top_left(d2, d0, is_clockwise) ? 0 : -1);
bias_w2 = (is_top_left(d0, d1, is_clockwise) ? 0 : -1);
if (is_uniform) {
Uint32 color;
if (tmp) {
if (dst->format->Amask) {
color = SDL_MapRGBA(tmp->format, c0.r, c0.g, c0.b, c0.a);
} else {
//color = SDL_MapRGB(tmp->format, c0.r, c0.g, c0.b);
color = SDL_MapRGBA(tmp->format, c0.r, c0.g, c0.b, c0.a);
}
} else {
color = SDL_MapRGBA(dst->format, c0.r, c0.g, c0.b, c0.a);
}
if (dstbpp == 4) {
TRIANGLE_BEGIN_LOOP
{
*(Uint32 *)dptr = color;
}
TRIANGLE_END_LOOP
} else if (dstbpp == 3) {
TRIANGLE_BEGIN_LOOP
{
Uint8 *s = (Uint8*)&color;
dptr[0] = s[0];
dptr[1] = s[1];
dptr[2] = s[2];
}
TRIANGLE_END_LOOP
} else if (dstbpp == 2) {
TRIANGLE_BEGIN_LOOP
{
*(Uint16 *)dptr = color;
}
TRIANGLE_END_LOOP
} else if (dstbpp == 1) {
TRIANGLE_BEGIN_LOOP
{
*dptr = color;
}
TRIANGLE_END_LOOP
}
} else {
SDL_PixelFormat *format = dst->format;
if (tmp) {
format = tmp->format;
}
if (dstbpp == 4) {
TRIANGLE_BEGIN_LOOP
{
TRIANGLE_GET_MAPPED_COLOR
*(Uint32 *)dptr = color;
}
TRIANGLE_END_LOOP
} else if (dstbpp == 3) {
TRIANGLE_BEGIN_LOOP
{
TRIANGLE_GET_MAPPED_COLOR
Uint8 *s = (Uint8*)&color;
dptr[0] = s[0];
dptr[1] = s[1];
dptr[2] = s[2];
}
TRIANGLE_END_LOOP
} else if (dstbpp == 2) {
TRIANGLE_BEGIN_LOOP
{
TRIANGLE_GET_MAPPED_COLOR
*(Uint16 *)dptr = color;
}
TRIANGLE_END_LOOP
} else if (dstbpp == 1) {
TRIANGLE_BEGIN_LOOP
{
TRIANGLE_GET_MAPPED_COLOR
*dptr = color;
}
TRIANGLE_END_LOOP
}
}
if (tmp) {
SDL_BlitSurface(tmp, NULL, dst, &dstrect);
SDL_FreeSurface(tmp);
}
end:
if (dst_locked) {
SDL_UnlockSurface(dst);
}
return ret;
}
int SDL_SW_BlitTriangle(
SDL_Surface *src,
SDL_Point *s0, SDL_Point *s1, SDL_Point *s2,
SDL_Surface *dst,
SDL_Point *d0, SDL_Point *d1, SDL_Point *d2,
SDL_Color c0, SDL_Color c1, SDL_Color c2)
{
int ret = 0;
int src_locked = 0;
int dst_locked = 0;
SDL_BlendMode blend;
SDL_Rect srcrect;
SDL_Rect dstrect;
SDL_Point s2_x_area;
int dstbpp;
Uint8 *dst_ptr;
int dst_pitch;
int *src_ptr;
int src_pitch;
int area, is_clockwise;
int d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x;
int s2s0_x, s2s1_x, s2s0_y, s2s1_y;
int w0_row, w1_row, w2_row;
int bias_w0, bias_w1, bias_w2;
int is_uniform;
int has_modulation;
if (src == NULL || dst == NULL) {
return -1;
}
area = cross_product(d0, d1, d2->x, d2->y);
/* Flat triangle */
if (area == 0) {
return 0;
}
/* Lock the destination, if needed */
if (SDL_MUSTLOCK(dst)) {
if (SDL_LockSurface(dst) < 0) {
ret = -1;
goto end;
} else {
dst_locked = 1;
}
}
/* Lock the source, if needed */
if (SDL_MUSTLOCK(src)) {
if (SDL_LockSurface(src) < 0) {
ret = -1;
goto end;
} else {
src_locked = 1;
}
}
is_uniform = COLOR_EQ(c0, c1) && COLOR_EQ(c1, c2);
bounding_rect(s0, s1, s2, &srcrect);
bounding_rect(d0, d1, d2, &dstrect);
SDL_GetSurfaceBlendMode(src, &blend);
if (is_uniform) {
// SDL_GetSurfaceColorMod(src, &r, &g, &b);
has_modulation = c0.r != 255 || c0.g != 255 || c0.b != 255 || c0.a != 255;;
} else {
has_modulation = SDL_TRUE;
}
{
/* Clip triangle rect with surface rect */
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = dst->w;
rect.h = dst->h;
SDL_IntersectRect(&dstrect, &rect, &dstrect);
}
{
/* Clip triangle with surface clip rect */
SDL_Rect rect;
SDL_GetClipRect(dst, &rect);
SDL_IntersectRect(&dstrect, &rect, &dstrect);
}
/* Set destination pointer */
dstbpp = dst->format->BytesPerPixel;
dst_ptr = (Uint8 *)dst->pixels + dstrect.x * dstbpp + dstrect.y * dst->pitch;
dst_pitch = dst->pitch;
/* Set source pointer */
src_ptr = src->pixels;
src_pitch = src->pitch;
is_clockwise = area > 0;
area = SDL_abs(area);
d2d1_y = (d1->y - d2->y) << FP_BITS;
d0d2_y = (d2->y - d0->y) << FP_BITS;
d1d0_y = (d0->y - d1->y) << FP_BITS;
d1d2_x = (d2->x - d1->x) << FP_BITS;
d2d0_x = (d0->x - d2->x) << FP_BITS;
d0d1_x = (d1->x - d0->x) << FP_BITS;
s2s0_x = s0->x - s2->x;
s2s1_x = s1->x - s2->x;
s2s0_y = s0->y - s2->y;
s2s1_y = s1->y - s2->y;
/* Starting point for rendering, at the middle of a pixel */
{
SDL_Point p;
p.x = dstrect.x;
p.y = dstrect.y;
trianglepoint_2_fixedpoint(&p);
p.x += (1 << FP_BITS) / 2;
p.y += (1 << FP_BITS) / 2;
w0_row = cross_product(d1, d2, p.x, p.y);
w1_row = cross_product(d2, d0, p.x, p.y);
w2_row = cross_product(d0, d1, p.x, p.y);
}
/* Handle anti-clockwise triangles */
if (! is_clockwise) {
d2d1_y *= -1;
d0d2_y *= -1;
d1d0_y *= -1;
d1d2_x *= -1;
d2d0_x *= -1;
d0d1_x *= -1;
w0_row *= -1;
w1_row *= -1;
w2_row *= -1;
}
/* Add a bias to respect top-left rasterization rule */
bias_w0 = (is_top_left(d1, d2, is_clockwise) ? 0 : -1);
bias_w1 = (is_top_left(d2, d0, is_clockwise) ? 0 : -1);
bias_w2 = (is_top_left(d0, d1, is_clockwise) ? 0 : -1);
/* precompute constant 's2->x * area' used in TRIANGLE_GET_TEXTCOORD */
s2_x_area.x = s2->x * area;
s2_x_area.y = s2->y * area;
if (blend != SDL_BLENDMODE_NONE || src->format->format != dst->format->format || has_modulation || ! is_uniform) {
/* Use SDL_BlitTriangle_Slow */
SDL_BlitInfo *info = &src->map->info;
SDL_BlitInfo tmp_info;
SDL_zero(tmp_info);
tmp_info.src_fmt = src->format;
tmp_info.dst_fmt = dst->format;
tmp_info.flags = info->flags;
/*
tmp_info.r = info->r;
tmp_info.g = info->g;
tmp_info.b = info->b;
tmp_info.a = info->a;
*/
tmp_info.r = c0.r;
tmp_info.g = c0.g;
tmp_info.b = c0.b;
tmp_info.a = c0.a;
tmp_info.flags &= ~(SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA);
if (c0.r != 255 || c1.r != 255 || c2.r != 255 ||
c0.g != 255 || c1.g != 255 || c2.g != 255 ||
c0.b != 255 || c1.b != 255 || c2.b != 255) {
tmp_info.flags |= SDL_COPY_MODULATE_COLOR;
}
if (c0.a != 255 || c1.a != 255 || c2.a != 255) {
tmp_info.flags |= SDL_COPY_MODULATE_ALPHA;
}
tmp_info.colorkey = info->colorkey;
/* src */
tmp_info.src = (Uint8 *) src_ptr;
tmp_info.src_pitch = src_pitch;
/* dst */
tmp_info.dst = (Uint8 *) dst_ptr;
tmp_info.dst_pitch = dst_pitch;
SDL_BlitTriangle_Slow(&tmp_info, s2_x_area, dstrect, area, bias_w0, bias_w1, bias_w2,
d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x,
s2s0_x, s2s1_x, s2s0_y, s2s1_y, w0_row, w1_row, w2_row,
c0, c1, c2, is_uniform);
goto end;
}
if (dstbpp == 4) {
TRIANGLE_BEGIN_LOOP
{
TRIANGLE_GET_TEXTCOORD
Uint32 *sptr = (Uint32 *)((Uint8 *) src_ptr + srcy * src_pitch);
*(Uint32 *)dptr = sptr[srcx];
}
TRIANGLE_END_LOOP
} else if (dstbpp == 3) {
TRIANGLE_BEGIN_LOOP
{
TRIANGLE_GET_TEXTCOORD
Uint8 *sptr = (Uint8 *)((Uint8 *) src_ptr + srcy * src_pitch);
dptr[0] = sptr[3 * srcx];
dptr[1] = sptr[3 * srcx + 1];
dptr[2] = sptr[3 * srcx + 2];
}
TRIANGLE_END_LOOP
} else if (dstbpp == 2) {
TRIANGLE_BEGIN_LOOP
{
TRIANGLE_GET_TEXTCOORD
Uint16 *sptr = (Uint16 *)((Uint8 *) src_ptr + srcy * src_pitch);
*(Uint16 *)dptr = sptr[srcx];
}
TRIANGLE_END_LOOP
} else if (dstbpp == 1) {
TRIANGLE_BEGIN_LOOP
{
TRIANGLE_GET_TEXTCOORD
Uint8 *sptr = (Uint8 *)((Uint8 *) src_ptr + srcy * src_pitch);
*dptr = sptr[srcx];
}
TRIANGLE_END_LOOP
}
end:
if (dst_locked) {
SDL_UnlockSurface(dst);
}
if (src_locked) {
SDL_UnlockSurface(src);
}
return ret;
}
static void
SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2,
int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x,
int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row,
SDL_Color c0, SDL_Color c1, SDL_Color c2, int is_uniform)
{
const int flags = info->flags;
Uint32 modulateR = info->r;
Uint32 modulateG = info->g;
Uint32 modulateB = info->b;
Uint32 modulateA = info->a;
Uint32 srcpixel;
Uint32 srcR, srcG, srcB, srcA;
Uint32 dstpixel;
Uint32 dstR, dstG, dstB, dstA;
SDL_PixelFormat *src_fmt = info->src_fmt;
SDL_PixelFormat *dst_fmt = info->dst_fmt;
int srcbpp = src_fmt->BytesPerPixel;
int dstbpp = dst_fmt->BytesPerPixel;
Uint32 rgbmask = ~src_fmt->Amask;
Uint32 ckey = info->colorkey & rgbmask;
Uint8 *dst_ptr = info->dst;
int dst_pitch = info->dst_pitch;;
TRIANGLE_BEGIN_LOOP
{
Uint8 *src;
Uint8 *dst = dptr;
TRIANGLE_GET_TEXTCOORD
src = (info->src + (srcy * info->src_pitch) + (srcx * srcbpp));
if (src_fmt->Amask) {
DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
srcB, srcA);
} else {
DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
srcB);
srcA = 0xFF;
}
if (flags & SDL_COPY_COLORKEY) {
/* srcpixel isn't set for 24 bpp */
if (srcbpp == 3) {
srcpixel = (srcR << src_fmt->Rshift) |
(srcG << src_fmt->Gshift) | (srcB << src_fmt->Bshift);
}
if ((srcpixel & rgbmask) == ckey) {
continue;
}
}
if (dst_fmt->Amask) {
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
dstB, dstA);
} else {
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
dstB);
dstA = 0xFF;
}
if (! is_uniform) {
TRIANGLE_GET_COLOR
modulateR = r;
modulateG = g;
modulateB = b;
modulateA = a;
}
if (flags & SDL_COPY_MODULATE_COLOR) {
srcR = (srcR * modulateR) / 255;
srcG = (srcG * modulateG) / 255;
srcB = (srcB * modulateB) / 255;
}
if (flags & SDL_COPY_MODULATE_ALPHA) {
srcA = (srcA * modulateA) / 255;
}
if (flags & (SDL_COPY_BLEND | SDL_COPY_ADD)) {
/* This goes away if we ever use premultiplied alpha */
if (srcA < 255) {
srcR = (srcR * srcA) / 255;
srcG = (srcG * srcA) / 255;
srcB = (srcB * srcA) / 255;
}
}
switch (flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) {
case 0:
dstR = srcR;
dstG = srcG;
dstB = srcB;
dstA = srcA;
break;
case SDL_COPY_BLEND:
dstR = srcR + ((255 - srcA) * dstR) / 255;
dstG = srcG + ((255 - srcA) * dstG) / 255;
dstB = srcB + ((255 - srcA) * dstB) / 255;
dstA = srcA + ((255 - srcA) * dstA) / 255;
break;
case SDL_COPY_ADD:
dstR = srcR + dstR;
if (dstR > 255)
dstR = 255;
dstG = srcG + dstG;
if (dstG > 255)
dstG = 255;
dstB = srcB + dstB;
if (dstB > 255)
dstB = 255;
break;
case SDL_COPY_MOD:
dstR = (srcR * dstR) / 255;
dstG = (srcG * dstG) / 255;
dstB = (srcB * dstB) / 255;
break;
case SDL_COPY_MUL:
dstR = ((srcR * dstR) + (dstR * (255 - srcA))) / 255;
if (dstR > 255)
dstR = 255;
dstG = ((srcG * dstG) + (dstG * (255 - srcA))) / 255;
if (dstG > 255)
dstG = 255;
dstB = ((srcB * dstB) + (dstB * (255 - srcA))) / 255;
if (dstB > 255)
dstB = 255;
dstA = ((srcA * dstA) + (dstA * (255 - srcA))) / 255;
if (dstA > 255)
dstA = 255;
break;
}
if (dst_fmt->Amask) {
ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA);
} else {
ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB);
}
}
TRIANGLE_END_LOOP
}
#endif /* SDL_VIDEO_RENDER_SW && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -0,0 +1,42 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SDL_triangle_h_
#define SDL_triangle_h_
#include "../../SDL_internal.h"
extern int SDL_SW_FillTriangle(SDL_Surface *dst,
SDL_Point *d0, SDL_Point *d1, SDL_Point *d2,
SDL_BlendMode blend, SDL_Color c0, SDL_Color c1, SDL_Color c2);
extern int SDL_SW_BlitTriangle(
SDL_Surface *src,
SDL_Point *s0, SDL_Point *s1, SDL_Point *s2,
SDL_Surface *dst,
SDL_Point *d0, SDL_Point *d1, SDL_Point *d2,
SDL_Color c0, SDL_Color c1, SDL_Color c2);
extern void trianglepoint_2_fixedpoint(SDL_Point *a);
#endif /* SDL_triangle_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -81,24 +81,14 @@ static int VITA_GXM_QueueSetDrawColor(SDL_Renderer * renderer, SDL_RenderCommand
static int VITA_GXM_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count);
static int VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count);
static int VITA_GXM_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
static int VITA_GXM_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
static int
VITA_GXM_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);
static int VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
static int VITA_GXM_RenderDrawPoints(SDL_Renderer *renderer, const SDL_RenderCommand *cmd);
static int VITA_GXM_RenderDrawLines(SDL_Renderer *renderer, const SDL_RenderCommand *cmd);
static int VITA_GXM_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count);
static int VITA_GXM_RenderFillRects(SDL_Renderer *renderer, const SDL_RenderCommand *cmd);
static int VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
static int VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
@@ -160,7 +150,6 @@ StartDrawing(SDL_Renderer *renderer)
data->drawstate.vertex_program = NULL;
data->drawstate.fragment_program = NULL;
data->drawstate.last_command = -1;
data->drawstate.texture_color = 0xFFFFFFFF;
data->drawstate.viewport_dirty = SDL_TRUE;
// reset blend mode
@@ -168,7 +157,6 @@ StartDrawing(SDL_Renderer *renderer)
// fragment_programs *in = &data->blendFragmentPrograms.blend_mode_blend;
// data->colorFragmentProgram = in->color;
// data->textureFragmentProgram = in->texture;
// data->textureTintFragmentProgram = in->textureTint;
if (renderer->target == NULL) {
sceGxmBeginScene(
@@ -201,6 +189,20 @@ StartDrawing(SDL_Renderer *renderer)
data->drawing = SDL_TRUE;
}
static int
VITA_GXM_SetVSync(SDL_Renderer * renderer, const int vsync)
{
VITA_GXM_RenderData *data = renderer->driverdata;
if (vsync) {
data->displayData.wait_vblank = SDL_TRUE;
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
} else {
data->displayData.wait_vblank = SDL_FALSE;
renderer->info.flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
return 0;
}
SDL_Renderer *
VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
{
@@ -233,14 +235,13 @@ VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->QueueSetDrawColor = VITA_GXM_QueueSetDrawColor;
renderer->QueueDrawPoints = VITA_GXM_QueueDrawPoints;
renderer->QueueDrawLines = VITA_GXM_QueueDrawLines;
renderer->QueueFillRects = VITA_GXM_QueueFillRects;
renderer->QueueCopy = VITA_GXM_QueueCopy;
renderer->QueueCopyEx = VITA_GXM_QueueCopyEx;
renderer->QueueGeometry = VITA_GXM_QueueGeometry;
renderer->RunCommandQueue = VITA_GXM_RunCommandQueue;
renderer->RenderReadPixels = VITA_GXM_RenderReadPixels;
renderer->RenderPresent = VITA_GXM_RenderPresent;
renderer->DestroyTexture = VITA_GXM_DestroyTexture;
renderer->DestroyRenderer = VITA_GXM_DestroyRenderer;
renderer->SetVSync = VITA_GXM_SetVSync;
renderer->info = VITA_GXM_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
@@ -349,12 +350,19 @@ static int
VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, void **pixels, int *pitch)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
*pixels =
(void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex)
+ (rect->y * vita_texture->pitch) + rect->x * SDL_BYTESPERPIXEL(texture->format));
*pitch = vita_texture->pitch;
// make sure that rendering is finished on render target textures
if (vita_texture->tex->gxm_rendertarget != NULL) {
sceGxmFinish(data->gxm_context);
}
return 0;
}
@@ -419,7 +427,6 @@ VITA_GXM_SetBlendMode(VITA_GXM_RenderData *data, int blendMode)
}
data->colorFragmentProgram = in->color;
data->textureFragmentProgram = in->texture;
data->textureTintFragmentProgram = in->textureTint;
data->currentBlendMode = blendMode;
}
}
@@ -439,7 +446,7 @@ VITA_GXM_QueueSetDrawColor(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
data->drawstate.color = ((a << 24) | (b << 16) | (g << 8) | r);
data->drawstate.color = (((Uint32)a << 24) | (b << 16) | (g << 8) | r);
return 0;
}
@@ -451,10 +458,9 @@ VITA_GXM_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const
int color = data->drawstate.color;
color_vertex *vertex = (color_vertex *)pool_memalign(
color_vertex *vertex = (color_vertex *)pool_malloc(
data,
count * sizeof(color_vertex),
sizeof(color_vertex)
count * sizeof(color_vertex)
);
cmd->data.draw.first = (size_t)vertex;
@@ -464,7 +470,6 @@ VITA_GXM_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const
{
vertex[i].x = points[i].x;
vertex[i].y = points[i].y;
vertex[i].z = +0.5f;
vertex[i].color = color;
}
@@ -477,10 +482,9 @@ VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const S
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
int color = data->drawstate.color;
color_vertex *vertex = (color_vertex *)pool_memalign(
color_vertex *vertex = (color_vertex *)pool_malloc(
data,
(count-1) * 2 * sizeof(color_vertex),
sizeof(color_vertex)
(count-1) * 2 * sizeof(color_vertex)
);
cmd->data.draw.first = (size_t)vertex;
@@ -490,12 +494,10 @@ VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const S
{
vertex[i*2].x = points[i].x;
vertex[i*2].y = points[i].y;
vertex[i*2].z = +0.5f;
vertex[i*2].color = color;
vertex[i*2+1].x = points[i+1].x;
vertex[i*2+1].y = points[i+1].y;
vertex[i*2+1].z = +0.5f;
vertex[i*2+1].color = color;
}
@@ -503,192 +505,98 @@ VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const S
}
static int
VITA_GXM_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
VITA_GXM_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)
{
int color;
color_vertex *vertices;
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
int i;
int count = indices ? num_indices : num_vertices;
cmd->data.draw.count = count;
color = data->drawstate.color;
size_indices = indices ? size_indices : 0;
vertices = (color_vertex *)pool_memalign(
data,
4 * count * sizeof(color_vertex), // 4 vertices * count
sizeof(color_vertex));
if (texture) {
texture_vertex *vertices;
for (int i =0; i < count; i++)
{
const SDL_FRect *rect = &rects[i];
vertices = (texture_vertex *)pool_malloc(
data,
count * sizeof(texture_vertex));
vertices[4*i+0].x = rect->x;
vertices[4*i+0].y = rect->y;
vertices[4*i+0].z = +0.5f;
vertices[4*i+0].color = color;
if (!vertices) {
return -1;
}
vertices[4*i+1].x = rect->x + rect->w;
vertices[4*i+1].y = rect->y;
vertices[4*i+1].z = +0.5f;
vertices[4*i+1].color = color;
vertices[4*i+2].x = rect->x;
vertices[4*i+2].y = rect->y + rect->h;
vertices[4*i+2].z = +0.5f;
vertices[4*i+2].color = color;
for (i = 0; i < count; i++) {
int j;
float *xy_;
float *uv_;
int 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;
}
vertices[4*i+3].x = rect->x + rect->w;
vertices[4*i+3].y = rect->y + rect->h;
vertices[4*i+3].z = +0.5f;
vertices[4*i+3].color = color;
}
xy_ = (float *)((char*)xy + j * xy_stride);
col_ = *(int *)((char*)color + j * color_stride);
uv_ = (float *)((char*)uv + j * uv_stride);
cmd->data.draw.first = (size_t)vertices;
vertices[i].x = xy_[0] * scale_x;
vertices[i].y = xy_[1] * scale_y;
vertices[i].u = uv_[0];
vertices[i].v = uv_[1];
vertices[i].color = col_;
}
return 0;
}
cmd->data.draw.first = (size_t)vertices;
#define degToRad(x) ((x)*M_PI/180.f)
void MathSincos(float r, float *s, float *c)
{
*s = SDL_sin(r);
*c = SDL_cos(r);
}
static int
VITA_GXM_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
texture_vertex *vertices;
float u0, v0, u1, v1;
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
cmd->data.draw.count = 1;
vertices = (texture_vertex *)pool_memalign(
data,
4 * sizeof(texture_vertex), // 4 vertices
sizeof(texture_vertex));
cmd->data.draw.first = (size_t)vertices;
cmd->data.draw.texture = texture;
u0 = (float)srcrect->x / (float)texture->w;
v0 = (float)srcrect->y / (float)texture->h;
u1 = (float)(srcrect->x + srcrect->w) / (float)texture->w;
v1 = (float)(srcrect->y + srcrect->h) / (float)texture->h;
vertices[0].x = dstrect->x;
vertices[0].y = dstrect->y;
vertices[0].z = +0.5f;
vertices[0].u = u0;
vertices[0].v = v0;
vertices[1].x = dstrect->x + dstrect->w;
vertices[1].y = dstrect->y;
vertices[1].z = +0.5f;
vertices[1].u = u1;
vertices[1].v = v0;
vertices[2].x = dstrect->x;
vertices[2].y = dstrect->y + dstrect->h;
vertices[2].z = +0.5f;
vertices[2].u = u0;
vertices[2].v = v1;
vertices[3].x = dstrect->x + dstrect->w;
vertices[3].y = dstrect->y + dstrect->h;
vertices[3].z = +0.5f;
vertices[3].u = u1;
vertices[3].v = v1;
return 0;
}
static int
VITA_GXM_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
texture_vertex *vertices;
float u0, v0, u1, v1;
float x0, y0, x1, y1;
float s, c;
const float centerx = center->x + dstrect->x;
const float centery = center->y + dstrect->y;
cmd->data.draw.count = 1;
vertices = (texture_vertex *)pool_memalign(
data,
4 * sizeof(texture_vertex), // 4 vertices
sizeof(texture_vertex));
cmd->data.draw.first = (size_t)vertices;
cmd->data.draw.texture = texture;
if (flip & SDL_FLIP_HORIZONTAL) {
x0 = dstrect->x + dstrect->w;
x1 = dstrect->x;
} else {
x0 = dstrect->x;
x1 = dstrect->x + dstrect->w;
color_vertex *vertices;
vertices = (color_vertex *)pool_malloc(
data,
count * sizeof(color_vertex));
if (!vertices) {
return -1;
}
for (i = 0; i < count; i++) {
int j;
float *xy_;
int 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_ = *(int *)((char*)color + j * color_stride);
vertices[i].x = xy_[0] * scale_x;
vertices[i].y = xy_[1] * scale_y;
vertices[i].color = col_;
}
cmd->data.draw.first = (size_t)vertices;
}
if (flip & SDL_FLIP_VERTICAL) {
y0 = dstrect->y + dstrect->h;
y1 = dstrect->y;
} else {
y0 = dstrect->y;
y1 = dstrect->y + dstrect->h;
}
u0 = (float)srcrect->x / (float)texture->w;
v0 = (float)srcrect->y / (float)texture->h;
u1 = (float)(srcrect->x + srcrect->w) / (float)texture->w;
v1 = (float)(srcrect->y + srcrect->h) / (float)texture->h;
MathSincos(degToRad(angle), &s, &c);
vertices[0].x = x0 - centerx;
vertices[0].y = y0 - centery;
vertices[0].z = +0.5f;
vertices[0].u = u0;
vertices[0].v = v0;
vertices[1].x = x1 - centerx;
vertices[1].y = y0 - centery;
vertices[1].z = +0.5f;
vertices[1].u = u1;
vertices[1].v = v0;
vertices[2].x = x0 - centerx;
vertices[2].y = y1 - centery;
vertices[2].z = +0.5f;
vertices[2].u = u0;
vertices[2].v = v1;
vertices[3].x = x1 - centerx;
vertices[3].y = y1 - centery;
vertices[3].z = +0.5f;
vertices[3].u = u1;
vertices[3].v = v1;
for (int i = 0; i < 4; ++i)
{
float _x = vertices[i].x;
float _y = vertices[i].y;
vertices[i].x = _x * c - _y * s + centerx;
vertices[i].y = _x * s + _y * c + centery;
}
return 0;
}
static int
VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
@@ -723,43 +631,7 @@ VITA_GXM_RenderClear(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int
VITA_GXM_RenderDrawPoints(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_POINT);
sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_POINTS, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, cmd->data.draw.count);
sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL);
return 0;
}
static int
VITA_GXM_RenderDrawLines(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_LINE);
sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_LINES, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, cmd->data.draw.count);
sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL);
return 0;
}
static int
VITA_GXM_RenderFillRects(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
sceGxmSetVertexStream(data->gxm_context, 0, (const void*)cmd->data.draw.first);
sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 4 * cmd->data.draw.count);
return 0;
}
static int
SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd, SDL_bool solid)
SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
{
SDL_Texture *texture = cmd->data.draw.texture;
const SDL_BlendMode blend = cmd->data.draw.blend;
@@ -767,13 +639,6 @@ SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd, SDL_bool s
SceGxmVertexProgram *vertex_program;
SDL_bool matrix_updated = SDL_FALSE;
SDL_bool program_updated = SDL_FALSE;
Uint32 texture_color;
Uint8 r, g, b, a;
r = cmd->data.draw.r;
g = cmd->data.draw.g;
b = cmd->data.draw.b;
a = cmd->data.draw.a;
if (data->drawstate.viewport_dirty) {
const SDL_Rect *viewport = &data->drawstate.viewport;
@@ -819,11 +684,7 @@ SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd, SDL_bool s
if (texture) {
vertex_program = data->textureVertexProgram;
if(cmd->data.draw.r == 255 && cmd->data.draw.g == 255 && cmd->data.draw.b == 255 && cmd->data.draw.a == 255) {
fragment_program = data->textureFragmentProgram;
} else {
fragment_program = data->textureTintFragmentProgram;
}
fragment_program = data->textureFragmentProgram;
} else {
vertex_program = data->colorVertexProgram;
fragment_program = data->colorFragmentProgram;
@@ -841,58 +702,17 @@ SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd, SDL_bool s
program_updated = SDL_TRUE;
}
texture_color = ((a << 24) | (b << 16) | (g << 8) | r);
if (program_updated || matrix_updated) {
if (data->drawstate.fragment_program == data->textureFragmentProgram) {
void *vertex_wvp_buffer;
sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertex_wvp_buffer);
sceGxmSetUniformDataF(vertex_wvp_buffer, data->textureWvpParam, 0, 16, data->ortho_matrix);
} else if (data->drawstate.fragment_program == data->textureTintFragmentProgram) {
void *vertex_wvp_buffer;
void *texture_tint_color_buffer;
float *tint_color;
sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertex_wvp_buffer);
sceGxmSetUniformDataF(vertex_wvp_buffer, data->textureWvpParam, 0, 16, data->ortho_matrix);
sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &texture_tint_color_buffer);
tint_color = pool_memalign(
data,
4 * sizeof(float), // RGBA
sizeof(float)
);
tint_color[0] = r / 255.0f;
tint_color[1] = g / 255.0f;
tint_color[2] = b / 255.0f;
tint_color[3] = a / 255.0f;
sceGxmSetUniformDataF(texture_tint_color_buffer, data->textureTintColorParam, 0, 4, tint_color);
data->drawstate.texture_color = texture_color;
} else { // color
void *vertexDefaultBuffer;
sceGxmReserveVertexDefaultUniformBuffer(data->gxm_context, &vertexDefaultBuffer);
sceGxmSetUniformDataF(vertexDefaultBuffer, data->colorWvpParam, 0, 16, data->ortho_matrix);
}
} else {
if (data->drawstate.fragment_program == data->textureTintFragmentProgram && data->drawstate.texture_color != texture_color) {
void *texture_tint_color_buffer;
float *tint_color;
sceGxmReserveFragmentDefaultUniformBuffer(data->gxm_context, &texture_tint_color_buffer);
tint_color = pool_memalign(
data,
4 * sizeof(float), // RGBA
sizeof(float)
);
tint_color[0] = r / 255.0f;
tint_color[1] = g / 255.0f;
tint_color[2] = b / 255.0f;
tint_color[3] = a / 255.0f;
sceGxmSetUniformDataF(texture_tint_color_buffer, data->textureTintColorParam, 0, 4, tint_color);
data->drawstate.texture_color = texture_color;
}
}
if (texture != data->drawstate.texture) {
@@ -914,7 +734,7 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
return SetDrawState(data, cmd, SDL_FALSE);
return SetDrawState(data, cmd);
}
static int
@@ -925,7 +745,15 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
data->drawstate.target = renderer->target;
if (!data->drawstate.target) {
SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
int w, h;
SDL_GL_GetDrawableSize(renderer->window, &w, &h);
if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
data->drawstate.viewport_dirty = SDL_TRUE; // if the window dimensions changed, invalidate the current viewport, etc.
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.drawablew = w;
data->drawstate.drawableh = h;
}
}
while (cmd) {
@@ -963,29 +791,64 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
break;
}
case SDL_RENDERCMD_DRAW_POINTS: {
SetDrawState(data, cmd, SDL_FALSE);
VITA_GXM_RenderDrawPoints(renderer, cmd);
case SDL_RENDERCMD_FILL_RECTS: /* unused */
break;
}
case SDL_RENDERCMD_DRAW_LINES: {
SetDrawState(data, cmd, SDL_FALSE);
VITA_GXM_RenderDrawLines(renderer, cmd);
case SDL_RENDERCMD_COPY: /* unused */
break;
}
case SDL_RENDERCMD_FILL_RECTS: {
SetDrawState(data, cmd, SDL_FALSE);
VITA_GXM_RenderFillRects(renderer, cmd);
case SDL_RENDERCMD_COPY_EX: /* unused */
break;
}
case SDL_RENDERCMD_COPY:
case SDL_RENDERCMD_COPY_EX: {
SetCopyState(renderer, cmd);
sceGxmDraw(data->gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, 4 * cmd->data.draw.count);
case SDL_RENDERCMD_DRAW_POINTS:
case SDL_RENDERCMD_DRAW_LINES:
case SDL_RENDERCMD_GEOMETRY: {
SDL_Texture *thistexture = cmd->data.draw.texture;
SDL_BlendMode thisblend = cmd->data.draw.blend;
const SDL_RenderCommandType thiscmdtype = cmd->command;
SDL_RenderCommand *finalcmd = cmd;
SDL_RenderCommand *nextcmd = cmd->next;
size_t count = cmd->data.draw.count;
int ret;
while (nextcmd != NULL) {
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != thiscmdtype) {
break; /* can't go any further on this draw call, different render command up next. */
} else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
break; /* can't go any further on this draw call, different texture/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;
}
if (thistexture) {
ret = SetCopyState(renderer, cmd);
} else {
ret = SetDrawState(data, cmd);
}
if (ret == 0) {
int op = SCE_GXM_PRIMITIVE_TRIANGLES;
if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) {
sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_POINT);
op = SCE_GXM_PRIMITIVE_POINTS;
} else if (thiscmdtype == SDL_RENDERCMD_DRAW_LINES) {
sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_LINE);
op = SCE_GXM_PRIMITIVE_LINES;
}
sceGxmDraw(data->gxm_context, op, SCE_GXM_INDEX_FORMAT_U16, data->linearIndices, count);
if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS || thiscmdtype == SDL_RENDERCMD_DRAW_LINES) {
sceGxmSetFrontPolygonMode(data->gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL);
}
}
cmd = finalcmd; /* skip any copy commands we just combined in here. */
break;
}
@@ -996,6 +859,9 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
cmd = cmd->next;
}
sceGxmEndScene(data->gxm_context, NULL, NULL);
data->drawing = SDL_FALSE;
return 0;
}
@@ -1091,13 +957,6 @@ VITA_GXM_RenderPresent(SDL_Renderer *renderer)
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
SceCommonDialogUpdateParam updateParam;
if (data->drawing) {
sceGxmEndScene(data->gxm_context, NULL, NULL);
if (data->displayData.wait_vblank) {
sceGxmFinish(data->gxm_context);
}
}
data->displayData.address = data->displayBufferData[data->backBufferIndex];
SDL_memset(&updateParam, 0, sizeof(updateParam));
@@ -1134,8 +993,6 @@ VITA_GXM_RenderPresent(SDL_Renderer *renderer)
data->pool_index = 0;
data->current_pool = (data->current_pool + 1) % 2;
data->drawing = SDL_FALSE;
}
static void

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -124,37 +124,39 @@ static const unsigned char gxm_shader_color_f[gxm_shader_color_f_size] = {
0x7e, 0x0d, 0x80, 0x40,
};
#define gxm_shader_color_v_size 352
#define gxm_shader_color_v_size 368
static const unsigned char gxm_shader_color_v[gxm_shader_color_v_size] = {
0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03,
0x5d, 0x01, 0x00, 0x00, 0x4a, 0xb6, 0x4f, 0x7b,
0x51, 0x19, 0x1a, 0xae, 0x00, 0x00, 0x19, 0x00,
0x6d, 0x01, 0x00, 0x00, 0x09, 0xce, 0x4e, 0xc2,
0xe1, 0xcd, 0x24, 0xbc, 0x00, 0x00, 0x19, 0x00,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0xf0, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x74, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00,
0x98, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x74, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0xa8, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00,
0xb8, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x61,
0x86, 0x81, 0xa2, 0x00, 0x07, 0x53, 0x40, 0x61,
0x86, 0x81, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x01, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa,
0x80, 0x00, 0x08, 0x83, 0x21, 0x1d, 0x80, 0x38,
0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40,
0x0e, 0x86, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40,
0x04, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18,
0x00, 0x00, 0xf0, 0x83, 0x20, 0x0d, 0x80, 0x38,
0x0a, 0x84, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40,
0x02, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18,
0x00, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18,
0x01, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18,
@@ -172,142 +174,106 @@ static const unsigned char gxm_shader_color_v[gxm_shader_color_v_size] = {
0x00, 0x77, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00,
};
#define gxm_shader_texture_f_size 256
#define gxm_shader_texture_f_size 288
static const unsigned char gxm_shader_texture_f[gxm_shader_texture_f_size] = {
0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03,
0x00, 0x01, 0x00, 0x00, 0x2f, 0x18, 0xe0, 0x2b,
0x1f, 0x21, 0x47, 0x49, 0x01, 0x08, 0x18, 0x00,
0x20, 0x01, 0x00, 0x00, 0xeb, 0x4f, 0xb5, 0xba,
0x60, 0xb2, 0xd0, 0x8d, 0x05, 0x18, 0x18, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0xa4, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0xc4, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x64, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00,
0x84, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04,
0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0xa9, 0xd0, 0x0e, 0x00, 0x00, 0x00, 0x00,
0xf0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0x44, 0xfa, 0x30, 0x00, 0x00, 0x00,
0x02, 0x04, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
0x00, 0x07, 0x44, 0xfa, 0x00, 0x00, 0x00, 0x00,
0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x99, 0xaf,
0xbc, 0x0d, 0xc0, 0x40, 0x06, 0x82, 0xb9, 0xaf,
0xbc, 0x0d, 0x80, 0x40, 0x7c, 0x0f, 0x04, 0x00,
0x86, 0x47, 0xa4, 0x10, 0x30, 0x00, 0x00, 0x00,
0x02, 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x00,
};
#define gxm_shader_texture_tint_f_size 324
static const unsigned char gxm_shader_texture_tint_f[gxm_shader_texture_tint_f_size] = {
0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03,
0x43, 0x01, 0x00, 0x00, 0x44, 0x2f, 0x5d, 0xfe,
0x9e, 0xda, 0xf8, 0x6f, 0x05, 0x08, 0x18, 0x00,
0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0xcc, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x84, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04,
0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0x44, 0xfa, 0x00, 0x00, 0x00, 0x00,
0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x99, 0xff,
0xbc, 0x0d, 0xc0, 0x40, 0x02, 0x80, 0xb9, 0xaf,
0xbc, 0x0d, 0x80, 0x40, 0x7c, 0x0f, 0x04, 0x00,
0x86, 0x47, 0xa4, 0x10, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00,
0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
0x02, 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x75, 0x54, 0x69, 0x6e,
0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x74,
0x65, 0x78, 0x00, 0x00,
};
#define gxm_shader_texture_v_size 344
#define gxm_shader_texture_v_size 400
static const unsigned char gxm_shader_texture_v[gxm_shader_texture_v_size] = {
0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03,
0x58, 0x01, 0x00, 0x00, 0xa3, 0x36, 0x7b, 0x62,
0x1b, 0x80, 0x1c, 0xb0, 0x00, 0x00, 0x19, 0x00,
0x8f, 0x01, 0x00, 0x00, 0x60, 0x1e, 0x69, 0x97,
0x82, 0x7e, 0x0c, 0xac, 0x00, 0x00, 0x19, 0x00,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0xe8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x74, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x08, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x98, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x74, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0xa0, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
0xc0, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x33, 0x0f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0a,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x43, 0x00, 0x61,
0x86, 0x81, 0xa2, 0x00, 0x07, 0x53, 0x40, 0x61,
0x86, 0x81, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x01, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa,
0x80, 0x00, 0x08, 0x83, 0x21, 0x0d, 0x80, 0x38,
0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40,
0x0e, 0x86, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40,
0x04, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18,
0x01, 0x0e, 0x01, 0x01, 0x02, 0x00, 0x10, 0xfa,
0x80, 0x00, 0x08, 0x83, 0x21, 0x25, 0x80, 0x38,
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x14, 0xfa,
0x00, 0x00, 0xf0, 0x83, 0x20, 0x0d, 0x80, 0x38,
0x0a, 0x84, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40,
0x02, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18,
0x00, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18,
0x01, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18,
0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb,
0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x3a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00,
0x34, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
0x6e, 0x00, 0x61, 0x54, 0x65, 0x78, 0x63, 0x6f,
0x6f, 0x72, 0x64, 0x00, 0x77, 0x76, 0x70, 0x00,
0x6f, 0x72, 0x64, 0x00, 0x61, 0x43, 0x6f, 0x6c,
0x6f, 0x72, 0x00, 0x77, 0x76, 0x70, 0x00, 0x00,
};
static const SceGxmProgram *const clearVertexProgramGxp = (const SceGxmProgram*)gxm_shader_clear_v;
static const SceGxmProgram *const clearVertexProgramGxp = (const SceGxmProgram *)gxm_shader_clear_v;
static const SceGxmProgram *const clearFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_clear_f;
static const SceGxmProgram *const colorVertexProgramGxp = (const SceGxmProgram *)gxm_shader_color_v;
static const SceGxmProgram *const colorFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_color_f;
static const SceGxmProgram *const textureVertexProgramGxp = (const SceGxmProgram *)gxm_shader_texture_v;
static const SceGxmProgram *const textureFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_texture_f;
static const SceGxmProgram *const textureTintFragmentProgramGxp = (const SceGxmProgram *)gxm_shader_texture_tint_f;
#endif // SDL_RENDER_VITA_GXM_SHADERS_H

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -164,7 +164,6 @@ free_fragment_programs(VITA_GXM_RenderData *data, fragment_programs *out)
{
sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->color);
sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->texture);
sceGxmShaderPatcherReleaseFragmentProgram(data->shaderPatcher, out->textureTint);
}
static void
@@ -202,21 +201,6 @@ make_fragment_programs(VITA_GXM_RenderData *data, fragment_programs *out,
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Patcher create fragment failed: %d\n", err);
return;
}
err = sceGxmShaderPatcherCreateFragmentProgram(
data->shaderPatcher,
data->textureTintFragmentProgramId,
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
0,
blend_info,
textureVertexProgramGxp,
&out->textureTint
);
if (err != 0) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Patcher create fragment failed: %d\n", err);
return;
}
}
@@ -232,22 +216,18 @@ set_stencil_mask(VITA_GXM_RenderData *data, float x, float y, float w, float h)
vertices[0].x = x;
vertices[0].y = y;
vertices[0].z = +0.5f;
vertices[0].color = 0;
vertices[1].x = x + w;
vertices[1].y = y;
vertices[1].z = +0.5f;
vertices[1].color = 0;
vertices[2].x = x;
vertices[2].y = y + h;
vertices[2].z = +0.5f;
vertices[2].color = 0;
vertices[3].x = x + w;
vertices[3].y = y + h;
vertices[3].z = +0.5f;
vertices[3].color = 0;
data->drawstate.fragment_program = data->colorFragmentProgram;
@@ -495,7 +475,7 @@ gxm_init(SDL_Renderer *renderer)
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&data->displayBufferUid[i]);
// memset the buffer to black
// SDL_memset the buffer to black
for (y = 0; y < VITA_GXM_SCREEN_HEIGHT; y++) {
unsigned int *row = (unsigned int *)data->displayBufferData[i] + y * VITA_GXM_SCREEN_STRIDE;
for (x = 0; x < VITA_GXM_SCREEN_WIDTH; x++) {
@@ -654,12 +634,6 @@ gxm_init(SDL_Renderer *renderer)
return err;
}
err = sceGxmProgramCheck(textureTintFragmentProgramGxp);
if (err != 0) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "check program (texture tint fragment) failed: %d\n", err);
return err;
}
// register programs with the patcher
err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, clearVertexProgramGxp, &data->clearVertexProgramId);
if (err != 0) {
@@ -697,13 +671,6 @@ gxm_init(SDL_Renderer *renderer)
return err;
}
err = sceGxmShaderPatcherRegisterProgram(data->shaderPatcher, textureTintFragmentProgramGxp, &data->textureTintFragmentProgramId);
if (err != 0) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "register program (texture tint fragment) failed: %d\n", err);
return err;
}
{
// get attributes by name to create vertex format bindings
const SceGxmProgramParameter *paramClearPositionAttribute = sceGxmProgramFindParameterByName(clearVertexProgramGxp, "aPosition");
@@ -789,15 +756,15 @@ gxm_init(SDL_Renderer *renderer)
// create color vertex format
SceGxmVertexAttribute colorVertexAttributes[2];
SceGxmVertexStream colorVertexStreams[1];
/* x,y,z: 3 float 32 bits */
/* x,y: 2 float 32 bits */
colorVertexAttributes[0].streamIndex = 0;
colorVertexAttributes[0].offset = 0;
colorVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
colorVertexAttributes[0].componentCount = 3; // (x, y, z)
colorVertexAttributes[0].componentCount = 2; // (x, y)
colorVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorPositionAttribute);
/* color: 4 unsigned char = 32 bits */
colorVertexAttributes[1].streamIndex = 0;
colorVertexAttributes[1].offset = 12; // (x, y, z) * 4 = 12 bytes
colorVertexAttributes[1].offset = 8; // (x, y) * 4 = 8 bytes
colorVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N;
colorVertexAttributes[1].componentCount = 4; // (color)
colorVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramColorColorAttribute);
@@ -826,22 +793,29 @@ gxm_init(SDL_Renderer *renderer)
{
const SceGxmProgramParameter *paramTexturePositionAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aPosition");
const SceGxmProgramParameter *paramTextureTexcoordAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aTexcoord");
const SceGxmProgramParameter *paramTextureColorAttribute = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "aColor");
// create texture vertex format
SceGxmVertexAttribute textureVertexAttributes[2];
SceGxmVertexAttribute textureVertexAttributes[3];
SceGxmVertexStream textureVertexStreams[1];
/* x,y,z: 3 float 32 bits */
/* x,y: 2 float 32 bits */
textureVertexAttributes[0].streamIndex = 0;
textureVertexAttributes[0].offset = 0;
textureVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
textureVertexAttributes[0].componentCount = 3; // (x, y, z)
textureVertexAttributes[0].componentCount = 2; // (x, y)
textureVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramTexturePositionAttribute);
/* u,v: 2 floats 32 bits */
textureVertexAttributes[1].streamIndex = 0;
textureVertexAttributes[1].offset = 12; // (x, y, z) * 4 = 12 bytes
textureVertexAttributes[1].offset = 8; // (x, y) * 4 = 8 bytes
textureVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
textureVertexAttributes[1].componentCount = 2; // (u, v)
textureVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureTexcoordAttribute);
/* r,g,b,a: 4 unsigned chars 32 bits */
textureVertexAttributes[2].streamIndex = 0;
textureVertexAttributes[2].offset = 16; // (x, y, u, v) * 4 = 16 bytes
textureVertexAttributes[2].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N;
textureVertexAttributes[2].componentCount = 4; // (r, g, b, a)
textureVertexAttributes[2].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureColorAttribute);
// 16 bit (short) indices
textureVertexStreams[0].stride = sizeof(texture_vertex);
textureVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
@@ -851,13 +825,13 @@ gxm_init(SDL_Renderer *renderer)
data->shaderPatcher,
data->textureVertexProgramId,
textureVertexAttributes,
2,
3,
textureVertexStreams,
1,
&data->textureVertexProgram
);
if (err != 0) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (texture vertex) failed: %d\n", err);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create program (texture vertex) failed: %x\n", err);
return err;
}
@@ -876,7 +850,6 @@ gxm_init(SDL_Renderer *renderer)
data->colorFragmentProgram = in->color;
data->textureFragmentProgram = in->texture;
data->textureTintFragmentProgram = in->textureTint;
}
@@ -884,7 +857,6 @@ gxm_init(SDL_Renderer *renderer)
data->clearClearColorParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(clearFragmentProgramGxp, "uClearColor");
data->colorWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(colorVertexProgramGxp, "wvp");
data->textureWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(textureVertexProgramGxp, "wvp");
data->textureTintColorParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(textureTintFragmentProgramGxp, "uTintColor");
// Allocate memory for the memory pool
data->pool_addr[0] = mem_gpu_alloc(
@@ -953,7 +925,7 @@ void gxm_finish(SDL_Renderer *renderer)
sceGxmSyncObjectDestroy(data->displayBufferSync[i]);
}
// free the depth and stencil buffer
// Free the depth and stencil buffer
mem_gpu_free(data->depthBufferUid);
mem_gpu_free(data->stencilBufferUid);
@@ -963,7 +935,6 @@ void gxm_finish(SDL_Renderer *renderer)
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->colorFragmentProgramId);
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->colorVertexProgramId);
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureFragmentProgramId);
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureTintFragmentProgramId);
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureVertexProgramId);
sceGxmShaderPatcherDestroy(data->shaderPatcher);
@@ -1040,7 +1011,7 @@ gxm_texture_get_datap(const gxm_texture *texture)
gxm_texture *
create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget)
{
gxm_texture *texture = SDL_malloc(sizeof(gxm_texture));
gxm_texture *texture = SDL_calloc(1, sizeof(gxm_texture));
const int tex_size = ((w + 7) & ~ 7) * h * tex_format_to_bytespp(format);
void *texture_data;
@@ -1056,8 +1027,20 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
&texture->data_UID
);
/* Try SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE in case we're out of VRAM */
if (!texture_data) {
free(texture);
SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "CDRAM texture allocation failed\n");
texture_data = mem_gpu_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
tex_size,
SCE_GXM_TEXTURE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&texture->data_UID
);
}
if (!texture_data) {
SDL_free(texture);
return NULL;
}
@@ -1073,6 +1056,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
const uint32_t alignedHeight = ALIGN(h, SCE_GXM_TILE_SIZEY);
uint32_t sampleCount = alignedWidth*alignedHeight;
uint32_t depthStrideInSamples = alignedWidth;
const uint32_t alignedColorSurfaceStride = ALIGN(w, 8);
int err = sceGxmColorSurfaceInit(
&texture->gxm_colorsurface,
@@ -1082,7 +1066,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
w,
h,
w,
alignedColorSurfaceStride,
texture_data
);
@@ -1120,7 +1104,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
// set up parameters
SceGxmRenderTargetParams renderTargetParams;
memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams));
SDL_memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams));
renderTargetParams.flags = 0;
renderTargetParams.width = w;
renderTargetParams.height = h;

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -61,16 +61,15 @@ typedef struct clear_vertex {
typedef struct color_vertex {
float x;
float y;
float z;
unsigned int color;
} color_vertex;
typedef struct texture_vertex {
float x;
float y;
float z;
float u;
float v;
unsigned int color;
} texture_vertex;
typedef struct gxm_texture {
@@ -85,7 +84,6 @@ typedef struct gxm_texture {
typedef struct fragment_programs {
SceGxmFragmentProgram *color;
SceGxmFragmentProgram *texture;
SceGxmFragmentProgram *textureTint;
} fragment_programs;
typedef struct blend_fragment_programs {
@@ -103,7 +101,6 @@ typedef struct
SDL_Texture *texture;
SDL_Texture *target;
Uint32 color;
Uint32 texture_color;
SceGxmFragmentProgram *fragment_program;
SceGxmVertexProgram *vertex_program;
int last_command;
@@ -162,11 +159,9 @@ typedef struct
SceGxmFragmentProgram *colorFragmentProgram;
SceGxmVertexProgram *textureVertexProgram;
SceGxmFragmentProgram *textureFragmentProgram;
SceGxmFragmentProgram *textureTintFragmentProgram;
SceGxmProgramParameter *clearClearColorParam;
SceGxmProgramParameter *colorWvpParam;
SceGxmProgramParameter *textureWvpParam;
SceGxmProgramParameter *textureTintColorParam;
SceGxmShaderPatcher *shaderPatcher;
SceGxmVertexProgram *clearVertexProgram;
@@ -178,7 +173,6 @@ typedef struct
SceGxmShaderPatcherId colorFragmentProgramId;
SceGxmShaderPatcherId textureVertexProgramId;
SceGxmShaderPatcherId textureFragmentProgramId;
SceGxmShaderPatcherId textureTintFragmentProgramId;
SceUID patcherBufferUid;
SceUID patcherVertexUsseUid;

View File

@@ -1,5 +1,5 @@
void main(
float3 aPosition,
float2 aPosition,
float4 aColor,
uniform float4x4 wvp,
out float4 vPosition : POSITION,
@@ -7,7 +7,7 @@ void main(
out float pSize : PSIZE
)
{
vPosition = mul(float4(aPosition, 1.f), wvp);
vPosition = mul(float4(aPosition, 1.f, 0.5f), wvp);
vColor = aColor;
pSize = 1.f;
}

View File

@@ -1,4 +1,4 @@
float4 main(float2 vTexcoord : TEXCOORD0, uniform sampler2D tex)
float4 main(float2 vTexcoord : TEXCOORD0, float4 vColor : COLOR, uniform sampler2D tex)
{
return tex2D(tex, vTexcoord);
return tex2D(tex, vTexcoord) * vColor;
}

View File

@@ -1,11 +1,14 @@
void main(
float3 aPosition,
float2 aPosition,
float2 aTexcoord,
float4 aColor,
uniform float4x4 wvp,
out float4 vPosition : POSITION,
out float4 vColor : COLOR,
out float2 vTexcoord : TEXCOORD0
)
{
vPosition = mul(float4(aPosition, 1.f), wvp);
vPosition = mul(float4(aPosition, 1.f, 0.5f), wvp);
vTexcoord = aTexcoord;
vColor = aColor;
}