early-access version 2835

This commit is contained in:
pineappleEA
2022-07-15 04:00:50 +02:00
parent 5c0ee5eba6
commit 0e7aef7e36
1173 changed files with 55320 additions and 18881 deletions

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -20,7 +20,7 @@
*/
#include "../SDL_internal.h"
#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11) && !SDL_RENDER_DISABLED
#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12) && !SDL_RENDER_DISABLED
#include "SDL_stdinc.h"
#include "SDL_d3dmath.h"
@@ -131,6 +131,6 @@ Float4X4 MatrixRotationZ(float r)
}
#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11) && !SDL_RENDER_DISABLED */
#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12) && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -20,7 +20,7 @@
*/
#include "../SDL_internal.h"
#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11) && !SDL_RENDER_DISABLED
#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12) && !SDL_RENDER_DISABLED
/* Direct3D matrix math functions */
@@ -67,6 +67,6 @@ Float4X4 MatrixRotationX(float r);
Float4X4 MatrixRotationY(float r);
Float4X4 MatrixRotationZ(float r);
#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11) && !SDL_RENDER_DISABLED */
#endif /* (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12) && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -28,6 +28,19 @@
#include "SDL_mutex.h"
#include "SDL_yuv_sw_c.h"
/**
* A rectangle, with the origin at the upper left (double precision).
*/
typedef struct SDL_DRect
{
double x;
double y;
double w;
double h;
} SDL_DRect;
/* The SDL 2D rendering system */
typedef struct SDL_RenderDriver SDL_RenderDriver;
@@ -107,6 +120,21 @@ typedef struct SDL_RenderCommand
} SDL_RenderCommand;
typedef struct SDL_VertexSolid
{
SDL_FPoint position;
SDL_Color color;
} SDL_VertexSolid;
typedef enum
{
SDL_RENDERLINEMETHOD_POINTS,
SDL_RENDERLINEMETHOD_LINES,
SDL_RENDERLINEMETHOD_GEOMETRY,
} SDL_RenderLineMethod;
/* Define the SDL renderer structure */
struct SDL_Renderer
{
@@ -128,9 +156,9 @@ struct SDL_Renderer
const SDL_Rect * srcrect, const SDL_FRect * dstrect);
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);
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, float scale_x, float scale_y);
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,
const float *xy, int xy_stride, const SDL_Color *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);
@@ -186,12 +214,12 @@ struct SDL_Renderer
SDL_bool integer_scale;
/* The drawable area within the window */
SDL_FRect viewport;
SDL_FRect viewport_backup;
SDL_DRect viewport;
SDL_DRect viewport_backup;
/* The clip rectangle within the window */
SDL_FRect clip_rect;
SDL_FRect clip_rect_backup;
SDL_DRect clip_rect;
SDL_DRect clip_rect_backup;
/* Wether or not the clipping rectangle is used. */
SDL_bool clipping_enabled;
@@ -207,6 +235,9 @@ struct SDL_Renderer
/* Whether or not to scale relative mouse motion */
SDL_bool relative_scaling;
/* The method of drawing lines */
SDL_RenderLineMethod line_method;
/* Remainder from scaled relative motion */
float xrel;
float yrel;
@@ -226,8 +257,8 @@ struct SDL_Renderer
SDL_RenderCommand *render_commands_pool;
Uint32 render_command_generation;
Uint32 last_queued_color;
SDL_FRect last_queued_viewport;
SDL_FRect last_queued_cliprect;
SDL_DRect last_queued_viewport;
SDL_DRect last_queued_cliprect;
SDL_bool last_queued_cliprect_enabled;
SDL_bool color_queued;
SDL_bool viewport_queued;
@@ -252,6 +283,7 @@ struct SDL_RenderDriver
/* Not all of these are available in a given build. Use #ifdefs, etc. */
extern SDL_RenderDriver D3D_RenderDriver;
extern SDL_RenderDriver D3D11_RenderDriver;
extern SDL_RenderDriver D3D12_RenderDriver;
extern SDL_RenderDriver GL_RenderDriver;
extern SDL_RenderDriver GLES2_RenderDriver;
extern SDL_RenderDriver GLES_RenderDriver;

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -41,6 +41,13 @@
#include "SDL_shaders_d3d.h"
#ifdef __WATCOMC__
/* FIXME: Remove this once https://github.com/open-watcom/open-watcom-v2/pull/868 is merged */
#define D3DBLENDOP_REVSUBTRACT 3
/* FIXME: Remove this once https://github.com/open-watcom/open-watcom-v2/pull/869 is merged */
#define D3DERR_UNSUPPORTEDCOLOROPERATION MAKE_D3DHRESULT( 2073 )
#endif
typedef struct
{
SDL_Rect viewport;
@@ -71,7 +78,9 @@ typedef struct
IDirect3DSurface9 *defaultRenderTarget;
IDirect3DSurface9 *currentRenderTarget;
void* d3dxDLL;
#if SDL_HAVE_YUV
LPDIRECT3DPIXELSHADER9 shaders[NUM_SHADERS];
#endif
LPDIRECT3DVERTEXBUFFER9 vertexBuffers[8];
size_t vertexBufferSize[8];
int currentVertexBuffer;
@@ -95,6 +104,7 @@ typedef struct
D3D_TextureRep texture;
D3DTEXTUREFILTERTYPE scaleMode;
#if SDL_HAVE_YUV
/* YV12 texture support */
SDL_bool yuv;
D3D_TextureRep utexture;
@@ -102,6 +112,7 @@ typedef struct
Uint8 *pixels;
int pitch;
SDL_Rect locked_rect;
#endif
} D3D_TextureData;
typedef struct
@@ -297,7 +308,7 @@ D3D_ActivateRenderer(SDL_Renderer * renderer)
int w, h;
Uint32 window_flags = SDL_GetWindowFlags(window);
SDL_GetWindowSize(window, &w, &h);
WIN_GetDrawableSize(window, &w, &h);
data->pparams.BackBufferWidth = w;
data->pparams.BackBufferHeight = h;
if (window_flags & SDL_WINDOW_FULLSCREEN && (window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
@@ -343,7 +354,15 @@ D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
}
}
static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
static int
D3D_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
{
WIN_GetDrawableSize(renderer->window, w, h);
return 0;
}
static D3DBLEND
GetBlendFunc(SDL_BlendFactor factor)
{
switch (factor) {
case SDL_BLENDFACTOR_ZERO:
@@ -366,9 +385,28 @@ static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
return D3DBLEND_DESTALPHA;
case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
return D3DBLEND_INVDESTALPHA;
default:
return (D3DBLEND)0;
default: break;
}
return (D3DBLEND) 0;
}
static D3DBLENDOP
GetBlendEquation(SDL_BlendOperation operation)
{
switch (operation) {
case SDL_BLENDOPERATION_ADD:
return D3DBLENDOP_ADD;
case SDL_BLENDOPERATION_SUBTRACT:
return D3DBLENDOP_SUBTRACT;
case SDL_BLENDOPERATION_REV_SUBTRACT:
return D3DBLENDOP_REVSUBTRACT;
case SDL_BLENDOPERATION_MINIMUM:
return D3DBLENDOP_MIN;
case SDL_BLENDOPERATION_MAXIMUM:
return D3DBLENDOP_MAX;
default: break;
}
return (D3DBLENDOP) 0;
}
static SDL_bool
@@ -383,14 +421,16 @@ D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) ||
!GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor)) {
!GetBlendEquation(colorOperation) ||
!GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor) ||
!GetBlendEquation(alphaOperation)) {
return SDL_FALSE;
}
if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->enableSeparateAlphaBlend) {
return SDL_FALSE;
}
if (colorOperation != SDL_BLENDOPERATION_ADD || alphaOperation != SDL_BLENDOPERATION_ADD) {
return SDL_FALSE;
if (!data->enableSeparateAlphaBlend) {
if ((srcColorFactor != srcAlphaFactor) || (dstColorFactor != dstAlphaFactor) || (colorOperation != alphaOperation)) {
return SDL_FALSE;
}
}
return SDL_TRUE;
}
@@ -534,7 +574,7 @@ D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (D3D_CreateTextureRep(data->device, &texturedata->texture, usage, texture->format, PixelFormatToD3DFMT(texture->format), texture->w, texture->h) < 0) {
return -1;
}
#if SDL_HAVE_YUV
if (texture->format == SDL_PIXELFORMAT_YV12 ||
texture->format == SDL_PIXELFORMAT_IYUV) {
texturedata->yuv = SDL_TRUE;
@@ -547,6 +587,7 @@ D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
return -1;
}
}
#endif
return 0;
}
@@ -563,7 +604,7 @@ D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (D3D_RecreateTextureRep(data->device, &texturedata->texture) < 0) {
return -1;
}
#if SDL_HAVE_YUV
if (texturedata->yuv) {
if (D3D_RecreateTextureRep(data->device, &texturedata->utexture) < 0) {
return -1;
@@ -573,6 +614,7 @@ D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
return -1;
}
}
#endif
return 0;
}
@@ -584,14 +626,13 @@ D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
if (!texturedata) {
SDL_SetError("Texture is not currently available");
return -1;
return SDL_SetError("Texture is not currently available");
}
if (D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
return -1;
}
#if SDL_HAVE_YUV
if (texturedata->yuv) {
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
@@ -606,6 +647,7 @@ D3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
return -1;
}
}
#endif
return 0;
}
@@ -621,8 +663,7 @@ D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
if (!texturedata) {
SDL_SetError("Texture is not currently available");
return -1;
return SDL_SetError("Texture is not currently available");
}
if (D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
@@ -647,10 +688,9 @@ D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
IDirect3DDevice9 *device = data->device;
if (!texturedata) {
SDL_SetError("Texture is not currently available");
return -1;
return SDL_SetError("Texture is not currently available");
}
#if SDL_HAVE_YUV
texturedata->locked_rect = *rect;
if (texturedata->yuv) {
@@ -666,7 +706,9 @@ D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
(void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format));
*pitch = texturedata->pitch;
} else {
} else
#endif
{
RECT d3drect;
D3DLOCKED_RECT locked;
HRESULT result;
@@ -699,14 +741,17 @@ D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (!texturedata) {
return;
}
#if SDL_HAVE_YUV
if (texturedata->yuv) {
const SDL_Rect *rect = &texturedata->locked_rect;
void *pixels =
(void *) ((Uint8 *) texturedata->pixels + rect->y * texturedata->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format));
D3D_UpdateTexture(renderer, texture, rect, pixels, texturedata->pitch);
} else {
}
else
#endif
{
IDirect3DTexture9_UnlockRect(texturedata->texture.staging, 0);
texturedata->texture.dirty = SDL_TRUE;
if (data->drawstate.texture == texture) {
@@ -714,10 +759,6 @@ D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
data->drawstate.shader = NULL;
IDirect3DDevice9_SetPixelShader(data->device, NULL);
IDirect3DDevice9_SetTexture(data->device, 0, NULL);
if (texturedata->yuv) {
IDirect3DDevice9_SetTexture(data->device, 1, NULL);
IDirect3DDevice9_SetTexture(data->device, 2, NULL);
}
}
}
}
@@ -756,8 +797,7 @@ D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture)
texturedata = (D3D_TextureData *)texture->driverdata;
if (!texturedata) {
SDL_SetError("Texture is not currently available");
return -1;
return SDL_SetError("Texture is not currently available");
}
/* Make sure the render target is updated if it was locked and written to */
@@ -833,7 +873,7 @@ D3D_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_F
static int
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,
const float *xy, int xy_stride, const SDL_Color *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)
{
@@ -942,8 +982,7 @@ SetupTextureState(D3D_RenderData *data, SDL_Texture * texture, LPDIRECT3DPIXELSH
SDL_assert(*shader == NULL);
if (!texturedata) {
SDL_SetError("Texture is not currently available");
return -1;
return SDL_SetError("Texture is not currently available");
}
UpdateTextureScaleMode(data, texturedata, 0);
@@ -951,7 +990,7 @@ SetupTextureState(D3D_RenderData *data, SDL_Texture * texture, LPDIRECT3DPIXELSH
if (BindTextureRep(data->device, &texturedata->texture, 0) < 0) {
return -1;
}
#if SDL_HAVE_YUV
if (texturedata->yuv) {
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
case SDL_YUV_CONVERSION_JPEG:
@@ -977,6 +1016,7 @@ SetupTextureState(D3D_RenderData *data, SDL_Texture * texture, LPDIRECT3DPIXELSH
return -1;
}
}
#endif
return 0;
}
@@ -987,18 +1027,22 @@ SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
const SDL_BlendMode blend = cmd->data.draw.blend;
if (texture != data->drawstate.texture) {
#if SDL_HAVE_YUV
D3D_TextureData *oldtexturedata = data->drawstate.texture ? (D3D_TextureData *) data->drawstate.texture->driverdata : NULL;
D3D_TextureData *newtexturedata = texture ? (D3D_TextureData *) texture->driverdata : NULL;
#endif
LPDIRECT3DPIXELSHADER9 shader = NULL;
/* disable any enabled textures we aren't going to use, let SetupTextureState() do the rest. */
if (texture == NULL) {
IDirect3DDevice9_SetTexture(data->device, 0, NULL);
}
#if SDL_HAVE_YUV
if ((!newtexturedata || !newtexturedata->yuv) && (oldtexturedata && oldtexturedata->yuv)) {
IDirect3DDevice9_SetTexture(data->device, 1, NULL);
IDirect3DDevice9_SetTexture(data->device, 2, NULL);
}
#endif
if (texture && SetupTextureState(data, texture, &shader) < 0) {
return -1;
}
@@ -1015,10 +1059,12 @@ SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
} else if (texture) {
D3D_TextureData *texturedata = (D3D_TextureData *) texture->driverdata;
UpdateDirtyTexture(data->device, &texturedata->texture);
#if SDL_HAVE_YUV
if (texturedata->yuv) {
UpdateDirtyTexture(data->device, &texturedata->utexture);
UpdateDirtyTexture(data->device, &texturedata->vtexture);
}
#endif
}
if (blend != data->drawstate.blend) {
@@ -1030,11 +1076,15 @@ SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_BLENDOP,
GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
if (data->enableSeparateAlphaBlend) {
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_BLENDOPALPHA,
GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
}
}
@@ -1043,7 +1093,13 @@ SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
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 };
D3DVIEWPORT9 d3dviewport;
d3dviewport.X = viewport->x;
d3dviewport.Y = viewport->y;
d3dviewport.Width = viewport->w;
d3dviewport.Height = viewport->h;
d3dviewport.MinZ = 0.0f;
d3dviewport.MaxZ = 1.0f;
IDirect3DDevice9_SetViewport(data->device, &d3dviewport);
/* Set an orthographic projection matrix */
@@ -1070,7 +1126,11 @@ SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
if (data->drawstate.cliprect_dirty) {
const SDL_Rect *viewport = &data->drawstate.viewport;
const SDL_Rect *rect = &data->drawstate.cliprect;
const RECT d3drect = { viewport->x + rect->x, viewport->y + rect->y, viewport->x + rect->x + rect->w, viewport->y + rect->y + rect->h };
RECT d3drect;
d3drect.left = viewport->x + rect->x;
d3drect.top = viewport->y + rect->y;
d3drect.right = viewport->x + rect->x + rect->w;
d3drect.bottom = viewport->y + rect->y + rect->h;
IDirect3DDevice9_SetScissorRect(data->device, &d3drect);
data->drawstate.cliprect_dirty = SDL_FALSE;
}
@@ -1090,46 +1150,48 @@ D3D_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
return -1;
}
/* upload the new VBO data for this set of commands. */
vbo = data->vertexBuffers[vboidx];
if (data->vertexBufferSize[vboidx] < vertsize) {
const DWORD usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
const DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
if (vertices) {
/* upload the new VBO data for this set of commands. */
vbo = data->vertexBuffers[vboidx];
if (data->vertexBufferSize[vboidx] < vertsize) {
const DWORD usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
const DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
if (vbo) {
IDirect3DVertexBuffer9_Release(vbo);
}
if (FAILED(IDirect3DDevice9_CreateVertexBuffer(data->device, (UINT) vertsize, usage, fvf, D3DPOOL_DEFAULT, &vbo, NULL))) {
vbo = NULL;
}
data->vertexBuffers[vboidx] = vbo;
data->vertexBufferSize[vboidx] = vbo ? vertsize : 0;
}
if (vbo) {
IDirect3DVertexBuffer9_Release(vbo);
}
if (FAILED(IDirect3DDevice9_CreateVertexBuffer(data->device, (UINT) vertsize, usage, fvf, D3DPOOL_DEFAULT, &vbo, NULL))) {
vbo = NULL;
}
data->vertexBuffers[vboidx] = vbo;
data->vertexBufferSize[vboidx] = vbo ? vertsize : 0;
}
if (vbo) {
void *ptr;
if (FAILED(IDirect3DVertexBuffer9_Lock(vbo, 0, (UINT) vertsize, &ptr, D3DLOCK_DISCARD))) {
vbo = NULL; /* oh well, we'll do immediate mode drawing. :( */
} else {
SDL_memcpy(ptr, vertices, vertsize);
if (FAILED(IDirect3DVertexBuffer9_Unlock(vbo))) {
void *ptr;
if (FAILED(IDirect3DVertexBuffer9_Lock(vbo, 0, (UINT) vertsize, &ptr, D3DLOCK_DISCARD))) {
vbo = NULL; /* oh well, we'll do immediate mode drawing. :( */
} else {
SDL_memcpy(ptr, vertices, vertsize);
if (FAILED(IDirect3DVertexBuffer9_Unlock(vbo))) {
vbo = NULL; /* oh well, we'll do immediate mode drawing. :( */
}
}
}
}
/* cycle through a few VBOs so D3D has some time with the data before we replace it. */
if (vbo) {
data->currentVertexBuffer++;
if (data->currentVertexBuffer >= SDL_arraysize(data->vertexBuffers)) {
data->currentVertexBuffer = 0;
/* cycle through a few VBOs so D3D has some time with the data before we replace it. */
if (vbo) {
data->currentVertexBuffer++;
if (data->currentVertexBuffer >= SDL_arraysize(data->vertexBuffers)) {
data->currentVertexBuffer = 0;
}
} else if (!data->reportedVboProblem) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL failed to get a vertex buffer for this Direct3D 9 rendering batch!");
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Dropping back to a slower method.");
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "This might be a brief hiccup, but if performance is bad, this is probably why.");
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "This error will not be logged again for this renderer.");
data->reportedVboProblem = SDL_TRUE;
}
} else if (!data->reportedVboProblem) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "SDL failed to get a vertex buffer for this Direct3D 9 rendering batch!");
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Dropping back to a slower method.");
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "This might be a brief hiccup, but if performance is bad, this is probably why.");
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "This error will not be logged again for this renderer.");
data->reportedVboProblem = SDL_TRUE;
}
IDirect3DDevice9_SetStreamSource(data->device, 0, vbo, 0, sizeof (Vertex));
@@ -1183,7 +1245,9 @@ D3D_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
} else {
/* Clear is defined to clear the entire render target */
const D3DVIEWPORT9 wholeviewport = { 0, 0, backw, backh, 0.0f, 1.0f };
D3DVIEWPORT9 wholeviewport = { 0, 0, 0, 0, 0.0f, 1.0f };
wholeviewport.Width = backw;
wholeviewport.Height = backh;
IDirect3DDevice9_SetViewport(data->device, &wholeviewport);
data->drawstate.viewport_dirty = SDL_TRUE; /* we still need to (re)set orthographic projection, so always mark it dirty. */
IDirect3DDevice9_Clear(data->device, 0, NULL, D3DCLEAR_TARGET, color, 0.0f, 0);
@@ -1274,6 +1338,7 @@ D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
RECT d3drect;
D3DLOCKED_RECT locked;
HRESULT result;
int status;
if (data->currentRenderTarget) {
backBuffer = data->currentRenderTarget;
@@ -1308,7 +1373,7 @@ D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
return D3D_SetError("LockRect()", result);
}
SDL_ConvertPixels(rect->w, rect->h,
status = SDL_ConvertPixels(rect->w, rect->h,
D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch,
format, pixels, pitch);
@@ -1316,7 +1381,7 @@ D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
IDirect3DSurface9_Release(surface);
return 0;
return status;
}
static void
@@ -1355,10 +1420,12 @@ D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
renderdata->drawstate.shader = NULL;
IDirect3DDevice9_SetPixelShader(renderdata->device, NULL);
IDirect3DDevice9_SetTexture(renderdata->device, 0, NULL);
#if SDL_HAVE_YUV
if (data->yuv) {
IDirect3DDevice9_SetTexture(renderdata->device, 1, NULL);
IDirect3DDevice9_SetTexture(renderdata->device, 2, NULL);
}
#endif
}
if (!data) {
@@ -1366,9 +1433,11 @@ D3D_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
}
D3D_DestroyTextureRep(&data->texture);
#if SDL_HAVE_YUV
D3D_DestroyTextureRep(&data->utexture);
D3D_DestroyTextureRep(&data->vtexture);
SDL_free(data->pixels);
#endif
SDL_free(data);
texture->driverdata = NULL;
}
@@ -1390,12 +1459,14 @@ D3D_DestroyRenderer(SDL_Renderer * renderer)
IDirect3DSurface9_Release(data->currentRenderTarget);
data->currentRenderTarget = NULL;
}
#if SDL_HAVE_YUV
for (i = 0; i < SDL_arraysize(data->shaders); ++i) {
if (data->shaders[i]) {
IDirect3DPixelShader9_Release(data->shaders[i]);
data->shaders[i] = NULL;
}
}
#endif
/* Release all vertex buffers */
for (i = 0; i < SDL_arraysize(data->vertexBuffers); ++i) {
if (data->vertexBuffers[i]) {
@@ -1552,6 +1623,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
}
renderer->WindowEvent = D3D_WindowEvent;
renderer->GetOutputSize = D3D_GetOutputSize;
renderer->SupportsBlendMode = D3D_SupportsBlendMode;
renderer->CreateTexture = D3D_CreateTexture;
renderer->UpdateTexture = D3D_UpdateTexture;
@@ -1581,7 +1653,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
SDL_GetWindowWMInfo(window, &windowinfo);
window_flags = SDL_GetWindowFlags(window);
SDL_GetWindowSize(window, &w, &h);
WIN_GetDrawableSize(window, &w, &h);
SDL_GetWindowDisplayMode(window, &fullscreen_mode);
SDL_zero(pparams);
@@ -1668,7 +1740,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
/* Set up parameters for rendering */
D3D_InitRenderState(data);
#if SDL_HAVE_YUV
if (caps.MaxSimultaneousTextures >= 3) {
int i;
for (i = 0; i < SDL_arraysize(data->shaders); ++i) {
@@ -1682,7 +1754,10 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
}
}
#endif
data->drawstate.viewport_dirty = SDL_TRUE;
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
data->drawstate.blend = SDL_BLENDMODE_INVALID;
return renderer;

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -27,6 +27,9 @@
#define COBJMACROS
#include "../../core/windows/SDL_windows.h"
#if !defined(__WINRT__)
#include "../../video/windows/SDL_windowswindow.h"
#endif
#include "SDL_hints.h"
#include "SDL_loadso.h"
#include "SDL_syswm.h"
@@ -63,8 +66,8 @@ extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNat
#define SAFE_RELEASE(X) if ((X)) { IUnknown_Release(SDL_static_cast(IUnknown*, X)); X = NULL; }
/* !!! FIXME: vertex buffer bandwidth could be significantly lower; move color to a uniform, only use UV coords
!!! FIXME: when textures are needed, and don't ever pass Z, since it's always zero. */
/* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when
!!! FIXME: textures are needed. */
/* Vertex shader, common values */
typedef struct
@@ -76,9 +79,9 @@ typedef struct
/* Per-vertex data */
typedef struct
{
Float3 pos;
Float2 pos;
Float2 tex;
Float4 color;
SDL_Color color;
} VertexPositionColor;
/* Per-texture data */
@@ -91,7 +94,7 @@ typedef struct
int lockedTexturePositionX;
int lockedTexturePositionY;
D3D11_FILTER scaleMode;
#if SDL_HAVE_YUV
/* YV12 texture support */
SDL_bool yuv;
ID3D11Texture2D *mainTextureU;
@@ -107,6 +110,7 @@ typedef struct
Uint8 *pixels;
int pitch;
SDL_Rect locked_rect;
#endif
} D3D11_TextureData;
/* Blend mode data */
@@ -487,6 +491,11 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
}
/* Create a single-threaded device unless the app requests otherwise. */
if (!SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_FALSE)) {
creationFlags |= D3D11_CREATE_DEVICE_SINGLETHREADED;
}
/* Create the Direct3D 11 API device object and a corresponding context. */
result = D3D11CreateDeviceFunc(
data->dxgiAdapter,
@@ -904,7 +913,11 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
/* The width and height of the swap chain must be based on the display's
* non-rotated size.
*/
#if defined(__WINRT__)
SDL_GetWindowSize(renderer->window, &w, &h);
#else
WIN_GetDrawableSize(renderer->window, &w, &h);
#endif
data->rotation = D3D11_GetCurrentRotation();
/* SDL_Log("%s: windowSize={%d,%d}, orientation=%d\n", __FUNCTION__, w, h, (int)data->rotation); */
if (D3D11_IsDisplayRotated90Degrees(data->rotation)) {
@@ -992,6 +1005,16 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
goto done;
}
/* Set the swap chain target immediately, so that a target is always set
* even before we get to SetDrawState. Without this it's possible to hit
* null references in places like ReadPixels!
*/
ID3D11DeviceContext_OMSetRenderTargets(data->d3dContext,
1,
&data->mainRenderTargetView,
NULL
);
data->viewportDirty = SDL_TRUE;
done:
@@ -1035,6 +1058,15 @@ D3D11_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
}
}
#if !defined(__WINRT__)
static int
D3D11_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
{
WIN_GetDrawableSize(renderer->window, w, h);
return 0;
}
#endif
static SDL_bool
D3D11_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
{
@@ -1109,10 +1141,9 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
#if SDL_HAVE_YUV
if (texture->format == SDL_PIXELFORMAT_YV12 ||
texture->format == SDL_PIXELFORMAT_IYUV) {
textureData->yuv = SDL_TRUE;
@@ -1127,8 +1158,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
@@ -1138,8 +1168,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
}
@@ -1160,11 +1189,11 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
}
}
#endif /* SDL_HAVE_YUV */
SDL_zero(resourceViewDesc);
resourceViewDesc.Format = textureDesc.Format;
resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceViewDesc.Texture2D.MostDetailedMip = 0;
@@ -1176,10 +1205,9 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
}
#if SDL_HAVE_YUV
if (textureData->yuv) {
result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
(ID3D11Resource *)textureData->mainTextureU,
@@ -1188,8 +1216,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
}
result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
(ID3D11Resource *)textureData->mainTextureV,
@@ -1198,8 +1225,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
}
}
@@ -1215,13 +1241,14 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
}
}
#endif /* SDL_HAVE_YUV */
if (texture->access & SDL_TEXTUREACCESS_TARGET) {
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
SDL_zero(renderTargetViewDesc);
renderTargetViewDesc.Format = textureDesc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;
@@ -1232,8 +1259,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
&textureData->mainTextureRenderTargetView);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRenderTargetView"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRenderTargetView"), result);
}
}
@@ -1254,6 +1280,7 @@ D3D11_DestroyTexture(SDL_Renderer * renderer,
SAFE_RELEASE(data->mainTextureResourceView);
SAFE_RELEASE(data->mainTextureRenderTargetView);
SAFE_RELEASE(data->stagingTexture);
#if SDL_HAVE_YUV
SAFE_RELEASE(data->mainTextureU);
SAFE_RELEASE(data->mainTextureResourceViewU);
SAFE_RELEASE(data->mainTextureV);
@@ -1261,6 +1288,7 @@ D3D11_DestroyTexture(SDL_Renderer * renderer,
SAFE_RELEASE(data->mainTextureNV);
SAFE_RELEASE(data->mainTextureResourceViewNV);
SDL_free(data->pixels);
#endif
SDL_free(data);
texture->driverdata = NULL;
}
@@ -1290,8 +1318,7 @@ D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Texture2D *tex
NULL,
&stagingTexture);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
}
/* Get a write-only pointer to data in the staging texture: */
@@ -1303,9 +1330,8 @@ D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Texture2D *tex
&textureMemory
);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
SAFE_RELEASE(stagingTexture);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
}
src = (const Uint8 *)pixels;
@@ -1357,14 +1383,13 @@ D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
if (!textureData) {
SDL_SetError("Texture is not currently available");
return -1;
return SDL_SetError("Texture is not currently available");
}
if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch) < 0) {
return -1;
}
#if SDL_HAVE_YUV
if (textureData->yuv) {
/* Skip to the correct offset into the next texture */
srcPixels = (const void*)((const Uint8*)srcPixels + rect->h * srcPitch);
@@ -1388,6 +1413,7 @@ D3D11_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
return -1;
}
}
#endif /* SDL_HAVE_YUV */
return 0;
}
@@ -1403,8 +1429,7 @@ D3D11_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
if (!textureData) {
SDL_SetError("Texture is not currently available");
return -1;
return SDL_SetError("Texture is not currently available");
}
if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
@@ -1429,8 +1454,7 @@ D3D11_UpdateTextureNV(SDL_Renderer * renderer, SDL_Texture * texture,
D3D11_TextureData *textureData = (D3D11_TextureData *)texture->driverdata;
if (!textureData) {
SDL_SetError("Texture is not currently available");
return -1;
return SDL_SetError("Texture is not currently available");
}
if (D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch) < 0) {
@@ -1455,10 +1479,9 @@ D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
D3D11_MAPPED_SUBRESOURCE textureMemory;
if (!textureData) {
SDL_SetError("Texture is not currently available");
return -1;
return SDL_SetError("Texture is not currently available");
}
#if SDL_HAVE_YUV
if (textureData->yuv || textureData->nv12) {
/* It's more efficient to upload directly... */
if (!textureData->pixels) {
@@ -1475,7 +1498,7 @@ D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
*pitch = textureData->pitch;
return 0;
}
#endif
if (textureData->stagingTexture) {
return SDL_SetError("texture is already locked");
}
@@ -1500,8 +1523,7 @@ D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
NULL,
&textureData->stagingTexture);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
}
/* Get a write-only pointer to data in the staging texture: */
@@ -1513,9 +1535,8 @@ D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
&textureMemory
);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
SAFE_RELEASE(textureData->stagingTexture);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
}
/* Make note of where the staging texture will be written to
@@ -1541,7 +1562,7 @@ D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (!textureData) {
return;
}
#if SDL_HAVE_YUV
if (textureData->yuv || textureData->nv12) {
const SDL_Rect *rect = &textureData->locked_rect;
void *pixels =
@@ -1550,7 +1571,7 @@ D3D11_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
D3D11_UpdateTexture(renderer, texture, rect, pixels, textureData->pitch);
return;
}
#endif
/* Commit the pixel buffer's changes back to the staging texture: */
ID3D11DeviceContext_Unmap(rendererData->d3dContext,
(ID3D11Resource *)textureData->stagingTexture,
@@ -1614,11 +1635,12 @@ static int
D3D11_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
{
VertexPositionColor *verts = (VertexPositionColor *) SDL_AllocateRenderVertices(renderer, count * 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;
SDL_Color color;
color.r = cmd->data.draw.r;
color.g = cmd->data.draw.g;
color.b = cmd->data.draw.b;
color.a = cmd->data.draw.a;
if (!verts) {
return -1;
@@ -1629,13 +1651,9 @@ D3D11_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL
for (i = 0; i < count; i++) {
verts->pos.x = points[i].x + 0.5f;
verts->pos.y = points[i].y + 0.5f;
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->color = color;
verts++;
}
@@ -1644,7 +1662,7 @@ D3D11_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL
static int
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,
const float *xy, int xy_stride, const SDL_Color *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)
{
@@ -1662,7 +1680,6 @@ D3D11_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
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) {
@@ -1674,15 +1691,10 @@ D3D11_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
}
xy_ = (float *)((char*)xy + j * xy_stride);
col_ = *(SDL_Color *)((char*)color + j * color_stride);
verts->pos.x = xy_[0] * scale_x;
verts->pos.y = xy_[1] * scale_y;
verts->pos.z = 0.0f;
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->color = *(SDL_Color*)((char*)color + j * color_stride);
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
@@ -1722,8 +1734,7 @@ D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
&mappedResource
);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [vertex buffer]"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [vertex buffer]"), result);
}
SDL_memcpy(mappedResource.pData, vertexData, dataSizeInBytes);
ID3D11DeviceContext_Unmap(rendererData->d3dContext, (ID3D11Resource *)rendererData->vertexBuffers[vbidx], 0);
@@ -1750,8 +1761,7 @@ D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
&rendererData->vertexBuffers[vbidx]
);
if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex buffer]"), result);
return -1;
return WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex buffer]"), result);
}
rendererData->vertexBufferSizes[vbidx] = dataSizeInBytes;
@@ -2004,7 +2014,7 @@ D3D11_SetCopyState(SDL_Renderer * renderer, const SDL_RenderCommand *cmd, const
default:
return SDL_SetError("Unknown scale mode: %d\n", textureData->scaleMode);
}
#if SDL_HAVE_YUV
if (textureData->yuv) {
ID3D11ShaderResourceView *shaderResources[] = {
textureData->mainTextureResourceView,
@@ -2055,7 +2065,7 @@ D3D11_SetCopyState(SDL_Renderer * renderer, const SDL_RenderCommand *cmd, const
SDL_arraysize(shaderResources), shaderResources, textureSampler, matrix);
}
#endif /* SDL_HAVE_YUV */
return D3D11_SetDrawState(renderer, cmd, rendererData->pixelShaders[SHADER_RGB],
1, &textureData->mainTextureResourceView, textureSampler, matrix);
}
@@ -2258,30 +2268,20 @@ D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
/* Copy the data into the desired buffer, converting pixels to the
* desired format at the same time:
*/
if (SDL_ConvertPixels(
status = SDL_ConvertPixels(
rect->w, rect->h,
D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
textureMemory.pData,
textureMemory.RowPitch,
format,
pixels,
pitch) != 0) {
/* When SDL_ConvertPixels fails, it'll have already set the format.
* Get the error message, and attach some extra data to it.
*/
char errorMessage[1024];
SDL_snprintf(errorMessage, sizeof(errorMessage), "%s, Convert Pixels failed: %s", __FUNCTION__, SDL_GetError());
SDL_SetError("%s", errorMessage);
goto done;
}
pitch);
/* Unmap the texture: */
ID3D11DeviceContext_Unmap(data->d3dContext,
(ID3D11Resource *)stagingTexture,
0);
status = 0;
done:
SAFE_RELEASE(backBuffer);
SAFE_RELEASE(stagingTexture);
@@ -2374,6 +2374,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
data = (D3D11_RenderData *) SDL_calloc(1, sizeof(*data));
if (!data) {
SDL_free(renderer);
SDL_OutOfMemory();
return NULL;
}
@@ -2381,6 +2382,9 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
data->identity = MatrixIdentity();
renderer->WindowEvent = D3D11_WindowEvent;
#if !defined(__WINRT__)
renderer->GetOutputSize = D3D11_GetOutputSize;
#endif
renderer->SupportsBlendMode = D3D11_SupportsBlendMode;
renderer->CreateTexture = D3D11_CreateTexture;
renderer->UpdateTexture = D3D11_UpdateTexture;

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -1886,9 +1886,10 @@ static struct
{
const void *shader_data;
SIZE_T shader_size;
} D3D11_shaders[] = {
} D3D11_shaders[NUM_SHADERS] = {
{ D3D11_PixelShader_Colors, sizeof(D3D11_PixelShader_Colors) },
{ D3D11_PixelShader_Textures, sizeof(D3D11_PixelShader_Textures) },
#if SDL_HAVE_YUV
{ D3D11_PixelShader_YUV_JPEG, sizeof(D3D11_PixelShader_YUV_JPEG) },
{ D3D11_PixelShader_YUV_BT601, sizeof(D3D11_PixelShader_YUV_BT601) },
{ D3D11_PixelShader_YUV_BT709, sizeof(D3D11_PixelShader_YUV_BT709) },
@@ -1898,6 +1899,7 @@ static struct
{ D3D11_PixelShader_NV21_JPEG, sizeof(D3D11_PixelShader_NV21_JPEG) },
{ D3D11_PixelShader_NV21_BT601, sizeof(D3D11_PixelShader_NV21_BT601) },
{ D3D11_PixelShader_NV21_BT709, sizeof(D3D11_PixelShader_NV21_BT709) },
#endif
};
int D3D11_CreateVertexShader(ID3D11Device1 *d3dDevice, ID3D11VertexShader **vertexShader, ID3D11InputLayout **inputLayout)
@@ -1905,9 +1907,9 @@ int D3D11_CreateVertexShader(ID3D11Device1 *d3dDevice, ID3D11VertexShader **vert
/* Declare how the input layout for SDL's vertex shader will be setup: */
const D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
HRESULT result;

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -25,6 +25,7 @@
typedef enum {
SHADER_SOLID,
SHADER_RGB,
#if SDL_HAVE_YUV
SHADER_YUV_JPEG,
SHADER_YUV_BT601,
SHADER_YUV_BT709,
@@ -34,6 +35,7 @@ typedef enum {
SHADER_NV21_JPEG,
SHADER_NV21_BT601,
SHADER_NV21_BT709,
#endif
NUM_SHADERS
} D3D11_Shader;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 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"
/* D3D12 shader implementation */
typedef enum {
SHADER_SOLID,
SHADER_RGB,
#if SDL_HAVE_YUV
SHADER_YUV_JPEG,
SHADER_YUV_BT601,
SHADER_YUV_BT709,
SHADER_NV12_JPEG,
SHADER_NV12_BT601,
SHADER_NV12_BT709,
SHADER_NV21_JPEG,
SHADER_NV21_BT601,
SHADER_NV21_BT709,
#endif
NUM_SHADERS
} D3D12_Shader;
typedef enum {
ROOTSIG_COLOR,
ROOTSIG_TEXTURE,
#if SDL_HAVE_YUV
ROOTSIG_YUV,
ROOTSIG_NV,
#endif
NUM_ROOTSIGS
} D3D12_RootSignature;
extern void D3D12_GetVertexShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode);
extern void D3D12_GetPixelShader(D3D12_Shader shader, D3D12_SHADER_BYTECODE *outBytecode);
extern D3D12_RootSignature D3D12_GetRootSignatureType(D3D12_Shader shader);
extern void D3D12_GetRootSignatureData(D3D12_RootSignature rootSig, D3D12_SHADER_BYTECODE* outBytecode);
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -32,6 +32,7 @@
#import <QuartzCore/CAMetalLayer.h>
#ifdef __MACOSX__
#import <AppKit/NSWindow.h>
#import <AppKit/NSView.h>
#endif
@@ -141,24 +142,6 @@ typedef struct METAL_ShaderPipelines
@end
@implementation METAL_RenderData
#if !__has_feature(objc_arc)
- (void)dealloc
{
[_mtldevice release];
[_mtlcmdqueue release];
[_mtlcmdbuffer release];
[_mtlcmdencoder release];
[_mtllibrary release];
[_mtlbackbuffer release];
[_mtlsamplernearest release];
[_mtlsamplerlinear release];
[_mtlbufconstants release];
[_mtlbufquadindices release];
[_mtllayer release];
[_mtlpassdesc release];
[super dealloc];
}
#endif
@end
@interface METAL_TextureData : NSObject
@@ -166,26 +149,17 @@ typedef struct METAL_ShaderPipelines
@property (nonatomic, retain) id<MTLTexture> mtltexture_uv;
@property (nonatomic, retain) id<MTLSamplerState> mtlsampler;
@property (nonatomic, assign) SDL_MetalFragmentFunction fragmentFunction;
#if SDL_HAVE_YUV
@property (nonatomic, assign) BOOL yuv;
@property (nonatomic, assign) BOOL nv12;
@property (nonatomic, assign) size_t conversionBufferOffset;
#endif
@property (nonatomic, assign) BOOL hasdata;
@property (nonatomic, retain) id<MTLBuffer> lockedbuffer;
@property (nonatomic, assign) SDL_Rect lockedrect;
@end
@implementation METAL_TextureData
#if !__has_feature(objc_arc)
- (void)dealloc
{
[_mtltexture release];
[_mtltexture_uv release];
[_mtlsampler release];
[_lockedbuffer release];
[super dealloc];
}
#endif
@end
static int
@@ -340,13 +314,6 @@ MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
METAL_PipelineState *states = SDL_realloc(cache->states, (cache->count + 1) * sizeof(pipeline));
#if !__has_feature(objc_arc)
[mtlpipedesc release]; // !!! FIXME: can these be reused for each creation, or does the pipeline obtain it?
[mtlvertfn release];
[mtlfragfn release];
[state release];
#endif
if (states) {
states[cache->count++] = pipeline;
cache->states = states;
@@ -604,14 +571,14 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
mtltexdesc.usage = MTLTextureUsageShaderRead;
}
}
id<MTLTexture> mtltexture = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
if (mtltexture == nil) {
return SDL_SetError("Texture allocation failed");
}
id<MTLTexture> mtltexture_uv = nil;
#if SDL_HAVE_YUV
BOOL yuv = (texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12);
BOOL nv12 = (texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21);
@@ -630,13 +597,10 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (yuv || nv12) {
mtltexture_uv = [data.mtldevice newTextureWithDescriptor:mtltexdesc];
if (mtltexture_uv == nil) {
#if !__has_feature(objc_arc)
[mtltexture release];
#endif
return SDL_SetError("Texture allocation failed");
}
}
#endif /* SDL_HAVE_YUV */
METAL_TextureData *texturedata = [[METAL_TextureData alloc] init];
if (texture->scaleMode == SDL_ScaleModeNearest) {
texturedata.mtlsampler = data.mtlsamplernearest;
@@ -645,7 +609,7 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
}
texturedata.mtltexture = mtltexture;
texturedata.mtltexture_uv = mtltexture_uv;
#if SDL_HAVE_YUV
texturedata.yuv = yuv;
texturedata.nv12 = nv12;
@@ -655,10 +619,12 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
texturedata.fragmentFunction = SDL_METAL_FRAGMENT_NV12;
} else if (texture->format == SDL_PIXELFORMAT_NV21) {
texturedata.fragmentFunction = SDL_METAL_FRAGMENT_NV21;
} else {
} else
#endif
{
texturedata.fragmentFunction = SDL_METAL_FRAGMENT_COPY;
}
#if SDL_HAVE_YUV
if (yuv || nv12) {
size_t offset = 0;
SDL_YUV_CONVERSION_MODE mode = SDL_GetYUVConversionModeForResolution(texture->w, texture->h);
@@ -670,14 +636,8 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
}
texturedata.conversionBufferOffset = offset;
}
texture->driverdata = (void*)CFBridgingRetain(texturedata);
#if !__has_feature(objc_arc)
[texturedata release];
[mtltexture release];
[mtltexture_uv release];
#endif
texture->driverdata = (void*)CFBridgingRetain(texturedata);
return 0;
}}
@@ -738,10 +698,6 @@ METAL_UpdateTextureInternal(SDL_Renderer * renderer, METAL_TextureData *textured
return SDL_OutOfMemory();
}
#if !__has_feature(objc_arc)
[stagingtex autorelease];
#endif
METAL_UploadTextureData(stagingtex, stagingrect, 0, pixels, pitch);
if (data.mtlcmdencoder != nil) {
@@ -784,7 +740,7 @@ METAL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
if (METAL_UpdateTextureInternal(renderer, texturedata, texturedata.mtltexture, *rect, 0, pixels, pitch) < 0) {
return -1;
}
#if SDL_HAVE_YUV
if (texturedata.yuv) {
int Uslice = texture->format == SDL_PIXELFORMAT_YV12 ? 1 : 0;
int Vslice = texture->format == SDL_PIXELFORMAT_YV12 ? 0 : 1;
@@ -814,7 +770,7 @@ METAL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
return -1;
}
}
#endif
texturedata.hasdata = YES;
return 0;
@@ -895,10 +851,12 @@ METAL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
}
*pitch = SDL_BYTESPERPIXEL(texture->format) * rect->w;
#if SDL_HAVE_YUV
if (texturedata.yuv || texturedata.nv12) {
buffersize = ((*pitch) * rect->h) + (2 * (*pitch + 1) / 2) * ((rect->h + 1) / 2);
} else {
} else
#endif
{
buffersize = (*pitch) * rect->h;
}
@@ -911,11 +869,6 @@ METAL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
texturedata.lockedbuffer = lockedbuffer;
*pixels = [lockedbuffer contents];
/* METAL_TextureData.lockedbuffer retains. */
#if !__has_feature(objc_arc)
[lockedbuffer release];
#endif
return 0;
}}
@@ -952,7 +905,7 @@ METAL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
destinationSlice:0
destinationLevel:0
destinationOrigin:MTLOriginMake(rect.x, rect.y, 0)];
#if SDL_HAVE_YUV
if (texturedata.yuv) {
int Uslice = texture->format == SDL_PIXELFORMAT_YV12 ? 1 : 0;
int Vslice = texture->format == SDL_PIXELFORMAT_YV12 ? 0 : 1;
@@ -992,7 +945,7 @@ METAL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
destinationLevel:0
destinationOrigin:MTLOriginMake(UVrect.x, UVrect.y, 0)];
}
#endif
[blitcmd endEncoding];
[data.mtlcmdbuffer commit];
@@ -1084,8 +1037,14 @@ METAL_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int
METAL_QueueDrawPoints(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);
const size_t vertlen = (2 * sizeof (float) + sizeof (int)) * count;
const SDL_Color color = {
cmd->data.draw.r,
cmd->data.draw.g,
cmd->data.draw.b,
cmd->data.draw.a
};
const size_t vertlen = (2 * sizeof (float) + sizeof (SDL_Color)) * count;
float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
if (!verts) {
return -1;
@@ -1095,7 +1054,7 @@ METAL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL
for (int i = 0; i < count; i++, points++) {
*(verts++) = points->x;
*(verts++) = points->y;
*((int *)verts++) = color;
*((SDL_Color *)verts++) = color;
}
return 0;
}
@@ -1103,12 +1062,16 @@ METAL_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL
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);
const SDL_Color color = {
cmd->data.draw.r,
cmd->data.draw.g,
cmd->data.draw.b,
cmd->data.draw.a
};
SDL_assert(count >= 2); /* should have been checked at the higher level. */
const size_t vertlen = (2 * sizeof (float) + sizeof (int)) * count;
const size_t vertlen = (2 * sizeof (float) + sizeof (SDL_Color)) * count;
float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
if (!verts) {
return -1;
@@ -1118,7 +1081,7 @@ METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
for (int i = 0; i < count; i++, points++) {
*(verts++) = points->x;
*(verts++) = points->y;
*((int *)verts++) = color;
*((SDL_Color *)verts++) = color;
}
/* If the line segment is completely horizontal or vertical,
@@ -1148,7 +1111,7 @@ METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
static int
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,
const float *xy, int xy_stride, const SDL_Color *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)
{
@@ -1175,12 +1138,11 @@ METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
}
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_;
*((SDL_Color *)verts++) = *(SDL_Color *)((char*)color + j * color_stride);
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
@@ -1194,13 +1156,8 @@ METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
typedef struct
{
#if __has_feature(objc_arc)
__unsafe_unretained id<MTLRenderPipelineState> pipeline;
__unsafe_unretained id<MTLBuffer> vertex_buffer;
#else
id<MTLRenderPipelineState> pipeline;
id<MTLBuffer> vertex_buffer;
#endif
size_t constants_offset;
SDL_Texture *texture;
SDL_bool cliprect_dirty;
@@ -1240,22 +1197,29 @@ SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Met
}
if (statecache->cliprect_dirty) {
MTLScissorRect mtlrect;
SDL_Rect output;
SDL_Rect clip;
if (statecache->cliprect_enabled) {
const SDL_Rect *rect = &statecache->cliprect;
mtlrect.x = statecache->viewport.x + rect->x;
mtlrect.y = statecache->viewport.y + rect->y;
mtlrect.width = rect->w;
mtlrect.height = rect->h;
clip = statecache->cliprect;
clip.x += statecache->viewport.x;
clip.y += statecache->viewport.y;
} else {
mtlrect.x = statecache->viewport.x;
mtlrect.y = statecache->viewport.y;
mtlrect.width = statecache->viewport.w;
mtlrect.height = statecache->viewport.h;
clip = statecache->viewport;
}
if (mtlrect.width > 0 && mtlrect.height > 0) {
/* Set Scissor Rect Validation: w/h must be <= render pass */
SDL_zero(output);
METAL_GetOutputSize(renderer, &output.w, &output.h);
if (SDL_IntersectRect(&output, &clip, &clip)) {
MTLScissorRect mtlrect;
mtlrect.x = clip.x;
mtlrect.y = clip.y;
mtlrect.width = clip.w;
mtlrect.height = clip.h;
[data.mtlcmdencoder setScissorRect:mtlrect];
}
statecache->cliprect_dirty = SDL_FALSE;
}
@@ -1303,10 +1267,12 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t
}
[data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0];
#if SDL_HAVE_YUV
if (texturedata.yuv || texturedata.nv12) {
[data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture_uv atIndex:1];
[data.mtlcmdencoder setFragmentBuffer:data.mtlbufconstants offset:texturedata.conversionBufferOffset atIndex:1];
}
#endif
statecache->texture = texture;
}
return SDL_TRUE;
@@ -1341,9 +1307,6 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
* TODO: this buffer is also used for constants. Is performance still
* good for those, or should we have a managed buffer for them? */
mtlbufvertex = [data.mtldevice newBufferWithLength:vertsize options:MTLResourceStorageModeShared];
#if !__has_feature(objc_arc)
[mtlbufvertex autorelease];
#endif
mtlbufvertex.label = @"SDL vertex data";
SDL_memcpy([mtlbufvertex contents], vertices, vertsize);
@@ -1556,7 +1519,11 @@ METAL_DestroyRenderer(SDL_Renderer * renderer)
DestroyAllPipelines(data.allpipelines, data.pipelinescount);
SDL_Metal_DestroyView(data.mtlview);
/* Release the metal view instead of destroying it,
in case we want to use it later (recreating the renderer)
*/
/* SDL_Metal_DestroyView(data.mtlview); */
CFBridgingRelease(data.mtlview);
}
SDL_free(renderer);
@@ -1599,6 +1566,33 @@ METAL_SetVSync(SDL_Renderer * renderer, const int vsync)
return SDL_SetError("This Apple OS does not support displaySyncEnabled!");
}
static SDL_MetalView GetWindowView(SDL_Window *window)
{
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(window, &info)) {
#ifdef __MACOSX__
if (info.subsystem == SDL_SYSWM_COCOA) {
NSView *view = info.info.cocoa.window.contentView;
if (view.subviews.count > 0) {
view = view.subviews[0];
if (view.tag == SDL_METALVIEW_TAG) {
return (SDL_MetalView)CFBridgingRetain(view);
}
}
}
#else
if (info.subsystem == SDL_SYSWM_UIKIT) {
UIView *view = info.info.uikit.window.rootViewController.view;
if (view.tag == SDL_METALVIEW_TAG) {
return (SDL_MetalView)CFBridgingRetain(view);
}
}
#endif
}
return nil;
}
static SDL_Renderer *
METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
@@ -1650,12 +1644,12 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
return NULL;
}
view = SDL_Metal_CreateView(window);
view = GetWindowView(window);
if (view == nil) {
view = SDL_Metal_CreateView(window);
}
if (view == NULL) {
#if !__has_feature(objc_arc)
[mtldevice release];
#endif
SDL_free(renderer);
if (changed_window) {
SDL_RecreateWindow(window, window_flags);
@@ -1667,10 +1661,11 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
data = [[METAL_RenderData alloc] init];
if (data == nil) {
#if !__has_feature(objc_arc)
[mtldevice release];
#endif
SDL_Metal_DestroyView(view);
/* Release the metal view instead of destroying it,
in case we want to use it later (recreating the renderer)
*/
/* SDL_Metal_DestroyView(view); */
CFBridgingRelease(view);
SDL_free(renderer);
if (changed_window) {
SDL_RecreateWindow(window, window_flags);
@@ -1684,7 +1679,7 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
data.mtlview = view;
#ifdef __MACOSX__
layer = (CAMetalLayer *)[(NSView *)view layer];
layer = (CAMetalLayer *)[(__bridge NSView *)view layer];
#else
layer = (CAMetalLayer *)[(__bridge UIView *)view layer];
#endif
@@ -1709,9 +1704,6 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
id<MTLLibrary> mtllibrary = [data.mtldevice newLibraryWithData:mtllibdata error:&err];
data.mtllibrary = mtllibrary;
SDL_assert(err == nil);
#if !__has_feature(objc_arc)
dispatch_release(mtllibdata);
#endif
data.mtllibrary.label = @"SDL Metal renderer shader library";
/* Do some shader pipeline state loading up-front rather than on demand. */
@@ -1769,9 +1761,6 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
};
id<MTLBuffer> mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared];
#if !__has_feature(objc_arc)
[mtlbufconstantstaging autorelease];
#endif
char *constantdata = [mtlbufconstantstaging contents];
SDL_memcpy(constantdata + CONSTANTS_OFFSET_IDENTITY, identitytransform, sizeof(identitytransform));
@@ -1783,9 +1772,6 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
int quadcount = UINT16_MAX / 4;
size_t indicessize = sizeof(UInt16) * quadcount * 6;
id<MTLBuffer> mtlbufquadindicesstaging = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModeShared];
#if !__has_feature(objc_arc)
[mtlbufquadindicesstaging autorelease];
#endif
/* Quads in the following vertex order (matches the FillRects vertices):
* 1---3
@@ -1903,18 +1889,6 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.max_texture_width = maxtexsize;
renderer->info.max_texture_height = maxtexsize;
#if !__has_feature(objc_arc)
[mtlcmdqueue release];
[mtllibrary release];
[samplerdesc release];
[mtlsamplernearest release];
[mtlsamplerlinear release];
[mtlbufconstants release];
[mtlbufquadindices release];
[data release];
[mtldevice release];
#endif
return renderer;
}}

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -73,7 +73,7 @@ SDL_PROC_UNUSED(void, glColor4i, (GLint, GLint, GLint, GLint))
SDL_PROC_UNUSED(void, glColor4iv, (const GLint *))
SDL_PROC_UNUSED(void, glColor4s, (GLshort, GLshort, GLshort, GLshort))
SDL_PROC_UNUSED(void, glColor4sv, (const GLshort *))
SDL_PROC_UNUSED(void, glColor4ub,
SDL_PROC(void, glColor4ub,
(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha))
SDL_PROC_UNUSED(void, glColor4ubv, (const GLubyte * v))
SDL_PROC_UNUSED(void, glColor4ui,
@@ -86,7 +86,7 @@ SDL_PROC_UNUSED(void, glColorMask,
(GLboolean red, GLboolean green, GLboolean blue,
GLboolean alpha))
SDL_PROC_UNUSED(void, glColorMaterial, (GLenum face, GLenum mode))
SDL_PROC_UNUSED(void, glColorPointer,
SDL_PROC(void, glColorPointer,
(GLint size, GLenum type, GLsizei stride,
const GLvoid * pointer))
SDL_PROC_UNUSED(void, glCopyPixels,
@@ -111,8 +111,8 @@ SDL_PROC(void, glDepthFunc, (GLenum func))
SDL_PROC_UNUSED(void, glDepthMask, (GLboolean flag))
SDL_PROC_UNUSED(void, glDepthRange, (GLclampd zNear, GLclampd zFar))
SDL_PROC(void, glDisable, (GLenum cap))
SDL_PROC_UNUSED(void, glDisableClientState, (GLenum array))
SDL_PROC_UNUSED(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count))
SDL_PROC(void, glDisableClientState, (GLenum array))
SDL_PROC(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count))
SDL_PROC_UNUSED(void, glDrawBuffer, (GLenum mode))
SDL_PROC_UNUSED(void, glDrawElements,
(GLenum mode, GLsizei count, GLenum type,
@@ -125,7 +125,7 @@ SDL_PROC_UNUSED(void, glEdgeFlagPointer,
(GLsizei stride, const GLvoid * pointer))
SDL_PROC_UNUSED(void, glEdgeFlagv, (const GLboolean * flag))
SDL_PROC(void, glEnable, (GLenum cap))
SDL_PROC_UNUSED(void, glEnableClientState, (GLenum array))
SDL_PROC(void, glEnableClientState, (GLenum array))
SDL_PROC(void, glEnd, (void))
SDL_PROC_UNUSED(void, glEndList, (void))
SDL_PROC_UNUSED(void, glEvalCoord1d, (GLdouble u))
@@ -401,7 +401,7 @@ SDL_PROC_UNUSED(void, glTexCoord4iv, (const GLint * v))
SDL_PROC_UNUSED(void, glTexCoord4s,
(GLshort s, GLshort t, GLshort r, GLshort q))
SDL_PROC_UNUSED(void, glTexCoord4sv, (const GLshort * v))
SDL_PROC_UNUSED(void, glTexCoordPointer,
SDL_PROC(void, glTexCoordPointer,
(GLint size, GLenum type, GLsizei stride,
const GLvoid * pointer))
SDL_PROC(void, glTexEnvf, (GLenum target, GLenum pname, GLfloat param))
@@ -470,7 +470,7 @@ SDL_PROC_UNUSED(void, glVertex4iv, (const GLint * v))
SDL_PROC_UNUSED(void, glVertex4s,
(GLshort x, GLshort y, GLshort z, GLshort w))
SDL_PROC_UNUSED(void, glVertex4sv, (const GLshort * v))
SDL_PROC_UNUSED(void, glVertexPointer,
SDL_PROC(void, glVertexPointer,
(GLint size, GLenum type, GLsizei stride,
const GLvoid * pointer))
SDL_PROC(void, glViewport, (GLint x, GLint y, GLsizei width, GLsizei height))

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -30,6 +30,11 @@
#include <OpenGL/OpenGL.h>
#endif
#ifdef SDL_VIDEO_VITA_PVR_OGL
#include <GL/gl.h>
#include <GL/glext.h>
#endif
/* To prevent unnecessary window recreation,
* these should match the defaults selected in SDL_GL_ResetAttributes
*/
@@ -72,6 +77,9 @@ typedef struct
SDL_bool cliprect_dirty;
SDL_Rect cliprect;
SDL_bool texturing;
SDL_bool vertex_array;
SDL_bool color_array;
SDL_bool texture_array;
Uint32 color;
Uint32 clear_color;
} GL_DrawStateCache;
@@ -316,6 +324,20 @@ GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h)
return result;
}
static void
GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
{
/* If the window x/y/w/h changed at all, assume the viewport has been
* changed behind our backs. x/y changes might seem weird but viewport
* resets have been observed on macOS at minimum!
*/
if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
event->event == SDL_WINDOWEVENT_MOVED) {
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
data->drawstate.viewport_dirty = SDL_TRUE;
}
}
static int
GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
{
@@ -981,7 +1003,7 @@ GL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPo
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,
const float *xy, int xy_stride, const SDL_Color *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)
{
@@ -989,9 +1011,9 @@ GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *te
int i;
int count = indices ? num_indices : num_vertices;
GLfloat *verts;
int sz = 2 + 4 + (texture ? 2 : 0);
size_t sz = 2 * sizeof(GLfloat) + 4 * sizeof(Uint8) + (texture ? 2 : 0) * sizeof(GLfloat);
verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * sz * sizeof (GLfloat), 0, &cmd->data.draw.first);
verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
@@ -1006,7 +1028,6 @@ GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *te
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) {
@@ -1018,15 +1039,14 @@ GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *te
}
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;
/* Not really a float, but it is still 4 bytes and will be cast to the
right type in the graphics driver. */
SDL_memcpy(verts, ((char*)color + j * color_stride), sizeof(*color));
++verts;
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
@@ -1037,10 +1057,13 @@ GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *te
return 0;
}
static void
static int
SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader shader)
{
const SDL_BlendMode blend = cmd->data.draw.blend;
SDL_bool vertex_array;
SDL_bool color_array;
SDL_bool texture_array;
if (data->drawstate.viewport_dirty) {
const SDL_bool istarget = data->drawstate.target != NULL;
@@ -1106,9 +1129,46 @@ SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader
data->drawstate.texturing = SDL_TRUE;
}
}
vertex_array = cmd->command == SDL_RENDERCMD_DRAW_POINTS
|| cmd->command == SDL_RENDERCMD_DRAW_LINES
|| cmd->command == SDL_RENDERCMD_GEOMETRY;
color_array = cmd->command == SDL_RENDERCMD_GEOMETRY;
texture_array = cmd->data.draw.texture != NULL;
if (vertex_array != data->drawstate.vertex_array) {
if (vertex_array) {
data->glEnableClientState(GL_VERTEX_ARRAY);
} else {
data->glDisableClientState(GL_VERTEX_ARRAY);
}
data->drawstate.vertex_array = vertex_array;
}
if (color_array != data->drawstate.color_array) {
if (color_array) {
data->glEnableClientState(GL_COLOR_ARRAY);
} else {
data->glDisableClientState(GL_COLOR_ARRAY);
}
data->drawstate.color_array = color_array;
}
/* This is a little awkward but should avoid texcoord arrays getting into
a bad state if SDL_GL_BindTexture/UnbindTexture are called. */
if (texture_array != data->drawstate.texture_array) {
if (texture_array) {
data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
} else {
data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
data->drawstate.texture_array = texture_array;
}
return 0;
}
static void
static int
SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
{
SDL_Texture *texture = cmd->data.draw.texture;
@@ -1144,6 +1204,8 @@ SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
data->drawstate.texture = texture;
}
return 0;
}
static int
@@ -1151,7 +1213,6 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
{
/* !!! FIXME: it'd be nice to use a vertex buffer instead of immediate mode... */
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
size_t i;
if (GL_ActivateRenderer(renderer) < 0) {
return -1;
@@ -1170,9 +1231,9 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
}
#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
// On macOS on older systems, the OpenGL view change and resize events aren't
// necessarily synchronized, so just always reset it.
// Workaround for: https://discourse.libsdl.org/t/sdl-2-0-22-prerelease/35306/6
data->drawstate.viewport_dirty = SDL_TRUE;
#endif
@@ -1185,10 +1246,7 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
const Uint8 a = cmd->data.color.a;
const Uint32 color = (((Uint32)a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.color) {
data->glColor4f((GLfloat) r * inv255f,
(GLfloat) g * inv255f,
(GLfloat) b * inv255f,
(GLfloat) a * inv255f);
data->glColor4ub((GLubyte) r, (GLubyte) g, (GLubyte) b, (GLubyte) a);
data->drawstate.color = color;
}
break;
@@ -1209,6 +1267,7 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
}
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
data->drawstate.cliprect_dirty = SDL_TRUE;
@@ -1237,32 +1296,6 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
}
data->glClear(GL_COLOR_BUFFER_BIT);
break;
}
case SDL_RENDERCMD_DRAW_POINTS: {
const size_t count = cmd->data.draw.count;
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
SetDrawState(data, cmd, SHADER_SOLID);
data->glBegin(GL_POINTS);
for (i = 0; i < count; i++, verts += 2) {
data->glVertex2f(verts[0], verts[1]);
}
data->glEnd();
break;
}
case SDL_RENDERCMD_DRAW_LINES: {
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
const size_t count = cmd->data.draw.count;
SDL_assert(count >= 2);
SetDrawState(data, cmd, SHADER_SOLID);
data->glBegin(GL_LINE_STRIP);
for (i = 0; i < count; ++i, verts += 2) {
data->glVertex2f(verts[0], verts[1]);
}
data->glEnd();
break;
}
@@ -1275,47 +1308,113 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
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;
case SDL_RENDERCMD_DRAW_LINES: {
if (SetDrawState(data, cmd, SHADER_SOLID) == 0) {
size_t count = cmd->data.draw.count;
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
if (texture) {
SetCopyState(data, cmd);
} else {
SetDrawState(data, cmd, SHADER_SOLID);
}
/* SetDrawState handles glEnableClientState. */
data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, verts);
{
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++);
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;
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);
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 += nextcmd->data.draw.count;
}
nextcmd = nextcmd->next;
}
data->glVertex2f(x, y);
data->glDrawArrays(GL_LINES, 0, (GLsizei)count);
cmd = finalcmd; /* skip any copy commands we just combined in here. */
}
data->glEnd();
data->glColor4f(currentColor[0], currentColor[1], currentColor[2], currentColor[3]);
}
break;
}
}
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 += nextcmd->data.draw.count;
}
nextcmd = nextcmd->next;
}
if (thistexture) {
ret = SetCopyState(data, cmd);
} else {
ret = SetDrawState(data, cmd, SHADER_SOLID);
}
if (ret == 0) {
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
int op = GL_TRIANGLES; /* SDL_RENDERCMD_GEOMETRY */
if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) {
op = GL_POINTS;
}
if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) {
/* SetDrawState handles glEnableClientState. */
data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, verts);
} else {
/* SetDrawState handles glEnableClientState. */
if (thistexture) {
data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 5, verts + 0);
data->glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(float) * 5, verts + 2);
data->glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 5, verts + 3);
} else {
data->glVertexPointer(2, GL_FLOAT, sizeof(float) * 3, verts + 0);
data->glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(float) * 3, verts + 2);
}
}
data->glDrawArrays(op, 0, (GLsizei) count);
/* Restore previously set color when we're done. */
if (thiscmdtype != SDL_RENDERCMD_DRAW_POINTS) {
Uint32 color = data->drawstate.color;
GLubyte a = (GLubyte)((color >> 24) & 0xFF);
GLubyte r = (GLubyte)((color >> 16) & 0xFF);
GLubyte g = (GLubyte)((color >> 8) & 0xFF);
GLubyte b = (GLubyte)((color >> 0) & 0xFF);
data->glColor4ub(r, g, b, a);
}
}
cmd = finalcmd; /* skip any copy commands we just combined in here. */
break;
}
case SDL_RENDERCMD_NO_OP:
break;
@@ -1324,6 +1423,21 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
cmd = cmd->next;
}
/* Turn off vertex array state when we're done, in case external code
relies on it being off. */
if (data->drawstate.vertex_array) {
data->glDisableClientState(GL_VERTEX_ARRAY);
data->drawstate.vertex_array = SDL_FALSE;
}
if (data->drawstate.color_array) {
data->glDisableClientState(GL_COLOR_ARRAY);
data->drawstate.color_array = SDL_FALSE;
}
if (data->drawstate.texture_array) {
data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
data->drawstate.texture_array = SDL_FALSE;
}
return GL_CheckError("", renderer);
}
@@ -1595,6 +1709,32 @@ GL_SetVSync(SDL_Renderer * renderer, const int vsync)
return retval;
}
static SDL_bool
GL_IsProbablyAccelerated(const GL_RenderData *data)
{
/*const char *vendor = (const char *) data->glGetString(GL_VENDOR);*/
const char *renderer = (const char *) data->glGetString(GL_RENDERER);
#ifdef __WINDOWS__
if (SDL_strcmp(renderer, "GDI Generic") == 0) {
return SDL_FALSE; /* Microsoft's fallback software renderer. Fix your system! */
}
#endif
#ifdef __APPLE__
if (SDL_strcmp(renderer, "Apple Software Renderer") == 0) {
return SDL_FALSE; /* (a probably very old) Apple software-based OpenGL. */
}
#endif
if (SDL_strcmp(renderer, "Software Rasterizer") == 0) {
return SDL_FALSE; /* (a probably very old) Software Mesa, or some other generic thing. */
}
/* !!! FIXME: swrast? llvmpipe? softpipe? */
return SDL_TRUE;
}
static SDL_Renderer *
GL_CreateRenderer(SDL_Window * window, Uint32 flags)
@@ -1605,11 +1745,14 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
Uint32 window_flags;
int profile_mask = 0, major = 0, minor = 0;
SDL_bool changed_window = SDL_FALSE;
const char *hint;
SDL_bool non_power_of_two_supported = SDL_FALSE;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
#ifndef SDL_VIDEO_VITA_PVR_OGL
window_flags = SDL_GetWindowFlags(window);
if (!(window_flags & SDL_WINDOW_OPENGL) ||
profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
@@ -1623,6 +1766,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
goto error;
}
}
#endif
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
@@ -1637,6 +1781,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
goto error;
}
renderer->WindowEvent = GL_WindowEvent;
renderer->GetOutputSize = GL_GetOutputSize;
renderer->SupportsBlendMode = GL_SupportsBlendMode;
renderer->CreateTexture = GL_CreateTexture;
@@ -1663,7 +1808,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->GL_BindTexture = GL_BindTexture;
renderer->GL_UnbindTexture = GL_UnbindTexture;
renderer->info = GL_RenderDriver.info;
renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->info.flags = 0; /* will set some flags below. */
renderer->driverdata = data;
renderer->window = window;
@@ -1687,6 +1832,10 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
goto error;
}
if (GL_IsProbablyAccelerated(data)) {
renderer->info.flags |= SDL_RENDERER_ACCELERATED;
}
#ifdef __MACOSX__
/* Enable multi-threaded rendering */
/* Disabled until Ryan finishes his VBO/PBO code...
@@ -1720,15 +1869,37 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
data->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
}
hint = SDL_getenv("GL_ARB_texture_non_power_of_two");
if (!hint || *hint != '0') {
SDL_bool isGL2 = SDL_FALSE;
const char *verstr = (const char *)data->glGetString(GL_VERSION);
if (verstr) {
char verbuf[16];
char *ptr;
SDL_strlcpy(verbuf, verstr, sizeof (verbuf));
ptr = SDL_strchr(verbuf, '.');
if (ptr) {
*ptr = '\0';
if (SDL_atoi(verbuf) >= 2) {
isGL2 = SDL_TRUE;
}
}
}
if (isGL2 || SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) {
non_power_of_two_supported = SDL_TRUE;
}
}
data->textype = GL_TEXTURE_2D;
if (SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) {
if (non_power_of_two_supported) {
data->GL_ARB_texture_non_power_of_two_supported = SDL_TRUE;
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
renderer->info.max_texture_width = value;
renderer->info.max_texture_height = value;
} else if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") ||
SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
data->textype = GL_TEXTURE_RECTANGLE_ARB;
}
if (data->GL_ARB_texture_rectangle_supported) {
data->glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &value);
renderer->info.max_texture_width = value;
renderer->info.max_texture_height = value;
@@ -1753,7 +1924,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
}
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
data->shaders ? "ENABLED" : "DISABLED");
#if SDL_HAVE_YUV
/* We support YV12 textures using 3 textures and a shader */
if (data->shaders && data->num_texture_units >= 3) {
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
@@ -1761,7 +1932,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
}
#endif
#ifdef __MACOSX__
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_UYVY;
#endif
@@ -1790,7 +1961,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
data->glDisable(GL_SCISSOR_TEST);
data->glDisable(data->textype);
data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
data->glColor4ub(255, 255, 255, 255);
/* This ended up causing video discrepancies between OpenGL and Direct3D */
/* data->glEnable(GL_LINE_SMOOTH); */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -284,7 +284,7 @@ static const char *shader_source[NUM_SHADERS][2] =
" gl_FragColor = texture2D(tex0, v_texCoord) * v_color;\n"
"}"
},
#if SDL_HAVE_YUV
/* SHADER_YUV_JPEG */
{
/* vertex shader */
@@ -384,6 +384,7 @@ static const char *shader_source[NUM_SHADERS][2] =
BT709_SHADER_CONSTANTS
NV21_SHADER_BODY
},
#endif /* SDL_HAVE_YUV */
};
static SDL_bool

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -32,6 +32,7 @@ typedef enum {
SHADER_SOLID,
SHADER_RGB,
SHADER_RGBA,
#if SDL_HAVE_YUV
SHADER_YUV_JPEG,
SHADER_YUV_BT601,
SHADER_YUV_BT709,
@@ -43,6 +44,7 @@ typedef enum {
SHADER_NV21_JPEG,
SHADER_NV21_BT601,
SHADER_NV21_BT709,
#endif
NUM_SHADERS
} GL_Shader;

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -603,7 +603,7 @@ GLES_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_F
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,
const float *xy, int xy_stride, const SDL_Color *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)
{

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -28,6 +28,17 @@
#include "../../video/SDL_blit.h"
#include "SDL_shaders_gles2.h"
/* WebGL doesn't offer client-side arrays, so use Vertex Buffer Objects
on Emscripten, which converts GLES2 into WebGL calls.
In all other cases, attempt to use client-side arrays, as they tend to
be dramatically faster when not batching, and about the same when
we are. */
#if defined(__EMSCRIPTEN__)
#define USE_VERTEX_BUFFER_OBJECTS 1
#else
#define USE_VERTEX_BUFFER_OBJECTS 0
#endif
/* To prevent unnecessary window recreation,
* these should match the defaults selected in SDL_GL_ResetAttributes
*/
@@ -151,9 +162,12 @@ typedef struct GLES2_RenderData
GLES2_ProgramCache program_cache;
Uint8 clear_r, clear_g, clear_b, clear_a;
#if USE_VERTEX_BUFFER_OBJECTS
GLuint vertex_buffers[8];
size_t vertex_buffer_size[8];
int current_vertex_buffer;
#endif
GLES2_DrawStateCache drawstate;
} GLES2_RenderData;
@@ -480,7 +494,7 @@ GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, GLenum shader_t
{
GLuint id;
GLint compileSuccessful = GL_FALSE;
const Uint8 *shader_src = GLES2_GetShader(type);
const char *shader_src = (char *)GLES2_GetShader(type);
if (!shader_src) {
SDL_SetError("No shader src");
@@ -489,7 +503,7 @@ GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, GLenum shader_t
/* Compile */
id = data->glCreateShader(shader_type);
data->glShaderSource(id, 1, (const char**)&shader_src, NULL);
data->glShaderSource(id, 1, &shader_src, NULL);
data->glCompileShader(id);
data->glGetShaderiv(id, GL_COMPILE_STATUS, &compileSuccessful);
@@ -547,6 +561,7 @@ GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int
case GLES2_IMAGESOURCE_TEXTURE_BGR:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR;
break;
#if SDL_HAVE_YUV
case GLES2_IMAGESOURCE_TEXTURE_YUV:
switch (SDL_GetYUVConversionModeForResolution(w, h)) {
case SDL_YUV_CONVERSION_JPEG:
@@ -603,6 +618,7 @@ GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int
goto fault;
}
break;
#endif /* SDL_HAVE_YUV */
case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES;
break;
@@ -663,26 +679,30 @@ static int
GLES2_QueueDrawPoints(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;
const size_t vertlen = (2 * sizeof (float) + sizeof (int)) * count;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
SDL_VertexSolid *verts = (SDL_VertexSolid *) SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
int i;
SDL_Color color;
color.r = cmd->data.draw.r;
color.g = cmd->data.draw.g;
color.b = cmd->data.draw.b;
color.a = cmd->data.draw.a;
if (!verts) {
return -1;
}
if (colorswap == 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);
if (colorswap) {
Uint8 r = color.r;
color.r = color.b;
color.b = r;
}
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;
verts->position.x = 0.5f + points[i].x;
verts->position.y = 0.5f + points[i].y;
verts->color = color;
verts++;
}
return 0;
@@ -692,19 +712,23 @@ 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;
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);
SDL_VertexSolid *verts = (SDL_VertexSolid *) SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
SDL_Color color;
color.r = cmd->data.draw.r;
color.g = cmd->data.draw.g;
color.b = cmd->data.draw.b;
color.a = cmd->data.draw.a;
if (!verts) {
return -1;
}
if (colorswap == 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);
if (colorswap) {
Uint8 r = color.r;
color.r = color.b;
color.b = r;
}
cmd->data.draw.count = count;
@@ -712,9 +736,10 @@ GLES2_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
/* 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;
verts->position.x = prevx;
verts->position.y = prevy;
verts->color = color;
verts++;
/* bump the end of each line segment out a quarter of a pixel, to provoke
the diamond-exit rule. Without this, you won't just drop the last
@@ -731,9 +756,10 @@ GLES2_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
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;
verts->position.x = prevx;
verts->position.y = prevy;
verts->color = color;
verts++;
}
return 0;
@@ -741,59 +767,92 @@ GLES2_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_
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,
const float *xy, int xy_stride, const SDL_Color *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;
if (texture) {
SDL_Vertex *verts = (SDL_Vertex *) SDL_AllocateRenderVertices(renderer, count * sizeof (*verts), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
xy_ = (float *)((char*)xy + j * xy_stride);
col_ = *(int *)((char*)color + j * color_stride);
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;
}
*(verts++) = xy_[0] * scale_x;
*(verts++) = xy_[1] * scale_y;
xy_ = (float *)((char*)xy + j * xy_stride);
col_ = *(SDL_Color *)((char*)color + j * color_stride);
uv_ = (float *)((char*)uv + j * uv_stride);
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_;
verts->position.x = xy_[0] * scale_x;
verts->position.y = xy_[1] * scale_y;
if (colorswap) {
Uint8 r = col_.r;
col_.r = col_.b;
col_.b = r;
}
verts->color = col_;
verts->tex_coord.x = uv_[0];
verts->tex_coord.y = uv_[1];
verts++;
}
if (texture) {
float *uv_ = (float *)((char*)uv + j * uv_stride);
*(verts++) = uv_[0];
*(verts++) = uv_[1];
} else {
SDL_VertexSolid *verts = (SDL_VertexSolid *) SDL_AllocateRenderVertices(renderer, count * sizeof (*verts), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
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->position.x = xy_[0] * scale_x;
verts->position.y = xy_[1] * scale_y;
if (colorswap) {
Uint8 r = col_.r;
col_.r = col_.b;
col_.b = r;
}
verts->color = col_;
verts++;
}
}
@@ -801,12 +860,12 @@ GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
}
static int
SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc)
SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc, void *vertices)
{
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 */;
int stride;
SDL_assert((texture != NULL) == (imgsrc != GLES2_IMAGESOURCE_SOLID));
@@ -841,47 +900,25 @@ SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_I
data->drawstate.cliprect_dirty = SDL_FALSE;
}
if (texture != data->drawstate.texture) {
if ((texture != NULL) != data->drawstate.texturing) {
if (texture == NULL) {
data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
data->drawstate.texturing = SDL_FALSE;
} else {
data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
data->drawstate.texturing = SDL_TRUE;
}
if ((texture != NULL) != data->drawstate.texturing) {
if (texture == NULL) {
data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
data->drawstate.texturing = SDL_FALSE;
} else {
data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
data->drawstate.texturing = SDL_TRUE;
}
if (texture) {
GLES2_TextureData *tdata = (GLES2_TextureData *) texture->driverdata;
#if SDL_HAVE_YUV
if (tdata->yuv) {
data->glActiveTexture(GL_TEXTURE2);
data->glBindTexture(tdata->texture_type, tdata->texture_v);
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
} else if (tdata->nv12) {
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
}
#endif
data->glBindTexture(tdata->texture_type, tdata->texture);
}
data->drawstate.texture = texture;
}
if (texture) {
stride += sizeof (GLfloat) * 2; /* tex coord */
stride = sizeof(SDL_Vertex);
} else {
stride = sizeof(SDL_VertexSolid);
}
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)));
SDL_Vertex *verts = (SDL_Vertex *) (((Uint8 *) vertices) + cmd->data.draw.first);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->tex_coord);
}
if (GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) {
@@ -913,18 +950,22 @@ 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, 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));
{
SDL_VertexSolid *verts = (SDL_VertexSolid *) (((Uint8 *) vertices) + cmd->data.draw.first);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *) &verts->position);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE /* Normalized */, stride, (const GLvoid *) &verts->color);
}
return 0;
}
static int
SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, void *vertices)
{
GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
SDL_Texture *texture = cmd->data.draw.texture;
int ret;
/* Pick an appropriate shader */
if (renderer->target) {
@@ -979,6 +1020,7 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
break;
}
break;
#if SDL_HAVE_YUV
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_YV12:
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
@@ -989,6 +1031,7 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
case SDL_PIXELFORMAT_NV21:
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
break;
#endif
case SDL_PIXELFORMAT_EXTERNAL_OES:
sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
break;
@@ -1012,6 +1055,7 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
case SDL_PIXELFORMAT_BGR888:
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
break;
#if SDL_HAVE_YUV
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_YV12:
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
@@ -1022,6 +1066,7 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
case SDL_PIXELFORMAT_NV21:
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
break;
#endif
case SDL_PIXELFORMAT_EXTERNAL_OES:
sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
break;
@@ -1030,7 +1075,31 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
}
}
return SetDrawState(data, cmd, sourceType);
ret = SetDrawState(data, cmd, sourceType, vertices);
if (texture != data->drawstate.texture) {
GLES2_TextureData *tdata = (GLES2_TextureData *) texture->driverdata;
#if SDL_HAVE_YUV
if (tdata->yuv) {
data->glActiveTexture(GL_TEXTURE2);
data->glBindTexture(tdata->texture_type, tdata->texture_v);
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
} else if (tdata->nv12) {
data->glActiveTexture(GL_TEXTURE1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
data->glActiveTexture(GL_TEXTURE0);
}
#endif
data->glBindTexture(tdata->texture_type, tdata->texture);
data->drawstate.texture = texture;
}
return ret;
}
static int
@@ -1038,8 +1107,11 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
{
GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
#if USE_VERTEX_BUFFER_OBJECTS
const int vboidx = data->current_vertex_buffer;
const GLuint vbo = data->vertex_buffers[vboidx];
#endif
if (GLES2_ActivateRenderer(renderer) < 0) {
return -1;
@@ -1057,6 +1129,7 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
}
}
#if USE_VERTEX_BUFFER_OBJECTS
/* upload the new VBO data for this set of commands. */
data->glBindBuffer(GL_ARRAY_BUFFER, vbo);
if (data->vertex_buffer_size[vboidx] < vertsize) {
@@ -1071,6 +1144,8 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
data->current_vertex_buffer = 0;
}
vertices = NULL; /* attrib pointers will be offsets into the VBO. */
#endif
while (cmd) {
switch (cmd->command) {
@@ -1135,7 +1210,7 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
break;
case SDL_RENDERCMD_DRAW_LINES: {
if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID, vertices) == 0) {
size_t count = cmd->data.draw.count;
if (count > 2) {
/* joined lines cannot be grouped */
@@ -1156,7 +1231,7 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
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;
count += nextcmd->data.draw.count;
}
nextcmd = nextcmd->next;
}
@@ -1187,21 +1262,21 @@ GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
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;
count += nextcmd->data.draw.count;
}
nextcmd = nextcmd->next;
}
if (thistexture) {
ret = SetCopyState(renderer, cmd);
ret = SetCopyState(renderer, cmd, vertices);
} else {
ret = SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID);
ret = SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID, vertices);
}
if (ret == 0) {
int op = GL_TRIANGLES; /* SDL_RENDERCMD_GEOMETRY */
if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) {
op = GL_POINTS;
op = GL_POINTS;
}
data->glDrawArrays(op, 0, (GLsizei) count);
}
@@ -1259,8 +1334,10 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer)
data->framebuffers = nextnode;
}
#if USE_VERTEX_BUFFER_OBJECTS
data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
GL_CheckError("", renderer);
#endif
SDL_GL_DeleteContext(data->context);
}
@@ -1293,6 +1370,7 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
break;
#if SDL_HAVE_YUV
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_NV12:
@@ -1300,6 +1378,7 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
format = GL_LUMINANCE;
type = GL_UNSIGNED_BYTE;
break;
#endif
#ifdef GL_TEXTURE_EXTERNAL_OES
case SDL_PIXELFORMAT_EXTERNAL_OES:
format = GL_NONE;
@@ -1437,6 +1516,9 @@ static int
GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp)
{
Uint8 *blob = NULL;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 *blob2 = NULL;
#endif
Uint8 *src;
int src_pitch;
int y;
@@ -1463,10 +1545,33 @@ GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoffset, GLint
src = blob;
}
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
if (format == GL_RGBA) {
int i;
Uint32 *src32 = (Uint32 *)src;
blob2 = (Uint32 *)SDL_malloc(src_pitch * height);
if (!blob2) {
if (blob) {
SDL_free(blob);
}
return SDL_OutOfMemory();
}
for (i = 0; i < (src_pitch * height) / 4; i++) {
blob2[i] = SDL_Swap32(src32[i]);
}
src = (Uint8 *) blob2;
}
#endif
data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
if (blob) {
SDL_free(blob);
}
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
if (blob2) {
SDL_free(blob2);
}
#endif
return 0;
}
@@ -1996,8 +2101,10 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
renderer->info.max_texture_height = value;
#if USE_VERTEX_BUFFER_OBJECTS
/* we keep a few of these and cycle through them, so data can live for a few frames. */
data->glGenBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
#endif
data->framebuffers = NULL;
data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
@@ -2030,11 +2137,12 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->SetVSync = GLES2_SetVSync;
renderer->GL_BindTexture = GLES2_BindTexture;
renderer->GL_UnbindTexture = GLES2_UnbindTexture;
#if SDL_HAVE_YUV
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
#endif
#ifdef GL_TEXTURE_EXTERNAL_OES
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_EXTERNAL_OES;
#endif
@@ -2090,3 +2198,4 @@ SDL_RenderDriver GLES2_RenderDriver = {
#endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -121,6 +121,8 @@ static const Uint8 GLES2_Fragment_TextureBGR[] = " \
} \
";
#if SDL_HAVE_YUV
#define JPEG_SHADER_CONSTANTS \
"// YUV offset \n" \
"const vec3 offset = vec3(0, -0.501960814, -0.501960814);\n" \
@@ -299,6 +301,7 @@ static const Uint8 GLES2_Fragment_TextureNV21BT709[] = \
BT709_SHADER_CONSTANTS \
NV21_SHADER_BODY \
;
#endif
/* Custom Android video format texture */
static const Uint8 GLES2_Fragment_TextureExternalOES[] = " \
@@ -335,6 +338,7 @@ const Uint8 *GLES2_GetShader(GLES2_ShaderType type)
return GLES2_Fragment_TextureRGB;
case GLES2_SHADER_FRAGMENT_TEXTURE_BGR:
return GLES2_Fragment_TextureBGR;
#if SDL_HAVE_YUV
case GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG:
return GLES2_Fragment_TextureYUVJPEG;
case GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601:
@@ -357,6 +361,7 @@ const Uint8 *GLES2_GetShader(GLES2_ShaderType type)
return GLES2_Fragment_TextureNV21BT601;
case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709:
return GLES2_Fragment_TextureNV21BT709;
#endif
case GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES:
return GLES2_Fragment_TextureExternalOES;
default:

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -34,6 +34,7 @@ typedef enum
GLES2_SHADER_FRAGMENT_TEXTURE_ARGB,
GLES2_SHADER_FRAGMENT_TEXTURE_BGR,
GLES2_SHADER_FRAGMENT_TEXTURE_RGB,
#if SDL_HAVE_YUV
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG,
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601,
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709,
@@ -45,6 +46,7 @@ typedef enum
GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG,
GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601,
GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709,
#endif
GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES,
GLES2_SHADER_COUNT
} GLES2_ShaderType;

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -220,7 +220,7 @@ SDL_BlendFillRect(SDL_Surface * dst, const SDL_Rect * rect,
SDL_Rect clipped;
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
return SDL_InvalidParamError("SDL_BlendFillRect(): dst");
}
/* This function doesn't work on surfaces < 8 bpp */
@@ -291,7 +291,7 @@ SDL_BlendFillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
int status = 0;
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
return SDL_InvalidParamError("SDL_BlendFillRects(): dst");
}
/* This function doesn't work on surfaces < 8 bpp */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -809,7 +809,7 @@ SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2,
BlendLineFunc func;
if (!dst) {
return SDL_SetError("SDL_BlendLine(): Passed NULL destination surface");
return SDL_InvalidParamError("SDL_BlendLine(): dst");
}
func = SDL_CalculateBlendLineFunc(dst->format);

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -218,7 +218,7 @@ SDL_BlendPoint(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r
Uint8 g, Uint8 b, Uint8 a)
{
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
return SDL_InvalidParamError("SDL_BlendPoint(): dst");
}
/* This function doesn't work on surfaces < 8 bpp */
@@ -287,7 +287,7 @@ SDL_BlendPoints(SDL_Surface * dst, const SDL_Point * points, int count,
int status = 0;
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
return SDL_InvalidParamError("SDL_BlendPoints(): dst");
}
/* This function doesn't work on surfaces < 8 bpp */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -144,7 +144,7 @@ SDL_DrawLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color)
DrawLineFunc func;
if (!dst) {
return SDL_SetError("SDL_DrawLine(): Passed NULL destination surface");
return SDL_InvalidParamError("SDL_DrawLine(): dst");
}
func = SDL_CalculateDrawLineFunc(dst->format);
@@ -173,7 +173,7 @@ SDL_DrawLines(SDL_Surface * dst, const SDL_Point * points, int count,
DrawLineFunc func;
if (!dst) {
return SDL_SetError("SDL_DrawLines(): Passed NULL destination surface");
return SDL_InvalidParamError("SDL_DrawLines(): dst");
}
func = SDL_CalculateDrawLineFunc(dst->format);

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -30,7 +30,7 @@ int
SDL_DrawPoint(SDL_Surface * dst, int x, int y, Uint32 color)
{
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
return SDL_InvalidParamError("SDL_DrawPoint(): dst");
}
/* This function doesn't work on surfaces < 8 bpp */
@@ -71,7 +71,7 @@ SDL_DrawPoints(SDL_Surface * dst, const SDL_Point * points, int count,
int x, y;
if (!dst) {
return SDL_SetError("Passed NULL destination surface");
return SDL_InvalidParamError("SDL_DrawPoints(): dst");
}
/* This function doesn't work on surfaces < 8 bpp */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -99,8 +99,7 @@ SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
return 0;
}
SDL_SetError("Software renderer doesn't have an output surface");
return -1;
return SDL_SetError("Software renderer doesn't have an output surface");
}
static int
@@ -274,12 +273,14 @@ typedef struct CopyExData
double angle;
SDL_FPoint center;
SDL_RendererFlip flip;
float scale_x;
float scale_y;
} CopyExData;
static int
SW_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)
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip, float scale_x, float scale_y)
{
CopyExData *verts = (CopyExData *) SDL_AllocateRenderVertices(renderer, sizeof (CopyExData), 0, &cmd->data.draw.first);
@@ -298,21 +299,41 @@ SW_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * te
verts->angle = angle;
SDL_memcpy(&verts->center, center, sizeof (SDL_FPoint));
verts->flip = flip;
verts->scale_x = scale_x;
verts->scale_y = scale_y;
return 0;
}
static int
Blit_to_Screen(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *surface, SDL_Rect *dstrect,
float scale_x, float scale_y, SDL_ScaleMode scaleMode)
{
int retval;
/* Renderer scaling, if needed */
if (scale_x != 1.0f || scale_y != 1.0f) {
SDL_Rect r;
r.x = (int)((float) dstrect->x * scale_x);
r.y = (int)((float) dstrect->y * scale_y);
r.w = (int)((float) dstrect->w * scale_x);
r.h = (int)((float) dstrect->h * scale_y);
retval = SDL_PrivateUpperBlitScaled(src, srcrect, surface, &r, scaleMode);
} else {
retval = SDL_BlitSurface(src, srcrect, surface, dstrect);
}
return retval;
}
static int
SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * final_rect,
const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip)
const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip, float scale_x, float scale_y)
{
SDL_Surface *src = (SDL_Surface *) texture->driverdata;
SDL_Rect tmp_rect;
SDL_Surface *src_clone, *src_rotated, *src_scaled;
SDL_Surface *mask = NULL, *mask_rotated = NULL;
int retval = 0, dstwidth, dstheight, abscenterx, abscentery;
double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
int retval = 0;
SDL_BlendMode blendmode;
Uint8 alphaMod, rMod, gMod, bMod;
int applyModulation = SDL_FALSE;
@@ -414,53 +435,32 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
SDL_SetSurfaceBlendMode(src_clone, blendmode);
if (!retval) {
SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle);
src_rotated = SDLgfx_rotateSurface(src_clone, angle, dstwidth/2, dstheight/2, (texture->scaleMode == SDL_ScaleModeNearest) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
SDL_Rect rect_dest;
double cangle, sangle;
SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, center,
&rect_dest, &cangle, &sangle);
src_rotated = SDLgfx_rotateSurface(src_clone, angle,
(texture->scaleMode == SDL_ScaleModeNearest) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL,
&rect_dest, cangle, sangle, center);
if (src_rotated == NULL) {
retval = -1;
}
if (!retval && mask != NULL) {
/* The mask needed for the NONE blend mode gets rotated with the same parameters. */
mask_rotated = SDLgfx_rotateSurface(mask, angle, dstwidth/2, dstheight/2, SDL_FALSE, 0, 0, dstwidth, dstheight, cangle, sangle);
mask_rotated = SDLgfx_rotateSurface(mask, angle,
SDL_FALSE, 0, 0,
&rect_dest, cangle, sangle, center);
if (mask_rotated == NULL) {
retval = -1;
}
}
if (!retval) {
/* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
abscenterx = final_rect->x + (int)center->x;
abscentery = final_rect->y + (int)center->y;
/* Compensate the angle inversion to match the behaviour of the other backends */
sangle = -sangle;
/* Top Left */
px = final_rect->x - abscenterx;
py = final_rect->y - abscentery;
p1x = px * cangle - py * sangle + abscenterx;
p1y = px * sangle + py * cangle + abscentery;
/* Top Right */
px = final_rect->x + final_rect->w - abscenterx;
py = final_rect->y - abscentery;
p2x = px * cangle - py * sangle + abscenterx;
p2y = px * sangle + py * cangle + abscentery;
/* Bottom Left */
px = final_rect->x - abscenterx;
py = final_rect->y + final_rect->h - abscentery;
p3x = px * cangle - py * sangle + abscenterx;
p3y = px * sangle + py * cangle + abscentery;
/* Bottom Right */
px = final_rect->x + final_rect->w - abscenterx;
py = final_rect->y + final_rect->h - abscentery;
p4x = px * cangle - py * sangle + abscenterx;
p4y = px * sangle + py * cangle + abscentery;
tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x));
tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y));
tmp_rect.w = dstwidth;
tmp_rect.h = dstheight;
tmp_rect.x = final_rect->x + rect_dest.x;
tmp_rect.y = final_rect->y + rect_dest.y;
tmp_rect.w = rect_dest.w;
tmp_rect.h = rect_dest.h;
/* The NONE blend mode needs some special care with non-opaque surfaces.
* Other blend modes or opaque surfaces can be blitted directly.
@@ -471,7 +471,8 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
SDL_SetSurfaceAlphaMod(src_rotated, alphaMod);
SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod);
}
retval = SDL_BlitSurface(src_rotated, NULL, surface, &tmp_rect);
/* Renderer scaling, if needed */
retval = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode);
} else {
/* The NONE blend mode requires three steps to get the pixels onto the destination surface.
* First, the area where the rotated pixels will be blitted to get set to zero.
@@ -480,7 +481,8 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
*/
SDL_Rect mask_rect = tmp_rect;
SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE);
retval = SDL_BlitSurface(mask_rotated, NULL, surface, &mask_rect);
/* Renderer scaling, if needed */
retval = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
if (!retval) {
/* The next step copies the alpha value. This is done with the BLEND blend mode and
* by modulating the source colors with 0. Since the destination is all zeros, this
@@ -488,7 +490,8 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
*/
SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0);
mask_rect = tmp_rect;
retval = SDL_BlitSurface(src_rotated, NULL, surface, &mask_rect);
/* Renderer scaling, if needed */
retval = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode);
if (!retval) {
/* The last step gets the color values in place. The ADD blend mode simply adds them to
* the destination (where the color values are all zero). However, because the ADD blend
@@ -504,7 +507,8 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * tex
retval = -1;
} else {
SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD);
retval = SDL_BlitSurface(src_rotated_rgb, NULL, surface, &tmp_rect);
/* Renderer scaling, if needed */
retval = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode);
SDL_FreeSurface(src_rotated_rgb);
}
}
@@ -545,7 +549,7 @@ typedef struct 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,
const float *xy, int xy_stride, const SDL_Color *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)
{
@@ -823,7 +827,42 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
* to avoid potentially frequent RLE encoding/decoding.
*/
SDL_SetSurfaceRLE(surface, 0);
SDL_PrivateUpperBlitScaled(src, srcrect, surface, dstrect, texture->scaleMode);
/* Prevent to do scaling + clipping on viewport boundaries as it may lose proportion */
if (dstrect->x < 0 || dstrect->y < 0 || dstrect->x + dstrect->w > surface->w || dstrect->y + dstrect->h > surface->h) {
SDL_Surface *tmp = SDL_CreateRGBSurfaceWithFormat(0, dstrect->w, dstrect->h, 0, src->format->format);
/* Scale to an intermediate surface, then blit */
if (tmp) {
SDL_Rect r;
SDL_BlendMode blendmode;
Uint8 alphaMod, rMod, gMod, bMod;
SDL_GetSurfaceBlendMode(src, &blendmode);
SDL_GetSurfaceAlphaMod(src, &alphaMod);
SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod);
r.x = 0;
r.y = 0;
r.w = dstrect->w;
r.h = dstrect->h;
SDL_SetSurfaceBlendMode(src, SDL_BLENDMODE_NONE);
SDL_SetSurfaceColorMod(src, 255, 255, 255);
SDL_SetSurfaceAlphaMod(src, 255);
SDL_PrivateUpperBlitScaled(src, srcrect, tmp, &r, texture->scaleMode);
SDL_SetSurfaceColorMod(tmp, rMod, gMod, bMod);
SDL_SetSurfaceAlphaMod(tmp, alphaMod);
SDL_SetSurfaceBlendMode(tmp, blendmode);
SDL_BlitSurface(tmp, NULL, surface, dstrect);
SDL_FreeSurface(tmp);
/* No need to set back r/g/b/a/blendmode to 'src' since it's done in PrepTextureForCopy() */
}
} else{
SDL_PrivateUpperBlitScaled(src, srcrect, surface, dstrect, texture->scaleMode);
}
}
break;
}
@@ -840,7 +879,8 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
}
SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, &copydata->srcrect,
&copydata->dstrect, copydata->angle, &copydata->center, copydata->flip);
&copydata->dstrect, copydata->angle, &copydata->center, copydata->flip,
copydata->scale_x, copydata->scale_y);
break;
}
@@ -977,7 +1017,7 @@ SW_CreateRendererForSurface(SDL_Surface * surface)
SW_RenderData *data;
if (!surface) {
SDL_SetError("Can't create renderer for NULL surface");
SDL_InvalidParamError("surface");
return NULL;
}

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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

