From 1e2eed1a018c2070157d6104aa473f744e5bf860 Mon Sep 17 00:00:00 2001
From: Ivan Epifanov <[EMAIL REDACTED]>
Date: Mon, 28 Dec 2020 15:32:52 +0300
Subject: [PATCH] Native framebuffer for software renderer
---
src/video/vita/SDL_vitaframebuffer.c | 121 +++++++++++++++++++++++++++
src/video/vita/SDL_vitaframebuffer.h | 27 ++++++
src/video/vita/SDL_vitavideo.c | 5 ++
src/video/vita/SDL_vitavideo.h | 5 ++
4 files changed, 158 insertions(+)
create mode 100644 src/video/vita/SDL_vitaframebuffer.c
create mode 100644 src/video/vita/SDL_vitaframebuffer.h
diff --git a/src/video/vita/SDL_vitaframebuffer.c b/src/video/vita/SDL_vitaframebuffer.c
new file mode 100644
index 000000000..ab6323654
--- /dev/null
+++ b/src/video/vita/SDL_vitaframebuffer.c
@@ -0,0 +1,121 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_VITA
+
+#include "SDL_vitavideo.h"
+
+#include <psp2/kernel/sysmem.h>
+
+#define SCREEN_W 960
+#define SCREEN_H 544
+#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
+#define DISPLAY_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8
+
+void *vita_gpu_alloc(SceKernelMemBlockType type, unsigned int size, SceUID *uid)
+{
+ void *mem;
+
+ if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW) {
+ size = ALIGN(size, 256*1024);
+ } else {
+ size = ALIGN(size, 4*1024);
+ }
+
+ *uid = sceKernelAllocMemBlock("gpu_mem", type, size, NULL);
+
+ if (*uid < 0)
+ return NULL;
+
+ if (sceKernelGetMemBlockBase(*uid, &mem) < 0)
+ return NULL;
+
+ return mem;
+}
+
+void vita_gpu_free(SceUID uid)
+{
+ void *mem = NULL;
+ if (sceKernelGetMemBlockBase(uid, &mem) < 0)
+ return;
+ sceKernelFreeMemBlock(uid);
+}
+
+int VITA_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SceDisplayFrameBuf framebuf;
+
+ *format = SDL_PIXELFORMAT_ABGR8888;
+ *pitch = SCREEN_W * 4;
+
+ data->buffer = vita_gpu_alloc(
+ SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
+ 4 * SCREEN_W * SCREEN_H,
+ &data->buffer_uid
+ );
+
+ // memset the buffer to black
+ for (int y = 0; y < SCREEN_H; y++) {
+ unsigned int *row = (unsigned int *)data->buffer + y * SCREEN_W;
+ for (int x = 0; x < SCREEN_W; x++) {
+ row[x] = 0xff0000FF;
+ }
+ }
+
+ SDL_memset(&framebuf, 0x00, sizeof(SceDisplayFrameBuf));
+ framebuf.size = sizeof(SceDisplayFrameBuf);
+ framebuf.base = data->buffer;
+ framebuf.pitch = SCREEN_W;
+ framebuf.pixelformat = DISPLAY_PIXEL_FORMAT;
+ framebuf.width = SCREEN_W;
+ framebuf.height = SCREEN_H;
+ sceDisplaySetFrameBuf(&framebuf, SCE_DISPLAY_SETBUF_NEXTFRAME);
+
+ *pixels = data->buffer;
+
+ return 0;
+}
+
+int VITA_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
+{
+ // do nothing
+ return 0;
+}
+
+void VITA_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if (!data) {
+ /* The window wasn't fully initialized */
+ return;
+ }
+
+ vita_gpu_free(data->buffer_uid);
+ data->buffer = NULL;
+ return;
+}
+
+#endif /* SDL_VIDEO_DRIVER_VITA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/vita/SDL_vitaframebuffer.h b/src/video/vita/SDL_vitaframebuffer.h
new file mode 100644
index 000000000..b2e6b6ae3
--- /dev/null
+++ b/src/video/vita/SDL_vitaframebuffer.h
@@ -0,0 +1,27 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2020 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"
+
+extern int VITA_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
+extern int VITA_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
+extern void VITA_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c
index 54063148b..b2c5c96b2 100644
--- a/src/video/vita/SDL_vitavideo.c
+++ b/src/video/vita/SDL_vitavideo.c
@@ -37,6 +37,7 @@
#include "SDL_vitatouch.h"
#include "SDL_vitakeyboard.h"
#include "SDL_vitamouse_c.h"
+#include "SDL_vitaframebuffer.h"
#if SDLVIDEO_OPENGL_ES2
#include "SDL_vitagl_c.h"
#endif
@@ -121,6 +122,10 @@ VITA_Create()
device->DestroyWindow = VITA_DestroyWindow;
device->GetWindowWMInfo = VITA_GetWindowWMInfo;
+ device->CreateWindowFramebuffer = VITA_CreateWindowFramebuffer;
+ device->UpdateWindowFramebuffer = VITA_UpdateWindowFramebuffer;
+ device->DestroyWindowFramebuffer = VITA_DestroyWindowFramebuffer;
+
#if SDL_VIDEO_OPENGL_ES2
device->GL_LoadLibrary = VITA_GL_LoadLibrary;
device->GL_GetProcAddress = VITA_GL_GetProcAddress;
diff --git a/src/video/vita/SDL_vitavideo.h b/src/video/vita/SDL_vitavideo.h
index 8f02e9680..f92182728 100644
--- a/src/video/vita/SDL_vitavideo.h
+++ b/src/video/vita/SDL_vitavideo.h
@@ -25,6 +25,8 @@
#include "../../SDL_internal.h"
#include "../SDL_sysvideo.h"
+#include <psp2/types.h>
+#include <psp2/display.h>
#include <psp2/ime_dialog.h>
typedef struct SDL_VideoData
@@ -34,6 +36,7 @@ typedef struct SDL_VideoData
wchar_t ime_buffer[SCE_IME_DIALOG_MAX_TEXT_LENGTH];
SDL_bool ime_active;
+
} SDL_VideoData;
@@ -46,6 +49,8 @@ typedef struct SDL_DisplayData
typedef struct SDL_WindowData
{
SDL_bool uses_gles;
+ SceUID buffer_uid;
+ void* buffer;
} SDL_WindowData;