update sdl to release 2.0.22

This commit is contained in:
AzaezelX 2022-04-26 09:17:21 -05:00
parent 3f796d2a06
commit d4307ea413
135 changed files with 5746 additions and 1161 deletions

View file

@ -356,7 +356,7 @@ QueueCmdSetViewport(SDL_Renderer *renderer)
if (cmd != NULL) {
cmd->command = SDL_RENDERCMD_SETVIEWPORT;
cmd->data.viewport.first = 0; /* render backend will fill this in. */
/* Convert SDL_FRect to SDL_Rect */
/* Convert SDL_DRect to SDL_Rect */
cmd->data.viewport.rect.x = (int)SDL_floor(renderer->viewport.x);
cmd->data.viewport.rect.y = (int)SDL_floor(renderer->viewport.y);
cmd->data.viewport.rect.w = (int)SDL_floor(renderer->viewport.w);
@ -386,7 +386,7 @@ QueueCmdSetClipRect(SDL_Renderer *renderer)
} else {
cmd->command = SDL_RENDERCMD_SETCLIPRECT;
cmd->data.cliprect.enabled = renderer->clipping_enabled;
/* Convert SDL_FRect to SDL_Rect */
/* Convert SDL_DRect to SDL_Rect */
cmd->data.cliprect.rect.x = (int)SDL_floor(renderer->clip_rect.x);
cmd->data.cliprect.rect.y = (int)SDL_floor(renderer->clip_rect.y);
cmd->data.cliprect.rect.w = (int)SDL_floor(renderer->clip_rect.w);
@ -580,10 +580,10 @@ QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect * rects, const int cou
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
}
SDL_small_free(xy, isstack1);
SDL_small_free(indices, isstack2);
}
SDL_small_free(xy, isstack1);
SDL_small_free(indices, isstack2);
} else {
retval = renderer->QueueFillRects(renderer, cmd, rects, count);
if (retval < 0) {
@ -676,7 +676,7 @@ SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info)
#endif
}
static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_FRect *viewport, SDL_FPoint *scale)
static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_DRect *viewport, SDL_FPoint *scale)
{
SDL_LockMutex(renderer->target_mutex);
*logical_w = renderer->target ? renderer->logical_w_backup : renderer->logical_w;
@ -698,7 +698,17 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
renderer->WindowEvent(renderer, &event->window);
}
if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
/* In addition to size changes, we also want to do this block for
* moves as well, for two reasons:
*
* 1. The window could be moved to a new display, which has a new
* DPI and therefore a new window/drawable ratio
* 2. For whatever reason, the viewport can get messed up during
* window movement (this has been observed on macOS), so this is
* also a good opportunity to force viewport updates
*/
if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED ||
event->window.event == SDL_WINDOWEVENT_MOVED) {
/* Make sure we're operating on the default render target */
SDL_Texture *saved_target = SDL_GetRenderTarget(renderer);
if (saved_target) {
@ -728,10 +738,10 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
SDL_GetWindowSize(renderer->window, &w, &h);
}
renderer->viewport.x = 0;
renderer->viewport.y = 0;
renderer->viewport.w = (float) w;
renderer->viewport.h = (float) h;
renderer->viewport.x = (double)0;
renderer->viewport.y = (double)0;
renderer->viewport.w = (double)w;
renderer->viewport.h = (double)h;
QueueCmdSetViewport(renderer);
FlushRenderCommandsIfNotBatching(renderer);
}
@ -758,7 +768,7 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
SDL_Window *window = SDL_GetWindowFromID(event->motion.windowID);
if (window == renderer->window) {
int logical_w, logical_h;
SDL_FRect viewport;
SDL_DRect viewport;
SDL_FPoint scale;
GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
if (logical_w) {
@ -785,7 +795,7 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
SDL_Window *window = SDL_GetWindowFromID(event->button.windowID);
if (window == renderer->window) {
int logical_w, logical_h;
SDL_FRect viewport;
SDL_DRect viewport;
SDL_FPoint scale;
GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
if (logical_w) {
@ -800,7 +810,7 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
event->type == SDL_FINGERMOTION) {
int logical_w, logical_h;
float physical_w, physical_h;
SDL_FRect viewport;
SDL_DRect viewport;
SDL_FPoint scale;
GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
@ -1095,6 +1105,13 @@ SDL_GetRenderer(SDL_Window * window)
return (SDL_Renderer *)SDL_GetWindowData(window, SDL_WINDOWRENDERDATA);
}
SDL_Window *
SDL_RenderGetWindow(SDL_Renderer *renderer)
{
CHECK_RENDERER_MAGIC(renderer, NULL);
return renderer->window;
}
int
SDL_GetRendererInfo(SDL_Renderer * renderer, SDL_RendererInfo * info)
{
@ -1585,10 +1602,11 @@ SDL_SetTextureScaleMode(SDL_Texture * texture, SDL_ScaleMode scaleMode)
CHECK_TEXTURE_MAGIC(texture, -1);
renderer = texture->renderer;
renderer->SetTextureScaleMode(renderer, texture, scaleMode);
texture->scaleMode = scaleMode;
if (texture->native) {
return SDL_SetTextureScaleMode(texture->native, scaleMode);
} else {
renderer->SetTextureScaleMode(renderer, texture, scaleMode);
}
return 0;
}
@ -2210,10 +2228,10 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
}
if (texture) {
renderer->viewport.x = 0.0f;
renderer->viewport.y = 0.0f;
renderer->viewport.w = (float) texture->w;
renderer->viewport.h = (float) texture->h;
renderer->viewport.x = (double)0;
renderer->viewport.y = (double)0;
renderer->viewport.w = (double)texture->w;
renderer->viewport.h = (double)texture->h;
SDL_zero(renderer->clip_rect);
renderer->clipping_enabled = SDL_FALSE;
renderer->scale.x = 1.0f;
@ -2245,6 +2263,8 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_Texture *
SDL_GetRenderTarget(SDL_Renderer *renderer)
{
CHECK_RENDERER_MAGIC(renderer, NULL);
return renderer->target;
}
@ -2420,19 +2440,19 @@ SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect)
CHECK_RENDERER_MAGIC(renderer, -1);
if (rect) {
renderer->viewport.x = rect->x * renderer->scale.x;
renderer->viewport.y = rect->y * renderer->scale.y;
renderer->viewport.w = rect->w * renderer->scale.x;
renderer->viewport.h = rect->h * renderer->scale.y;
renderer->viewport.x = (double)rect->x * renderer->scale.x;
renderer->viewport.y = (double)rect->y * renderer->scale.y;
renderer->viewport.w = (double)rect->w * renderer->scale.x;
renderer->viewport.h = (double)rect->h * renderer->scale.y;
} else {
int w, h;
if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
return -1;
}
renderer->viewport.x = 0.0f;
renderer->viewport.y = 0.0f;
renderer->viewport.w = (float) w;
renderer->viewport.h = (float) h;
renderer->viewport.x = (double)0;
renderer->viewport.y = (double)0;
renderer->viewport.w = (double)w;
renderer->viewport.h = (double)h;
}
retval = QueueCmdSetViewport(renderer);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
@ -2456,8 +2476,8 @@ RenderGetViewportSize(SDL_Renderer * renderer, SDL_FRect * rect)
{
rect->x = 0.0f;
rect->y = 0.0f;
rect->w = renderer->viewport.w / renderer->scale.x;
rect->h = renderer->viewport.h / renderer->scale.y;
rect->w = (float)(renderer->viewport.w / renderer->scale.x);
rect->h = (float)(renderer->viewport.h / renderer->scale.y);
}
int
@ -2468,10 +2488,10 @@ SDL_RenderSetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect)
if (rect) {
renderer->clipping_enabled = SDL_TRUE;
renderer->clip_rect.x = rect->x * renderer->scale.x;
renderer->clip_rect.y = rect->y * renderer->scale.y;
renderer->clip_rect.w = rect->w * renderer->scale.x;
renderer->clip_rect.h = rect->h * renderer->scale.y;
renderer->clip_rect.x = (double)rect->x * renderer->scale.x;
renderer->clip_rect.y = (double)rect->y * renderer->scale.y;
renderer->clip_rect.w = (double)rect->w * renderer->scale.x;
renderer->clip_rect.h = (double)rect->h * renderer->scale.y;
} else {
renderer->clipping_enabled = SDL_FALSE;
SDL_zero(renderer->clip_rect);
@ -2535,10 +2555,10 @@ SDL_RenderWindowToLogical(SDL_Renderer * renderer, int windowX, int windowY, flo
window_physical_y = ((float) windowY) / renderer->dpi_scale.y;
if (logicalX) {
*logicalX = (window_physical_x - renderer->viewport.x) / renderer->scale.x;
*logicalX = (float)((window_physical_x - renderer->viewport.x) / renderer->scale.x);
}
if (logicalY) {
*logicalY = (window_physical_y - renderer->viewport.y) / renderer->scale.y;
*logicalY = (float)((window_physical_y - renderer->viewport.y) / renderer->scale.y);
}
}
@ -2549,8 +2569,8 @@ SDL_RenderLogicalToWindow(SDL_Renderer * renderer, float logicalX, float logical
CHECK_RENDERER_MAGIC(renderer, );
window_physical_x = (logicalX * renderer->scale.x) + renderer->viewport.x;
window_physical_y = (logicalY * renderer->scale.y) + renderer->viewport.y;
window_physical_x = (float)((logicalX * renderer->scale.x) + renderer->viewport.x);
window_physical_y = (float)((logicalY * renderer->scale.y) + renderer->viewport.y);
if (windowX) {
*windowX = (int)(window_physical_x * renderer->dpi_scale.x);
@ -3138,10 +3158,11 @@ SDL_RenderDrawLinesF(SDL_Renderer * renderer,
num_vertices, indices, num_indices, size_indices,
1.0f, 1.0f);
SDL_small_free(xy, isstack1);
SDL_small_free(indices, isstack2);
}
SDL_small_free(xy, isstack1);
SDL_small_free(indices, isstack2);
} else if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
retval = RenderDrawLinesWithRectsF(renderer, points, count);
} else {

View file

@ -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;
@ -201,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;
@ -244,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;

View file

@ -347,7 +347,8 @@ D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
}
}
static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
static D3DBLEND
GetBlendFunc(SDL_BlendFactor factor)
{
switch (factor) {
case SDL_BLENDFACTOR_ZERO:
@ -370,9 +371,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
@ -387,14 +407,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;
}
@ -1040,11 +1062,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)));
}
}

View file

@ -998,6 +998,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:

View file

@ -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
*/
@ -319,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)
{
@ -1212,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
@ -1733,6 +1752,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
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) {
@ -1746,6 +1766,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
goto error;
}
}
#endif
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
@ -1760,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;

View file

@ -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);
@ -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;
}
@ -228,6 +246,7 @@ VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
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;
@ -295,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);
@ -306,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,
@ -345,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)
@ -519,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(
@ -551,7 +796,7 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
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_;
}
@ -730,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)
{
@ -824,11 +1061,7 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
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;
@ -1013,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

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

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

@ -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:
@ -414,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);
@ -480,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,
@ -525,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,
@ -533,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,
@ -565,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);
@ -728,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,
@ -740,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),
@ -871,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 *),
@ -879,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 *),
@ -918,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);
@ -950,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();
@ -975,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);
}
}
@ -995,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)
{
@ -1021,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) {
@ -1060,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;
@ -1083,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,
@ -1106,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;
}
@ -1131,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;
}
}
@ -1181,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,
@ -1229,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

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

@ -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>
@ -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 {
@ -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 */