@@ -61,11 +61,6 @@ typedef struct tColorY {
Uint8 y;
} tColorY;
/* !
\brief Returns maximum of two numbers a and b.
*/
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
/* !
\brief Number of guard rows added to destination surfaces.
@@ -82,7 +77,7 @@ to a situation where the program can segfault.
\brief Returns colorkey info for a surface
*/
static Uint32
_colorkey(SDL_Surface *src)
get_colorkey(SDL_Surface *src)
{
Uint32 key = 0;
if (SDL_HasColorKey(src)) {
@@ -91,6 +86,18 @@ _colorkey(SDL_Surface *src)
return key;
}
/* rotate (sx, sy) by (angle, center) into (dx, dy) */
static void
rotate(double sx, double sy, double sinangle, double cosangle, const SDL_FPoint *center, double *dx, double *dy) {
sx -= center->x;
sy -= center->y;
*dx = cosangle * sx - sinangle * sy;
*dy = sinangle * sx + cosangle * sy;
*dx += center->x;
*dy += center->y;
}
/* !
\brief Internal target surface sizing function for rotations with trig result return.
@@ -105,49 +112,61 @@ _colorkey(SDL_Surface *src)
*/
void
SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle,
int *dstwidth, int *dstheight,
double *cangle, double *sangle)
SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle, const SDL_FPoint *center,
SDL_Rect *rect_dest, double *cangle, double *sangle)
{
/* The trig code below gets the wrong size (due to FP inaccuracy?) when angle is a multiple of 90 degrees */
int angle90 = (int)(angle/90);
if(angle90 == angle/90) { /* if the angle is a multiple of 90 degrees */
angle90 %= 4;
if(angle90 < 0) angle90 += 4; /* 0:0 deg, 1:90 deg, 2:180 deg, 3:270 deg */
if(angle90 & 1) {
*dstwidth = height;
*dstheight = width;
*cangle = 0;
*sangle = angle90 == 1 ? -1 : 1; /* reversed because our rotations are clockwise */
} else {
*dstwidth = width;
*dstheight = height;
*cangle = angle90 == 0 ? 1 : -1;
*sangle = 0;
}
} else {
double x, y, cx, cy, sx, sy;
double radangle;
int dstwidthhalf, dstheighthalf;
/*
* Determine destination width and height by rotating a centered source box
*/
radangle = angle * (M_PI / -180.0); /* reverse the angle because our rotations are clockwise */
*sangle = SDL_sin(radangle);
*cangle = SDL_cos(radangle);
x = (double)(width / 2);
y = (double)(height / 2);
cx = *cangle * x;
cy = *cangle * y;
sx = *sangle * x;
sy = *sangle * y;
int minx, maxx, miny, maxy;
double radangle;
double x0, x1, x2, x3;
double y0, y1, y2, y3;
double sinangle;
double cosangle;
dstwidthhalf = MAX((int)
SDL_ceil(MAX(MAX(MAX(SDL_fabs(cx + sy), SDL_fabs(cx - sy)), SDL_fabs(-cx + sy)), SDL_fabs(-cx - sy))), 1);
dstheighthalf = MAX((int)
SDL_ceil(MAX(MAX(MAX(SDL_fabs(sx + cy), SDL_fabs(sx - cy)), SDL_fabs(-sx + cy)), SDL_fabs(-sx - cy))), 1);
*dstwidth = 2 * dstwidthhalf;
*dstheight = 2 * dstheighthalf;
radangle = angle * (M_PI / 180.0);
sinangle = SDL_sin(radangle);
cosangle = SDL_cos(radangle);
/*
* Determine destination width and height by rotating a source box, at pixel center
*/
rotate(0.5, 0.5, sinangle, cosangle, center, &x0, &y0);
rotate(width - 0.5, 0.5, sinangle, cosangle, center, &x1, &y1);
rotate(0.5, height - 0.5, sinangle, cosangle, center, &x2, &y2);
rotate(width - 0.5, height - 0.5, sinangle, cosangle, center, &x3, &y3);
minx = (int)SDL_floor( SDL_min( SDL_min(x0, x1), SDL_min(x2, x3) ) );
maxx = (int)SDL_ceil( SDL_max( SDL_max(x0, x1), SDL_max(x2, x3) ) );
miny = (int)SDL_floor( SDL_min( SDL_min(y0, y1), SDL_min(y2, y3) ) );
maxy = (int)SDL_ceil( SDL_max( SDL_max(y0, y1), SDL_max(y2, y3) ) );
rect_dest->w = maxx - minx;
rect_dest->h = maxy - miny;
rect_dest->x = minx;
rect_dest->y = miny;
/* reverse the angle because our rotations are clockwise */
*sangle = -sinangle;
*cangle = cosangle;
{
/* The trig code below gets the wrong size (due to FP inaccuracy?) when angle is a multiple of 90 degrees */
int angle90 = (int)(angle/90);
if(angle90 == angle/90) { /* if the angle is a multiple of 90 degrees */
angle90 %= 4;
if(angle90 < 0) angle90 += 4; /* 0:0 deg, 1:90 deg, 2:180 deg, 3:270 deg */
if(angle90 & 1) {
rect_dest->w = height;
rect_dest->h = width;
*cangle = 0;
*sangle = angle90 == 1 ? -1 : 1; /* reversed because our rotations are clockwise */
} else {
rect_dest->w = width;
rect_dest->h = height;
*cangle = angle90 == 0 ? 1 : -1;
*sangle = 0;
}
}
}
}
@@ -220,48 +239,56 @@ Assumes dst surface was allocated with the correct dimensions.
\param src Source surface.
\param dst Destination surface.
\param cx Horizontal center coordinate.
\param cy Vertical center coordinate.
\param isin Integer version of sine of angle.
\param icos Integer version of cosine of angle.
\param flipx Flag indicating horizontal mirroring should be applied.
\param flipy Flag indicating vertical mirroring should be applied.
\param smooth Flag indicating anti-aliasing should be used.
\param dst_rect destination coordinates
\param center true center.
*/
static void
_transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int isin, int icos,
int flipx, int flipy, int smooth,
const SDL_Rect *rect_dest,
const SDL_FPoint *center)
{
int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
int sw, sh;
int cx, cy;
tColorRGBA c00, c01, c10, c11, cswap;
tColorRGBA *pc, *sp;
int gap;
const int fp_half = (1<<15);
/*
* Variable setup
*/
xd = ((src->w - dst->w) << 15);
yd = ((src->h - dst->h) << 15);
ax = (cx << 16) - (icos * cx);
ay = (cy << 16) - (isin * cx);
sw = src->w - 1;
sh = src->h - 1;
pc = (tColorRGBA*) dst->pixels;
gap = dst->pitch - dst->w * 4;
cx = (int)(center->x * 65536.0);
cy = (int)(center->y * 65536.0);
/*
* Switch between interpolating and non-interpolating code
*/
if (smooth) {
int y;
for (y = 0; y < dst->h; y++) {
dy = cy - y;
sdx = (ax + (isin * dy)) + xd;
sdy = (ay - (icos * dy)) + yd;
int x;
double src_x = (rect_dest->x + 0 + 0.5 - center->x);
double src_y = (rect_dest->y + y + 0.5 - center->y);
int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half);
int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half);
for (x = 0; x < dst->w; x++) {
dx = (sdx >> 16);
dy = (sdy >> 16);
int dx = (sdx >> 16);
int dy = (sdy >> 16);
if (flipx) dx = sw - dx;
if (flipy) dy = sh - dy;
if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
int ex, ey;
int t1, t2;
sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy) + dx;
c00 = *sp;
sp += 1;
@@ -303,13 +330,16 @@ _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int
pc = (tColorRGBA *) ((Uint8 *) pc + gap);
}
} else {
int y;
for (y = 0; y < dst->h; y++) {
dy = cy - y;
sdx = (ax + (isin * dy)) + xd;
sdy = (ay - (icos * dy)) + yd;
int x;
double src_x = (rect_dest->x + 0 + 0.5 - center->x);
double src_y = (rect_dest->y + y + 0.5 - center->y);
int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half);
int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half);
for (x = 0; x < dst->w; x++) {
dx = (sdx >> 16);
dy = (sdy >> 16);
int dx = (sdx >> 16);
int dy = (sdy >> 16);
if ((unsigned)dx < (unsigned)src->w && (unsigned)dy < (unsigned)src->h) {
if(flipx) dx = sw - dx;
if(flipy) dy = sh - dy;
@@ -335,46 +365,54 @@ Assumes dst surface was allocated with the correct dimensions.
\param src Source surface.
\param dst Destination surface.
\param cx Horizontal center coordinate.
\param cy Vertical center coordinate.
\param isin Integer version of sine of angle.
\param icos Integer version of cosine of angle.
\param flipx Flag indicating horizontal mirroring should be applied.
\param flipy Flag indicating vertical mirroring should be applied.
\param dst_rect destination coordinates
\param center true center.
*/
static void
transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int isin, int icos, int flipx, int flipy,
const SDL_Rect *rect_dest,
const SDL_FPoint *center)
{
int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay;
int sw, sh;
int cx, cy;
tColorY *pc;
int gap;
const int fp_half = (1<<15);
int y;
/*
* Variable setup
*/
xd = ((src->w - dst->w) << 15);
yd = ((src->h - dst->h) << 15);
ax = (cx << 16) - (icos * cx);
ay = (cy << 16) - (isin * cx);
sw = src->w - 1;
sh = src->h - 1;
pc = (tColorY*) dst->pixels;
gap = dst->pitch - dst->w;
cx = (int)(center->x * 65536.0);
cy = (int)(center->y * 65536.0);
/*
* Clear surface to colorkey
*/
SDL_memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h);
SDL_memset(pc, (int)(get_colorkey(src) & 0xff), dst->pitch * dst->h);
/*
* Iterate through destination surface
*/
for (y = 0; y < dst->h; y++) {
dy = cy - y;
sdx = (ax + (isin * dy)) + xd;
sdy = (ay - (icos * dy)) + yd;
int x;
double src_x = (rect_dest->x + 0 + 0.5 - center->x);
double src_y = (rect_dest->y + y + 0.5 - center->y);
int sdx = (int)((icos * src_x - isin * src_y) + cx - fp_half);
int sdy = (int)((isin * src_x + icos * src_y) + cy - fp_half);
for (x = 0; x < dst->w; x++) {
dx = (sdx >> 16);
dy = (sdy >> 16);
int dx = (sdx >> 16);
int dy = (sdy >> 16);
if ((unsigned)dx < (unsigned)src->w && (unsigned)dy < (unsigned)src->h) {
if (flipx) dx = (src->w-1)-dx;
if (flipy) dy = (src->h-1)-dy;
if (flipx) dx = sw - dx;
if (flipy) dy = sh- dy;
*pc = *((tColorY *)src->pixels + src->pitch * dy + dx);
}
sdx += icos;
@@ -390,7 +428,7 @@ transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin
\brief Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing.
Rotates a 32-bit or 8-bit 'src' surface to newly created 'dst' surface.
'angle' is the rotation in degrees, 'centerx' and 'centery' the rotation center. If 'smooth' is set
'angle' is the rotation in degrees, 'center' the rotation center. If 'smooth' is set
then the destination 32-bit surface is anti-aliased. 8-bit surfaces must have a colorkey. 32-bit
surfaces must have a 8888 layout with red, green, blue and alpha masks (any ordering goes).
The blend mode of the 'src' surface has some effects on generation of the 'dst' surface: The NONE
@@ -400,21 +438,21 @@ When using the NONE and MOD modes, color and alpha modulation must be applied be
\param src The surface to rotozoom.
\param angle The angle to rotate in degrees.
\param centerx The horizontal coordinate of the center of rotation
\param zoomy The vertical coordinate of the center of rotation
\param smooth Antialiasing flag; set to SMOOTHING_ON to enable.
\param flipx Set to 1 to flip the image horizontally
\param flipy Set to 1 to flip the image vertically
\param dstwidth The destination surface width
\param dstheight The destination surface height
\param rect_dest The destination rect bounding box
\param cangle The angle cosine
\param sangle The angle sine
\param center The true coordinate of the center of rotation
\return The new rotated surface.
*/
SDL_Surface *
SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery, int smooth, int flipx, int flipy, int dstwidth, int dstheight, double cangle, double sangle)
SDLgfx_rotateSurface(SDL_Surface * src, double angle, int smooth, int flipx, int flipy,
const SDL_Rect *rect_dest, double cangle, double sangle, const SDL_FPoint *center)
{
SDL_Surface *rz_dst;
int is8bit, angle90;
@@ -433,7 +471,6 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
colorKeyAvailable = SDL_TRUE;
}
}
/* This function requires a 32-bit surface or 8-bit surface with a colorkey */
is8bit = src->format->BitsPerPixel == 8 && colorKeyAvailable;
if (!(is8bit || (src->format->BitsPerPixel == 32 && src->format->Amask)))
@@ -447,16 +484,18 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
rz_dst = NULL;
if (is8bit) {
/* Target surface is 8 bit */
rz_dst = SDL_CreateRGBSurface(0, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
rz_dst = SDL_CreateRGBSurfaceWithFormat(0, rect_dest->w, rect_dest->h + GUARD_ROWS, 8, src->format->format);
if (rz_dst != NULL) {
for (i = 0; i < src->format->palette->ncolors; i++) {
rz_dst->format->palette->colors[i] = src->format->palette->colors[i];
if (src->format->palette) {
for (i = 0; i < src->format->palette->ncolors; i++) {
rz_dst->format->palette->colors[i] = src->format->palette->colors[i];
}
rz_dst->format->palette->ncolors = src->format->palette->ncolors;
}
rz_dst->format->palette->ncolors = src->format->palette->ncolors;
}
} else {
/* Target surface is 32 bit with source RGBA ordering */
rz_dst = SDL_CreateRGBSurface(0, dstwidth, dstheight + GUARD_ROWS, 32,
rz_dst = SDL_CreateRGBSurface(0, rect_dest->w, rect_dest->h + GUARD_ROWS, 32,
src->format->Rmask, src->format->Gmask,
src->format->Bmask, src->format->Amask);
}
@@ -466,7 +505,7 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
return NULL;
/* Adjust for guard rows */
rz_dst->h = dstheight;
rz_dst->h = rect_dest->h;
SDL_GetSurfaceBlendMode(src, &blendmode);
@@ -497,7 +536,7 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
}
/* check if the rotation is a multiple of 90 degrees so we can take a fast path and also somewhat reduce
* the off-by-one problem in _transformSurfaceRGBA that expresses itself when the rotation is near
* the off-by-one problem in transformSurfaceRGBA that expresses itself when the rotation is near
* multiples of 90 degrees.
*/
angle90 = (int)(angle/90);
@@ -513,16 +552,16 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
if(angle90 >= 0) {
transformSurfaceY90(src, rz_dst, angle90, flipx, flipy);
} else {
transformSurfaceY(src, rz_dst, centerx, centery, (int)sangleinv, (int)cangleinv,
flipx, flipy);
transformSurfaceY(src, rz_dst, (int)sangleinv, (int)cangleinv,
flipx, flipy, rect_dest, center);
}
} else {
/* Call the 32-bit transformation routine to do the rotation */
if (angle90 >= 0) {
transformSurfaceRGBA90(src, rz_dst, angle90, flipx, flipy);
} else {
_transformSurfaceRGBA(src, rz_dst, centerx, centery, (int)sangleinv, (int)cangleinv,
flipx, flipy, smooth);
transformSurfaceRGBA(src, rz_dst, (int)sangleinv, (int)cangleinv,
flipx, flipy, smooth, rect_dest, center);
}
}

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -22,11 +22,9 @@
#ifndef SDL_rotate_h_
#define SDL_rotate_h_
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
extern SDL_Surface *SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery, int smooth, int flipx, int flipy, int dstwidth, int dstheight, double cangle, double sangle);
extern void SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle, int *dstwidth, int *dstheight, double *cangle, double *sangle);
extern SDL_Surface *SDLgfx_rotateSurface(SDL_Surface * src, double angle, int smooth, int flipx, int flipy,
const SDL_Rect *rect_dest, double cangle, double sangle, const SDL_FPoint *center);
extern void SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle, const SDL_FPoint *center,
SDL_Rect *rect_dest, double *cangle, double *sangle);
#endif /* SDL_rotate_h_ */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -119,8 +119,8 @@ void trianglepoint_2_fixedpoint(SDL_Point *a) {
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)
/* bounding rect of three points (in fixed point) */
static void bounding_rect_fixedpoint(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));
@@ -133,6 +133,20 @@ static void bounding_rect(const SDL_Point *a, const SDL_Point *b, const SDL_Poin
r->h = (max_y - min_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));
r->x = min_x;
r->y = min_y;
r->w = (max_x - min_x);
r->h = (max_y - min_y);
}
/* Triangle rendering, using Barycentric coordinates (w0, w1, w2)
*
* The cross product isn't computed from scratch at each iteration,
@@ -232,7 +246,7 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin
}
}
bounding_rect(d0, d1, d2, &dstrect);
bounding_rect_fixedpoint(d0, d1, d2, &dstrect);
{
/* Clip triangle rect with surface rect */
@@ -438,7 +452,6 @@ int SDL_SW_BlitTriangle(
SDL_BlendMode blend;
SDL_Rect srcrect;
SDL_Rect dstrect;
SDL_Point s2_x_area;
@@ -495,11 +508,29 @@ int SDL_SW_BlitTriangle(
is_uniform = COLOR_EQ(c0, c1) && COLOR_EQ(c1, c2);
bounding_rect(s0, s1, s2, &srcrect);
bounding_rect(d0, d1, d2, &dstrect);
bounding_rect_fixedpoint(d0, d1, d2, &dstrect);
SDL_GetSurfaceBlendMode(src, &blend);
/* TRIANGLE_GET_TEXTCOORD interpolates up to the max values included, so reduce by 1 */
{
SDL_Rect srcrect;
int maxx, maxy;
bounding_rect(s0, s1, s2, &srcrect);
maxx = srcrect.x + srcrect.w;
maxy = srcrect.y + srcrect.h;
if (srcrect.w > 0) {
if (s0->x == maxx) s0->x--;
if (s1->x == maxx) s1->x--;
if (s2->x == maxx) s2->x--;
}
if (srcrect.h > 0) {
if (s0->y == maxy) s0->y--;
if (s1->y == maxy) s1->y--;
if (s2->y == maxy) s2->y--;
}
}
if (is_uniform) {
// SDL_GetSurfaceColorMod(src, &r, &g, &b);
has_modulation = c0.r != 255 || c0.g != 255 || c0.b != 255 || c0.a != 255;;
@@ -687,6 +718,21 @@ end:
}
#define FORMAT_ALPHA 0
#define FORMAT_NO_ALPHA -1
#define FORMAT_2101010 1
#define FORMAT_HAS_ALPHA(format) format == 0
#define FORMAT_HAS_NO_ALPHA(format) format < 0
static int SDL_INLINE detect_format(SDL_PixelFormat *pf) {
if (pf->format == SDL_PIXELFORMAT_ARGB2101010) {
return FORMAT_2101010;
} else if (pf->Amask) {
return FORMAT_ALPHA;
} else {
return FORMAT_NO_ALPHA;
}
}
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,
@@ -707,25 +753,32 @@ SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
SDL_PixelFormat *dst_fmt = info->dst_fmt;
int srcbpp = src_fmt->BytesPerPixel;
int dstbpp = dst_fmt->BytesPerPixel;
int srcfmt_val;
int dstfmt_val;
Uint32 rgbmask = ~src_fmt->Amask;
Uint32 ckey = info->colorkey & rgbmask;
Uint8 *dst_ptr = info->dst;
int dst_pitch = info->dst_pitch;;
srcfmt_val = detect_format(src_fmt);
dstfmt_val = detect_format(dst_fmt);
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);
if (FORMAT_HAS_ALPHA(srcfmt_val)) {
DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB, srcA);
} else if (FORMAT_HAS_NO_ALPHA(srcfmt_val)) {
DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB);
srcA = 0xFF;
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
srcpixel = *((Uint32 *)(src));
RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA);
}
if (flags & SDL_COPY_COLORKEY) {
/* srcpixel isn't set for 24 bpp */
@@ -737,13 +790,15 @@ SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
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);
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA);
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB);
dstA = 0xFF;
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
dstpixel = *((Uint32 *)(dst));
RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA);
}
if (! is_uniform) {
@@ -814,10 +869,15 @@ SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
dstA = 255;
break;
}
if (dst_fmt->Amask) {
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA);
} else {
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB);
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
Uint32 pixel;
ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA);
*(Uint32 *)dst = pixel;
}
}
TRIANGLE_END_LOOP

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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,6 +61,11 @@ static int VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * text
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch);
static int VITA_GXM_UpdateTextureNV(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect,
const Uint8 *Yplane, int Ypitch,
const Uint8 *UVplane, int UVpitch);
static int VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, void **pixels, int *pitch);
@@ -83,7 +88,7 @@ static int VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *c
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,
const float *xy, int xy_stride, const SDL_Color *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);
@@ -105,12 +110,16 @@ SDL_RenderDriver VITA_GXM_RenderDriver = {
.info = {
.name = "VITA gxm",
.flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
.num_texture_formats = 4,
.num_texture_formats = 8,
.texture_formats = {
[0] = SDL_PIXELFORMAT_ABGR8888,
[1] = SDL_PIXELFORMAT_ARGB8888,
[2] = SDL_PIXELFORMAT_RGB565,
[3] = SDL_PIXELFORMAT_BGR565
[3] = SDL_PIXELFORMAT_BGR565,
[4] = SDL_PIXELFORMAT_YV12,
[5] = SDL_PIXELFORMAT_IYUV,
[6] = SDL_PIXELFORMAT_NV12,
[7] = SDL_PIXELFORMAT_NV21,
},
.max_texture_width = 4096,
.max_texture_height = 4096,
@@ -133,6 +142,15 @@ PixelFormatToVITAFMT(Uint32 format)
return SCE_GXM_TEXTURE_FORMAT_U5U6U5_RGB;
case SDL_PIXELFORMAT_BGR565:
return SCE_GXM_TEXTURE_FORMAT_U5U6U5_BGR;
case SDL_PIXELFORMAT_YV12:
return SCE_GXM_TEXTURE_FORMAT_YVU420P3_CSC0;
case SDL_PIXELFORMAT_IYUV:
return SCE_GXM_TEXTURE_FORMAT_YUV420P3_CSC0;
// should be the other way around. looks like SCE bug.
case SDL_PIXELFORMAT_NV12:
return SCE_GXM_TEXTURE_FORMAT_YVU420P2_CSC0;
case SDL_PIXELFORMAT_NV21:
return SCE_GXM_TEXTURE_FORMAT_YUV420P2_CSC0;
default:
return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR;
}
@@ -217,7 +235,7 @@ VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
data = (VITA_GXM_RenderData *) SDL_calloc(1, sizeof(VITA_GXM_RenderData));
if (!data) {
VITA_GXM_DestroyRenderer(renderer);
SDL_free(renderer);
SDL_OutOfMemory();
return NULL;
}
@@ -226,7 +244,10 @@ VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->SupportsBlendMode = VITA_GXM_SupportsBlendMode;
renderer->CreateTexture = VITA_GXM_CreateTexture;
renderer->UpdateTexture = VITA_GXM_UpdateTexture;
#if SDL_HAVE_YUV
renderer->UpdateTextureYUV = VITA_GXM_UpdateTextureYUV;
renderer->UpdateTextureNV = VITA_GXM_UpdateTextureNV;
#endif
renderer->LockTexture = VITA_GXM_LockTexture;
renderer->UnlockTexture = VITA_GXM_UnlockTexture;
renderer->SetTextureScaleMode = VITA_GXM_SetTextureScaleMode;
@@ -293,7 +314,17 @@ VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
return SDL_OutOfMemory();
}
vita_texture->tex = create_gxm_texture(data, texture->w, texture->h, PixelFormatToVITAFMT(texture->format), (texture->access == SDL_TEXTUREACCESS_TARGET));
vita_texture->tex = create_gxm_texture(
data,
texture->w,
texture->h,
PixelFormatToVITAFMT(texture->format),
(texture->access == SDL_TEXTUREACCESS_TARGET),
&(vita_texture->w),
&(vita_texture->h),
&(vita_texture->pitch),
&(vita_texture->wscale)
);
if (!vita_texture->tex) {
SDL_free(vita_texture);
@@ -304,38 +335,129 @@ VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
VITA_GXM_SetTextureScaleMode(renderer, texture, texture->scaleMode);
vita_texture->w = gxm_texture_get_width(vita_texture->tex);
vita_texture->h = gxm_texture_get_height(vita_texture->tex);
vita_texture->pitch = gxm_texture_get_stride(vita_texture->tex);
#if SDL_HAVE_YUV
vita_texture->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
vita_texture->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
#endif
return 0;
}
static void VITA_GXM_SetYUVProfile(SDL_Renderer * renderer, SDL_Texture *texture)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
int ret = 0;
switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
case SDL_YUV_CONVERSION_BT601:
ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_STANDARD);
break;
case SDL_YUV_CONVERSION_BT709:
ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_STANDARD);
break;
case SDL_YUV_CONVERSION_JPEG:
default:
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Unsupported YUV profile: %d\n", SDL_GetYUVConversionModeForResolution(texture->w, texture->h));
break;
}
if (ret < 0) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Setting YUV profile failed: %x\n", ret);
}
}
static int
VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, const void *pixels, int pitch)
{
const Uint8 *src;
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
Uint8 *dst;
int row, length,dpitch;
src = pixels;
int row, length, dpitch;
#if SDL_HAVE_YUV
if (vita_texture->yuv || vita_texture->nv12) {
VITA_GXM_SetYUVProfile(renderer, texture);
}
#endif
VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch);
length = rect->w * SDL_BYTESPERPIXEL(texture->format);
if (length == pitch && length == dpitch) {
SDL_memcpy(dst, src, length*rect->h);
SDL_memcpy(dst, pixels, length*rect->h);
} else {
for (row = 0; row < rect->h; ++row) {
SDL_memcpy(dst, src, length);
src += pitch;
SDL_memcpy(dst, pixels, length);
pixels += pitch;
dst += dpitch;
}
}
#if SDL_HAVE_YUV
if (vita_texture->yuv) {
void *Udst;
void *Vdst;
int uv_pitch = (dpitch+1) / 2;
int uv_src_pitch = (pitch+1) / 2;
SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2};
// skip Y plane
Uint8 *Dpixels = gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h);
Udst = Dpixels + (UVrect.y * uv_pitch) + UVrect.x;
Vdst = Dpixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x;
length = UVrect.w;
// U plane
if (length == uv_src_pitch && length == uv_pitch) {
SDL_memcpy(Udst, pixels, length*UVrect.h);
} else {
for (row = 0; row < UVrect.h; ++row) {
SDL_memcpy(Udst, pixels, length);
pixels += uv_src_pitch;
Udst += uv_pitch;
}
}
// V plane
if (length == uv_src_pitch && length == uv_pitch) {
SDL_memcpy(Vdst, pixels, length*UVrect.h);
} else {
for (row = 0; row < UVrect.h; ++row) {
SDL_memcpy(Vdst, pixels, length);
pixels += uv_src_pitch;
Vdst += uv_pitch;
}
}
} else if (vita_texture->nv12) {
void *UVdst;
int uv_pitch = 2 * ((dpitch+1) / 2);
int uv_src_pitch = 2 * ((pitch+1) / 2);
SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2 , (rect->h + 1) / 2};
// skip Y plane
void *Dpixels = (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h));
UVdst = Dpixels + (UVrect.y * uv_pitch) + UVrect.x;
length = UVrect.w*2;
// UV plane
if (length == uv_src_pitch && length == uv_pitch) {
SDL_memcpy(UVdst, pixels, length*UVrect.h);
} else {
for (row = 0; row < UVrect.h; ++row) {
SDL_memcpy(UVdst, pixels, length);
pixels += uv_src_pitch;
UVdst += uv_pitch;
}
}
}
#endif
return 0;
}
#if SDL_HAVE_YUV
static int
VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect,
@@ -343,9 +465,133 @@ VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch)
{
Uint8 *dst;
int row, length, dpitch;
SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2};
VITA_GXM_SetYUVProfile(renderer, texture);
// copy Y plane
// obtain pixels via locking so that texture is flushed
VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch);
length = rect->w;
if (length == Ypitch && length == dpitch) {
SDL_memcpy(dst, Yplane, length*rect->h);
} else {
for (row = 0; row < rect->h; ++row) {
SDL_memcpy(dst, Yplane, length);
Yplane += Ypitch;
dst += dpitch;
}
}
// U/V planes
{
void *Udst;
void *Vdst;
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
int uv_pitch = (dpitch+1) / 2;
// skip Y plane
void *pixels = (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h));
if (texture->format == SDL_PIXELFORMAT_YV12) { // YVU
Vdst = pixels + (UVrect.y * uv_pitch) + UVrect.x;
Udst = pixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x;
} else { // YUV
Udst = pixels + (UVrect.y * uv_pitch) + UVrect.x;
Vdst = pixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x;
}
length = UVrect.w;
// U plane
if (length == Upitch && length == uv_pitch) {
SDL_memcpy(Udst, Uplane, length*UVrect.h);
} else {
for (row = 0; row < UVrect.h; ++row) {
SDL_memcpy(Udst, Uplane, length);
Uplane += Upitch;
Udst += uv_pitch;
}
}
// V plane
if (length == Vpitch && length == uv_pitch) {
SDL_memcpy(Vdst, Vplane, length*UVrect.h);
} else {
for (row = 0; row < UVrect.h; ++row) {
SDL_memcpy(Vdst, Vplane, length);
Vplane += Vpitch;
Vdst += uv_pitch;
}
}
}
return 0;
}
static int
VITA_GXM_UpdateTextureNV(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect,
const Uint8 *Yplane, int Ypitch,
const Uint8 *UVplane, int UVpitch)
{
Uint8 *dst;
int row, length, dpitch;
SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2};
VITA_GXM_SetYUVProfile(renderer, texture);
// copy Y plane
VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch);
length = rect->w * SDL_BYTESPERPIXEL(texture->format);
if (length == Ypitch && length == dpitch) {
SDL_memcpy(dst, Yplane, length*rect->h);
} else {
for (row = 0; row < rect->h; ++row) {
SDL_memcpy(dst, Yplane, length);
Yplane += Ypitch;
dst += dpitch;
}
}
// UV plane
{
void *UVdst;
VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
int uv_pitch = 2 * ((dpitch+1) / 2);
// skip Y plane
void *pixels = (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h));
UVdst = pixels + (UVrect.y * uv_pitch) + UVrect.x;
length = UVrect.w * 2;
// UV plane
if (length == UVpitch && length == uv_pitch) {
SDL_memcpy(UVdst, UVplane, length*UVrect.h);
} else {
for (row = 0; row < UVrect.h; ++row) {
SDL_memcpy(UVdst, UVplane, length);
UVplane += UVpitch;
UVdst += uv_pitch;
}
}
}
return 0;
}
#endif
static int
VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, void **pixels, int *pitch)
@@ -442,11 +688,10 @@ VITA_GXM_QueueSetDrawColor(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
const Uint8 r = cmd->data.color.r;
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
data->drawstate.color = (((Uint32)a << 24) | (b << 16) | (g << 8) | r);
data->drawstate.color.r = cmd->data.color.r;
data->drawstate.color.g = cmd->data.color.g;
data->drawstate.color.b = cmd->data.color.b;
data->drawstate.color.a = cmd->data.color.a;
return 0;
}
@@ -456,7 +701,7 @@ VITA_GXM_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
int color = data->drawstate.color;
SDL_Color color = data->drawstate.color;
color_vertex *vertex = (color_vertex *)pool_malloc(
data,
@@ -480,7 +725,7 @@ static int
VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
int color = data->drawstate.color;
SDL_Color color = data->drawstate.color;
color_vertex *vertex = (color_vertex *)pool_malloc(
data,
@@ -506,7 +751,7 @@ VITA_GXM_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const S
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,
const float *xy, int xy_stride, const SDL_Color *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)
{
@@ -518,6 +763,7 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
size_indices = indices ? size_indices : 0;
if (texture) {
VITA_GXM_TextureData* vita_texture = (VITA_GXM_TextureData*) texture->driverdata;
texture_vertex *vertices;
vertices = (texture_vertex *)pool_malloc(
@@ -533,7 +779,7 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
int j;
float *xy_;
float *uv_;
int col_;
SDL_Color col_;
if (size_indices == 4) {
j = ((const Uint32 *)indices)[i];
} else if (size_indices == 2) {
@@ -545,12 +791,12 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
}
xy_ = (float *)((char*)xy + j * xy_stride);
col_ = *(int *)((char*)color + j * color_stride);
col_ = *(SDL_Color *)((char*)color + j * color_stride);
uv_ = (float *)((char*)uv + j * uv_stride);
vertices[i].x = xy_[0] * scale_x;
vertices[i].y = xy_[1] * scale_y;
vertices[i].u = uv_[0];
vertices[i].u = uv_[0] * vita_texture->wscale;
vertices[i].v = uv_[1];
vertices[i].color = col_;
}
@@ -572,7 +818,7 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
for (i = 0; i < count; i++) {
int j;
float *xy_;
int col_;
SDL_Color col_;
if (size_indices == 4) {
j = ((const Uint32 *)indices)[i];
} else if (size_indices == 2) {
@@ -584,7 +830,7 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
}
xy_ = (float *)((char*)xy + j * xy_stride);
col_ = *(int *)((char*)color + j * color_stride);
col_ = *(SDL_Color *)((char*)color + j * color_stride);
vertices[i].x = xy_[0] * scale_x;
vertices[i].y = xy_[1] * scale_y;
@@ -729,14 +975,6 @@ SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
return 0;
}
static int
SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
{
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
return SetDrawState(data, cmd);
}
static int
VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
@@ -818,16 +1056,12 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
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;
count += nextcmd->data.draw.count;
}
nextcmd = nextcmd->next;
}
if (thistexture) {
ret = SetCopyState(renderer, cmd);
} else {
ret = SetDrawState(data, cmd);
}
ret = SetDrawState(data, cmd);
if (ret == 0) {
int op = SCE_GXM_PRIMITIVE_TRIANGLES;
@@ -1012,7 +1246,7 @@ VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
sceGxmFinish(data->gxm_context);
free_gxm_texture(vita_texture->tex);
free_gxm_texture(data, vita_texture->tex);
SDL_free(vita_texture);

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -26,7 +26,7 @@
#include "SDL_render_vita_gxm_memory.h"
void *
mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid)
vita_mem_alloc(unsigned int type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid)
{
void *mem;
@@ -51,7 +51,7 @@ mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignm
}
void
mem_gpu_free(SceUID uid)
vita_mem_free(SceUID uid)
{
void *mem = NULL;
if (sceKernelGetMemBlockBase(uid, &mem) < 0)
@@ -61,7 +61,71 @@ mem_gpu_free(SceUID uid)
}
void *
mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size)
{
void *mem;
if (data->texturePool == NULL) {
int poolsize;
int ret;
SceKernelFreeMemorySizeInfo info;
info.size = sizeof(SceKernelFreeMemorySizeInfo);
sceKernelGetFreeMemorySize(&info);
poolsize = ALIGN(info.size_cdram, 256*1024);
if (poolsize > info.size_cdram) {
poolsize = ALIGN(info.size_cdram - 256*1024, 256*1024);
}
data->texturePoolUID = sceKernelAllocMemBlock("gpu_texture_pool", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, poolsize, NULL);
if (data->texturePoolUID < 0) {
return NULL;
}
ret = sceKernelGetMemBlockBase(data->texturePoolUID, &mem);
if ( ret < 0)
{
return NULL;
}
data->texturePool = sceClibMspaceCreate(mem, poolsize);
if (data->texturePool == NULL) {
return NULL;
}
ret = sceGxmMapMemory(mem, poolsize, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE);
if (ret < 0)
{
return NULL;
}
}
return sceClibMspaceMemalign(data->texturePool, SCE_GXM_TEXTURE_ALIGNMENT, size);
}
void
vita_gpu_mem_free(VITA_GXM_RenderData *data, void* ptr)
{
if (data->texturePool != NULL)
{
sceClibMspaceFree(data->texturePool, ptr);
}
}
void
vita_gpu_mem_destroy(VITA_GXM_RenderData *data)
{
void *mem = NULL;
if (data->texturePool != NULL)
{
sceClibMspaceDestroy(data->texturePool);
data->texturePool = NULL;
if (sceKernelGetMemBlockBase(data->texturePoolUID, &mem) < 0)
return;
sceGxmUnmapMemory(mem);
sceKernelFreeMemBlock(data->texturePoolUID);
}
}
void *
vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
{
void *mem = NULL;
@@ -77,7 +141,7 @@ mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
}
void
mem_vertex_usse_free(SceUID uid)
vita_mem_vertex_usse_free(SceUID uid)
{
void *mem = NULL;
if (sceKernelGetMemBlockBase(uid, &mem) < 0)
@@ -87,7 +151,7 @@ mem_vertex_usse_free(SceUID uid)
}
void *
mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
{
void *mem = NULL;
@@ -103,7 +167,7 @@ mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offse
}
void
mem_fragment_usse_free(SceUID uid)
vita_mem_fragment_usse_free(SceUID uid)
{
void *mem = NULL;
if (sceKernelGetMemBlockBase(uid, &mem) < 0)

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -25,15 +25,19 @@
#include <psp2/gxm.h>
#include <psp2/types.h>
#include <psp2/kernel/sysmem.h>
#include "SDL_render_vita_gxm_types.h"
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
void *mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid);
void mem_gpu_free(SceUID uid);
void *mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
void mem_vertex_usse_free(SceUID uid);
void *mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
void mem_fragment_usse_free(SceUID uid);
void *vita_mem_alloc(unsigned int type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid);
void vita_mem_free(SceUID uid);
void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size);
void vita_gpu_mem_free(VITA_GXM_RenderData *data, void* ptr);
void vita_gpu_mem_destroy(VITA_GXM_RenderData *data);
void *vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
void vita_mem_vertex_usse_free(SceUID uid);
void *vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
void vita_mem_fragment_usse_free(SceUID uid);
#endif /* SDL_RENDER_VITA_GXM_MEMORY_H */

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -117,6 +117,8 @@ tex_format_to_bytespp(SceGxmTextureFormat format)
case SCE_GXM_TEXTURE_BASE_FORMAT_U8:
case SCE_GXM_TEXTURE_BASE_FORMAT_S8:
case SCE_GXM_TEXTURE_BASE_FORMAT_P8:
case SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2: // YUV actually uses 12 bits per pixel. UV planes bits/mem are handled elsewhere
case SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3:
return 1;
case SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4:
case SCE_GXM_TEXTURE_BASE_FORMAT_U8U3U3U2:
@@ -216,19 +218,31 @@ 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].color = 0;
vertices[0].color.r = 0;
vertices[0].color.g = 0;
vertices[0].color.b = 0;
vertices[0].color.a = 0;
vertices[1].x = x + w;
vertices[1].y = y;
vertices[1].color = 0;
vertices[1].color.r = 0;
vertices[1].color.g = 0;
vertices[1].color.b = 0;
vertices[1].color.a = 0;
vertices[2].x = x;
vertices[2].y = y + h;
vertices[2].color = 0;
vertices[2].color.r = 0;
vertices[2].color.g = 0;
vertices[2].color.b = 0;
vertices[2].color.a = 0;
vertices[3].x = x + w;
vertices[3].y = y + h;
vertices[3].color = 0;
vertices[3].color.r = 0;
vertices[3].color.g = 0;
vertices[3].color.b = 0;
vertices[3].color.a = 0;
data->drawstate.fragment_program = data->colorFragmentProgram;
data->drawstate.vertex_program = data->colorVertexProgram;
@@ -402,28 +416,28 @@ gxm_init(SDL_Renderer *renderer)
}
// allocate ring buffer memory using default sizes
vdmRingBuffer = mem_gpu_alloc(
vdmRingBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE,
4,
SCE_GXM_MEMORY_ATTRIB_READ,
&data->vdmRingBufferUid);
vertexRingBuffer = mem_gpu_alloc(
vertexRingBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE,
4,
SCE_GXM_MEMORY_ATTRIB_READ,
&data->vertexRingBufferUid);
fragmentRingBuffer = mem_gpu_alloc(
fragmentRingBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE,
4,
SCE_GXM_MEMORY_ATTRIB_READ,
&data->fragmentRingBufferUid);
fragmentUsseRingBuffer = mem_fragment_usse_alloc(
fragmentUsseRingBuffer = vita_mem_fragment_usse_alloc(
SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE,
&data->fragmentUsseRingBufferUid,
&fragmentUsseRingBufferOffset);
@@ -468,7 +482,7 @@ gxm_init(SDL_Renderer *renderer)
for (i = 0; i < VITA_GXM_BUFFERS; i++) {
// allocate memory for display
data->displayBufferData[i] = mem_gpu_alloc(
data->displayBufferData[i] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
@@ -513,7 +527,7 @@ gxm_init(SDL_Renderer *renderer)
// allocate the depth buffer
data->depthBufferData = mem_gpu_alloc(
data->depthBufferData = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
4 * sampleCount,
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@@ -521,7 +535,7 @@ gxm_init(SDL_Renderer *renderer)
&data->depthBufferUid);
// allocate the stencil buffer
data->stencilBufferData = mem_gpu_alloc(
data->stencilBufferData = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
4 * sampleCount,
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@@ -553,19 +567,19 @@ gxm_init(SDL_Renderer *renderer)
// allocate memory for buffers and USSE code
patcherBuffer = mem_gpu_alloc(
patcherBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
patcherBufferSize,
4,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&data->patcherBufferUid);
patcherVertexUsse = mem_vertex_usse_alloc(
patcherVertexUsse = vita_mem_vertex_usse_alloc(
patcherVertexUsseSize,
&data->patcherVertexUsseUid,
&patcherVertexUsseOffset);
patcherFragmentUsse = mem_fragment_usse_alloc(
patcherFragmentUsse = vita_mem_fragment_usse_alloc(
patcherFragmentUsseSize,
&data->patcherFragmentUsseUid,
&patcherFragmentUsseOffset);
@@ -716,7 +730,7 @@ gxm_init(SDL_Renderer *renderer)
}
// create the clear triangle vertex/index data
data->clearVertices = (clear_vertex *)mem_gpu_alloc(
data->clearVertices = (clear_vertex *)vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
3*sizeof(clear_vertex),
4,
@@ -728,7 +742,7 @@ gxm_init(SDL_Renderer *renderer)
// Allocate a 64k * 2 bytes = 128 KiB buffer and store all possible
// 16-bit indices in linear ascending order, so we can use this for
// all drawing operations where we don't want to use indexing.
data->linearIndices = (uint16_t *)mem_gpu_alloc(
data->linearIndices = (uint16_t *)vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
UINT16_MAX*sizeof(uint16_t),
sizeof(uint16_t),
@@ -859,7 +873,7 @@ gxm_init(SDL_Renderer *renderer)
data->textureWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(textureVertexProgramGxp, "wvp");
// Allocate memory for the memory pool
data->pool_addr[0] = mem_gpu_alloc(
data->pool_addr[0] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW,
VITA_GXM_POOL_SIZE,
sizeof(void *),
@@ -867,7 +881,7 @@ gxm_init(SDL_Renderer *renderer)
&data->poolUid[0]
);
data->pool_addr[1] = mem_gpu_alloc(
data->pool_addr[1] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW,
VITA_GXM_POOL_SIZE,
sizeof(void *),
@@ -906,28 +920,28 @@ void gxm_finish(SDL_Renderer *renderer)
free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mod);
free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mul);
mem_gpu_free(data->linearIndicesUid);
mem_gpu_free(data->clearVerticesUid);
vita_mem_free(data->linearIndicesUid);
vita_mem_free(data->clearVerticesUid);
// wait until display queue is finished before deallocating display buffers
sceGxmDisplayQueueFinish();
// clean up display queue
mem_gpu_free(data->depthBufferUid);
vita_mem_free(data->depthBufferUid);
for (size_t i = 0; i < VITA_GXM_BUFFERS; i++)
{
// clear the buffer then deallocate
SDL_memset(data->displayBufferData[i], 0, VITA_GXM_SCREEN_HEIGHT * VITA_GXM_SCREEN_STRIDE * 4);
mem_gpu_free(data->displayBufferUid[i]);
vita_mem_free(data->displayBufferUid[i]);
// destroy the sync object
sceGxmSyncObjectDestroy(data->displayBufferSync[i]);
}
// Free the depth and stencil buffer
mem_gpu_free(data->depthBufferUid);
mem_gpu_free(data->stencilBufferUid);
vita_mem_free(data->depthBufferUid);
vita_mem_free(data->stencilBufferUid);
// unregister programs and destroy shader patcher
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->clearFragmentProgramId);
@@ -938,23 +952,24 @@ void gxm_finish(SDL_Renderer *renderer)
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureVertexProgramId);
sceGxmShaderPatcherDestroy(data->shaderPatcher);
mem_fragment_usse_free(data->patcherFragmentUsseUid);
mem_vertex_usse_free(data->patcherVertexUsseUid);
mem_gpu_free(data->patcherBufferUid);
vita_mem_fragment_usse_free(data->patcherFragmentUsseUid);
vita_mem_vertex_usse_free(data->patcherVertexUsseUid);
vita_mem_free(data->patcherBufferUid);
// destroy the render target
sceGxmDestroyRenderTarget(data->renderTarget);
// destroy the gxm context
sceGxmDestroyContext(data->gxm_context);
mem_fragment_usse_free(data->fragmentUsseRingBufferUid);
mem_gpu_free(data->fragmentRingBufferUid);
mem_gpu_free(data->vertexRingBufferUid);
mem_gpu_free(data->vdmRingBufferUid);
vita_mem_fragment_usse_free(data->fragmentUsseRingBufferUid);
vita_mem_free(data->fragmentRingBufferUid);
vita_mem_free(data->vertexRingBufferUid);
vita_mem_free(data->vdmRingBufferUid);
SDL_free(data->contextParams.hostMem);
mem_gpu_free(data->poolUid[0]);
mem_gpu_free(data->poolUid[1]);
vita_mem_free(data->poolUid[0]);
vita_mem_free(data->poolUid[1]);
vita_gpu_mem_destroy(data);
// terminate libgxm
sceGxmTerminate();
@@ -963,16 +978,20 @@ void gxm_finish(SDL_Renderer *renderer)
// textures
void
free_gxm_texture(gxm_texture *texture)
free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture)
{
if (texture) {
if (texture->gxm_rendertarget) {
sceGxmDestroyRenderTarget(texture->gxm_rendertarget);
}
if (texture->depth_UID) {
mem_gpu_free(texture->depth_UID);
vita_mem_free(texture->depth_UID);
}
if (texture->cdram) {
vita_gpu_mem_free(data, sceGxmTextureGetData(&texture->gxm_tex));
} else {
vita_mem_free(texture->data_UID);
}
mem_gpu_free(texture->data_UID);
SDL_free(texture);
}
}
@@ -983,25 +1002,6 @@ gxm_texture_get_format(const gxm_texture *texture)
return sceGxmTextureGetFormat(&texture->gxm_tex);
}
unsigned int
gxm_texture_get_width(const gxm_texture *texture)
{
return sceGxmTextureGetWidth(&texture->gxm_tex);
}
unsigned int
gxm_texture_get_height(const gxm_texture *texture)
{
return sceGxmTextureGetHeight(&texture->gxm_tex);
}
unsigned int
gxm_texture_get_stride(const gxm_texture *texture)
{
return ((gxm_texture_get_width(texture) + 7) & ~7)
* tex_format_to_bytespp(gxm_texture_get_format(texture));
}
void *
gxm_texture_get_datap(const gxm_texture *texture)
{
@@ -1009,34 +1009,53 @@ 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)
create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale)
{
gxm_texture *texture = SDL_calloc(1, sizeof(gxm_texture));
const int tex_size = ((w + 7) & ~ 7) * h * tex_format_to_bytespp(format);
int aligned_w = ALIGN(w, 8);
int texture_w = w;
int tex_size = aligned_w * h * tex_format_to_bytespp(format);
void *texture_data;
int ret;
*return_wscale = 1.0f;
// SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3/P2 based formats require width aligned to 16
if ( (format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3 || (format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2) {
aligned_w = ALIGN(w, 16);
texture_w = aligned_w;
tex_size = aligned_w * h * tex_format_to_bytespp(format);
*return_wscale = (float) (w) / texture_w;
// add storage for UV planes
tex_size += (((aligned_w + 1) / 2) * ((h + 1) / 2)) * 2;
}
if (!texture)
return NULL;
*return_w = w;
*return_h = h;
*return_pitch = aligned_w * tex_format_to_bytespp(format);
/* Allocate a GPU buffer for the texture */
texture_data = mem_gpu_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
tex_size,
SCE_GXM_TEXTURE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&texture->data_UID
texture_data = vita_gpu_mem_alloc(
data,
tex_size
);
/* Try SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE in case we're out of VRAM */
if (!texture_data) {
SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "CDRAM texture allocation failed\n");
texture_data = mem_gpu_alloc(
texture_data = vita_mem_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
);
texture->cdram = 0;
} else {
texture->cdram = 1;
}
if (!texture_data) {
@@ -1048,7 +1067,12 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
SDL_memset(texture_data, 0, tex_size);
/* Create the gxm texture */
sceGxmTextureInitLinear( &texture->gxm_tex, texture_data, format, w, h, 0);
ret = sceGxmTextureInitLinear( &texture->gxm_tex, texture_data, format, texture_w, h, 0);
if (ret < 0) {
free_gxm_texture(data, texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "texture init failed: %x\n", ret);
return NULL;
}
if (isRenderTarget) {
void *depthBufferData;
@@ -1071,13 +1095,13 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
);
if (err < 0) {
free_gxm_texture(texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %d\n", err);
free_gxm_texture(data, texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %x\n", err);
return NULL;
}
// allocate it
depthBufferData = mem_gpu_alloc(
depthBufferData = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
4*sampleCount,
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@@ -1094,8 +1118,8 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
NULL);
if (err < 0) {
free_gxm_texture(texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %d\n", err);
free_gxm_texture(data, texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %x\n", err);
return NULL;
}
@@ -1119,8 +1143,8 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
texture->gxm_rendertarget = tgt;
if (err < 0) {
free_gxm_texture(texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %d\n", err);
free_gxm_texture(data, texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %x\n", err);
return NULL;
}
}
@@ -1169,7 +1193,7 @@ void gxm_init_for_common_dialog(void)
for (int i = 0; i < VITA_GXM_BUFFERS; i += 1)
{
buffer_for_common_dialog[i].displayData.wait_vblank = SDL_TRUE;
buffer_for_common_dialog[i].displayData.address = mem_gpu_alloc(
buffer_for_common_dialog[i].displayData.address = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
@@ -1217,7 +1241,7 @@ void gxm_term_for_common_dialog(void)
sceGxmDisplayQueueFinish();
for (int i = 0; i < VITA_GXM_BUFFERS; i += 1)
{
mem_gpu_free(buffer_for_common_dialog[i].uid);
vita_mem_free(buffer_for_common_dialog[i].uid);
sceGxmSyncObjectDestroy(buffer_for_common_dialog[i].sync);
}
}

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -48,15 +48,12 @@ void unset_clip_rectangle(VITA_GXM_RenderData *data);
int gxm_init(SDL_Renderer *renderer);
void gxm_finish(SDL_Renderer *renderer);
gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget);
void free_gxm_texture(gxm_texture *texture);
gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale);
void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture);
void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter);
SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture);
unsigned int gxm_texture_get_width(const gxm_texture *texture);
unsigned int gxm_texture_get_height(const gxm_texture *texture);
unsigned int gxm_texture_get_stride(const gxm_texture *texture);
void *gxm_texture_get_datap(const gxm_texture *texture);
void gxm_minimal_init_for_common_dialog(void);

View File

@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2022 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
@@ -33,6 +33,7 @@
#include <psp2/gxm.h>
#include <psp2/types.h>
#include <psp2/kernel/sysmem.h>
#include <psp2/kernel/clib.h>
#include <string.h>
@@ -61,7 +62,7 @@ typedef struct clear_vertex {
typedef struct color_vertex {
float x;
float y;
unsigned int color;
SDL_Color color;
} color_vertex;
typedef struct texture_vertex {
@@ -69,7 +70,7 @@ typedef struct texture_vertex {
float y;
float u;
float v;
unsigned int color;
SDL_Color color;
} texture_vertex;
typedef struct gxm_texture {
@@ -79,6 +80,7 @@ typedef struct gxm_texture {
SceGxmColorSurface gxm_colorsurface;
SceGxmDepthStencilSurface gxm_depthstencil;
SceUID depth_UID;
SDL_bool cdram;
} gxm_texture;
typedef struct fragment_programs {
@@ -100,7 +102,7 @@ typedef struct
SDL_bool viewport_dirty;
SDL_Texture *texture;
SDL_Texture *target;
Uint32 color;
SDL_Color color;
SceGxmFragmentProgram *fragment_program;
SceGxmVertexProgram *vertex_program;
int last_command;
@@ -110,7 +112,7 @@ typedef struct
SDL_bool cliprect_dirty;
SDL_Rect cliprect;
SDL_bool texturing;
Uint32 clear_color;
SDL_Color clear_color;
int drawablew;
int drawableh;
} gxm_drawstate_cache;
@@ -186,14 +188,19 @@ typedef struct
blend_fragment_programs blendFragmentPrograms;
gxm_drawstate_cache drawstate;
SceClibMspace texturePool;
SceUID texturePoolUID;
} VITA_GXM_RenderData;
typedef struct
{
gxm_texture *tex;
unsigned int pitch;
unsigned int w;
unsigned int h;
unsigned int pitch;
unsigned int w;
unsigned int h;
float wscale;
SDL_bool yuv;
SDL_bool nv12;
} VITA_GXM_TextureData;
#endif /* SDL_RENDER_VITA_GXM_TYPES_H */