mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-02-02 12:01:15 +00:00
add gxm renderer (not working with display yet)
This commit is contained in:
parent
40a34ef48e
commit
b38091ba1b
@ -71,12 +71,14 @@ if(VITA)
|
|||||||
set(CMAKE_POSITION_INDEPENDENT_CODE OFF)
|
set(CMAKE_POSITION_INDEPENDENT_CODE OFF)
|
||||||
set(ISLE_DEBUG OFF)
|
set(ISLE_DEBUG OFF)
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/modules")
|
||||||
|
set(VITA_USE_OPENGLES2 ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(VITA_USE_OPENGLES2)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
include(cmake/modules/pvr_psp2.cmake)
|
include(cmake/modules/pvr_psp2.cmake)
|
||||||
include(cmake/modules/sdl3_pvr_psp2.cmake)
|
include(cmake/modules/sdl3_pvr_psp2.cmake)
|
||||||
|
|
||||||
fetch_iniparser()
|
fetch_iniparser()
|
||||||
|
|
||||||
elseif (DOWNLOAD_DEPENDENCIES)
|
elseif (DOWNLOAD_DEPENDENCIES)
|
||||||
@ -87,6 +89,7 @@ elseif (DOWNLOAD_DEPENDENCIES)
|
|||||||
SDL3
|
SDL3
|
||||||
GIT_REPOSITORY "https://github.com/libsdl-org/SDL.git"
|
GIT_REPOSITORY "https://github.com/libsdl-org/SDL.git"
|
||||||
GIT_TAG "main"
|
GIT_TAG "main"
|
||||||
|
UPDATE_DISCONNECTED TRUE
|
||||||
EXCLUDE_FROM_ALL
|
EXCLUDE_FROM_ALL
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(SDL3)
|
FetchContent_MakeAvailable(SDL3)
|
||||||
@ -512,8 +515,9 @@ if (ISLE_BUILD_APP)
|
|||||||
target_link_libraries(isle PRIVATE winmm)
|
target_link_libraries(isle PRIVATE winmm)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(VITA)
|
if(VITA AND VITA_USE_OPENGLES2)
|
||||||
target_link_libraries(isle PRIVATE GLESv2)
|
target_link_libraries(isle PRIVATE GLESv2)
|
||||||
|
target_compile_definitions(isle PRIVATE USE_OPENGLES2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Link LEGO1
|
# Link LEGO1
|
||||||
@ -670,7 +674,9 @@ set(CPACK_PACKAGE_FILE_NAME "isle-${PROJECT_VERSION}-${ISLE_PACKAGE_NAME}-${CMAK
|
|||||||
if(VITA)
|
if(VITA)
|
||||||
include("${VITASDK}/share/vita.cmake" REQUIRED)
|
include("${VITASDK}/share/vita.cmake" REQUIRED)
|
||||||
|
|
||||||
target_link_libraries(lego1 PRIVATE GLESv2)
|
if(VITA_USE_OPENGLES2)
|
||||||
|
target_link_libraries(lego1 PRIVATE GLESv2)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(ISLE_PACKAGE_NAME "vita-isle")
|
set(ISLE_PACKAGE_NAME "vita-isle")
|
||||||
set(VITA_APP_NAME "Lego Island")
|
set(VITA_APP_NAME "Lego Island")
|
||||||
@ -679,12 +685,14 @@ if(VITA)
|
|||||||
|
|
||||||
vita_create_self(isle.self isle UNSAFE)
|
vita_create_self(isle.self isle UNSAFE)
|
||||||
|
|
||||||
set(VPK_FILE_ARGS)
|
if(VITA_USE_OPENGLES2)
|
||||||
get_target_property(gles_modules GLESv2 MODULES)
|
set(VPK_FILE_ARGS)
|
||||||
foreach(file IN LISTS gles_modules)
|
get_target_property(gles_modules GLESv2 MODULES)
|
||||||
get_filename_component(fname ${file} NAME)
|
foreach(file IN LISTS gles_modules)
|
||||||
list(APPEND VPK_FILE_ARGS FILE ${file} module/${fname})
|
get_filename_component(fname ${file} NAME)
|
||||||
endforeach()
|
list(APPEND VPK_FILE_ARGS FILE ${file} module/${fname})
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
vita_create_vpk(isle.vpk ${VITA_TITLEID} isle.self
|
vita_create_vpk(isle.vpk ${VITA_TITLEID} isle.self
|
||||||
VERSION ${VITA_VERSION}
|
VERSION ${VITA_VERSION}
|
||||||
|
|||||||
@ -51,8 +51,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __vita__
|
#ifdef __vita__
|
||||||
|
#include <SDL3/SDL_gxm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__vita__) && defined(USE_OPENGLES2)
|
||||||
extern "C"{
|
extern "C"{
|
||||||
#include <gpu_es4/psp2_pvr_hint.h>
|
#include <gpu_es4/psp2_pvr_hint.h>
|
||||||
}
|
}
|
||||||
#include <psp2/kernel/modulemgr.h>
|
#include <psp2/kernel/modulemgr.h>
|
||||||
|
|
||||||
@ -71,6 +75,7 @@ extern "C"{
|
|||||||
#error GPU Memory exceeds maximum memblck size
|
#error GPU Memory exceeds maximum memblck size
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern SDL_Window* DDWindow;
|
||||||
|
|
||||||
int _newlib_heap_size_user = NEWLIB_HEAP_SIZE;
|
int _newlib_heap_size_user = NEWLIB_HEAP_SIZE;
|
||||||
unsigned int sceLibcHeapSize = LIBC_HEAP_SIZE;
|
unsigned int sceLibcHeapSize = LIBC_HEAP_SIZE;
|
||||||
@ -289,9 +294,8 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv)
|
|||||||
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
|
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
|
||||||
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
||||||
|
|
||||||
#if __vita__
|
#if defined(__vita__) && defined(USE_OPENGLES2)
|
||||||
SDL_SetHint("VITA_PVR_SKIP_INIT", "enable");
|
SDL_SetHint("VITA_PVR_SKIP_INIT", "enable");
|
||||||
SDL_SetHint("SDL_RENDER_OPENGLES2_TEXCOORD_PRECISION", "high"); // not really needed
|
|
||||||
PVRSRV_PSP2_APPHINT hint;
|
PVRSRV_PSP2_APPHINT hint;
|
||||||
|
|
||||||
sceKernelLoadStartModule("vs0:sys/external/libfios2.suprx", 0, NULL, 0, NULL, NULL);
|
sceKernelLoadStartModule("vs0:sys/external/libfios2.suprx", 0, NULL, 0, NULL, NULL);
|
||||||
@ -708,7 +712,7 @@ MxResult IsleApp::SetupWindow()
|
|||||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, g_targetHeight);
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, g_targetHeight);
|
||||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, m_fullScreen);
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, m_fullScreen);
|
||||||
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, WINDOW_TITLE);
|
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, WINDOW_TITLE);
|
||||||
#ifdef MINIWIN
|
#if defined(MINIWIN) && !defined(USE_GXM)
|
||||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
|
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -720,6 +724,8 @@ MxResult IsleApp::SetupWindow()
|
|||||||
(HWND) SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
|
(HWND) SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DDWindow = window;
|
||||||
|
|
||||||
SDL_DestroyProperties(props);
|
SDL_DestroyProperties(props);
|
||||||
|
|
||||||
if (!m_windowHandle) {
|
if (!m_windowHandle) {
|
||||||
|
|||||||
@ -52,6 +52,20 @@ else()
|
|||||||
message(STATUS "🧩 OpenGL ES 2.x support not enabled")
|
message(STATUS "🧩 OpenGL ES 2.x support not enabled")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(VITA)
|
||||||
|
target_sources(miniwin PRIVATE
|
||||||
|
src/d3drm/backends/gxm/renderer.cpp
|
||||||
|
src/d3drm/backends/gxm/memory.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(miniwin PRIVATE
|
||||||
|
SceGxm_stub
|
||||||
|
SceRazorCapture_stub
|
||||||
|
)
|
||||||
|
# for shaders incbin
|
||||||
|
target_include_directories(miniwin PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/d3drm/backends/gxm)
|
||||||
|
target_link_directories(miniwin PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/d3drm/backends/gxm)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_sources(miniwin PRIVATE
|
target_sources(miniwin PRIVATE
|
||||||
src/d3drm/backends/directx9/actual.cpp
|
src/d3drm/backends/directx9/actual.cpp
|
||||||
|
|||||||
1
miniwin/src/d3drm/backends/gxm/.gitignore
vendored
Normal file
1
miniwin/src/d3drm/backends/gxm/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.exe
|
||||||
7
miniwin/src/d3drm/backends/gxm/Makefile
Normal file
7
miniwin/src/d3drm/backends/gxm/Makefile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
all: main.frag.gxp main.vert.gxp clear.frag.gxp clear.vert.gxp
|
||||||
|
|
||||||
|
%.vert.gxp: %.vert.cg
|
||||||
|
./psp2cgc.exe -Wperf -profile sce_vp_psp2 $< -o $@
|
||||||
|
|
||||||
|
%.frag.gxp: %.frag.cg
|
||||||
|
./psp2cgc.exe -Wperf -profile sce_fp_psp2 $< -o $@
|
||||||
5
miniwin/src/d3drm/backends/gxm/clear.frag.cg
Normal file
5
miniwin/src/d3drm/backends/gxm/clear.frag.cg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
void main(
|
||||||
|
out float4 outColor : COLOR
|
||||||
|
) {
|
||||||
|
outColor = float4(0.0, 0.0, 0.5, 1.0);
|
||||||
|
}
|
||||||
BIN
miniwin/src/d3drm/backends/gxm/clear.frag.gxp
Normal file
BIN
miniwin/src/d3drm/backends/gxm/clear.frag.gxp
Normal file
Binary file not shown.
7
miniwin/src/d3drm/backends/gxm/clear.vert.cg
Normal file
7
miniwin/src/d3drm/backends/gxm/clear.vert.cg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
void main(
|
||||||
|
float2 aPosition : POSITION,
|
||||||
|
|
||||||
|
out float4 vPosition : POSITION
|
||||||
|
) {
|
||||||
|
vPosition = float4(aPosition, 0.0, 1.0);
|
||||||
|
}
|
||||||
BIN
miniwin/src/d3drm/backends/gxm/clear.vert.gxp
Normal file
BIN
miniwin/src/d3drm/backends/gxm/clear.vert.gxp
Normal file
Binary file not shown.
BIN
miniwin/src/d3drm/backends/gxm/libSceRazorCapture_stub.a
Normal file
BIN
miniwin/src/d3drm/backends/gxm/libSceRazorCapture_stub.a
Normal file
Binary file not shown.
66
miniwin/src/d3drm/backends/gxm/main.frag.cg
Normal file
66
miniwin/src/d3drm/backends/gxm/main.frag.cg
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
struct SceneLight {
|
||||||
|
float4 color;
|
||||||
|
float4 position;
|
||||||
|
float4 direction;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main(
|
||||||
|
float4 vPosition : POSITION,
|
||||||
|
float3 vViewPos : TEXCOORD1,
|
||||||
|
float3 vNormal : TEXCOORD2,
|
||||||
|
float2 vTexCoord : TEXCOORD3,
|
||||||
|
|
||||||
|
uniform SceneLight uLights[3] : BUFFER[0],
|
||||||
|
uniform int uLightCount : BUFFER[0],
|
||||||
|
uniform float uShininess,
|
||||||
|
uniform float4 uColor,
|
||||||
|
uniform int uUseTexture,
|
||||||
|
uniform sampler2D uTexture,
|
||||||
|
|
||||||
|
out float4 outColor : COLOR
|
||||||
|
) {
|
||||||
|
float3 diffuse = float3(0.0, 0.0, 0.0);
|
||||||
|
float3 specular = float3(0.0, 0.0, 0.0);
|
||||||
|
float3 normal = normalize(vNormal);
|
||||||
|
|
||||||
|
for (int i = 0; i < uLightCount; ++i) {
|
||||||
|
float3 lightColor = uLights[i].color.rgb;
|
||||||
|
|
||||||
|
// ambient
|
||||||
|
if (uLights[i].position.w == 0.0 && uLights[i].direction.w == 0.0) {
|
||||||
|
diffuse += lightColor;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// directional
|
||||||
|
float3 lightVec;
|
||||||
|
if (uLights[i].direction.w == 1.0) {
|
||||||
|
lightVec = -normalize(uLights[i].direction.xyz);
|
||||||
|
} else { // point
|
||||||
|
lightVec = normalize(uLights[i].position.xyz - vViewPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
float dotNL = max(dot(normal, lightVec), 0.0);
|
||||||
|
if (dotNL > 0.0) {
|
||||||
|
// Diffuse contribution
|
||||||
|
diffuse += dotNL * lightColor;
|
||||||
|
|
||||||
|
// Specular
|
||||||
|
if (uShininess > 0.0) {
|
||||||
|
float3 viewVec = normalize(-vViewPos); // Assuming camera at origin
|
||||||
|
float3 halfVec = normalize(lightVec + viewVec);
|
||||||
|
float dotNH = max(dot(normal, halfVec), 0.0);
|
||||||
|
float spec = pow(dotNH, uShininess);
|
||||||
|
specular += spec * lightColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outColor = uColor;
|
||||||
|
outColor.rgb = clamp(diffuse * uColor.rgb + specular, 0.0, 1.0);
|
||||||
|
if (uUseTexture != 0) {
|
||||||
|
float4 texel = tex2D(uTexture, vTexCoord);
|
||||||
|
outColor.rgb *= texel.rgb;
|
||||||
|
outColor.rgb = clamp(outColor.rgb, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
miniwin/src/d3drm/backends/gxm/main.frag.gxp
Normal file
BIN
miniwin/src/d3drm/backends/gxm/main.frag.gxp
Normal file
Binary file not shown.
20
miniwin/src/d3drm/backends/gxm/main.vert.cg
Normal file
20
miniwin/src/d3drm/backends/gxm/main.vert.cg
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
void main(
|
||||||
|
float3 aPosition : POSITION,
|
||||||
|
float3 aNormal : NORMAL,
|
||||||
|
float2 aTexCoord : TEXCOORD0,
|
||||||
|
|
||||||
|
uniform float4x4 uModelViewMatrix,
|
||||||
|
uniform float3x3 uNormalMatrix,
|
||||||
|
uniform float4x4 uProjectionMatrix,
|
||||||
|
|
||||||
|
out float4 vPosition : POSITION,
|
||||||
|
out float3 vViewPos : TEXCOORD1,
|
||||||
|
out float3 vNormal : TEXCOORD2,
|
||||||
|
out float2 vTexCoord : TEXCOORD3
|
||||||
|
) {
|
||||||
|
float4 viewPos = mul(uModelViewMatrix, float4(aPosition, 1.0));
|
||||||
|
vPosition = mul(uProjectionMatrix, viewPos);
|
||||||
|
vViewPos = viewPos.xyz;
|
||||||
|
vNormal = normalize(mul(uNormalMatrix, aNormal));
|
||||||
|
vTexCoord = aTexCoord;
|
||||||
|
}
|
||||||
BIN
miniwin/src/d3drm/backends/gxm/main.vert.gxp
Normal file
BIN
miniwin/src/d3drm/backends/gxm/main.vert.gxp
Normal file
Binary file not shown.
128
miniwin/src/d3drm/backends/gxm/memory.cpp
Normal file
128
miniwin/src/d3drm/backends/gxm/memory.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#include "memory.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <psp2/gxm.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void *patcher_host_alloc(void *user_data, unsigned int size)
|
||||||
|
{
|
||||||
|
void *mem = SDL_malloc(size);
|
||||||
|
(void)user_data;
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void patcher_host_free(void *user_data, void *mem)
|
||||||
|
{
|
||||||
|
(void)user_data;
|
||||||
|
SDL_free(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* vita_mem_alloc(
|
||||||
|
unsigned int type,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
int attribs,
|
||||||
|
SceUID *uid,
|
||||||
|
const char* name,
|
||||||
|
size_t* alignedSize
|
||||||
|
) {
|
||||||
|
void *mem;
|
||||||
|
|
||||||
|
if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW) {
|
||||||
|
size = ALIGN(size, 256 * 1024);
|
||||||
|
} else if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW) {
|
||||||
|
size = ALIGN(size, 1024 * 1024);
|
||||||
|
} else {
|
||||||
|
size = ALIGN(size, 4 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
*uid = sceKernelAllocMemBlock(name, type, size, NULL);
|
||||||
|
|
||||||
|
if (*uid < 0) {
|
||||||
|
SDL_Log("sceKernelAllocMemBlock: 0x%x", *uid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sceKernelGetMemBlockBase(*uid, &mem) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sceGxmMapMemory(mem, size, (SceGxmMemoryAttribFlags)attribs) < 0) {
|
||||||
|
SDL_Log("sceGxmMapMemory 0x%x 0x%x %d failed", mem, size, attribs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(alignedSize) {
|
||||||
|
*alignedSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vita_mem_free(SceUID uid)
|
||||||
|
{
|
||||||
|
void *mem = NULL;
|
||||||
|
if (sceKernelGetMemBlockBase(uid, &mem) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sceGxmUnmapMemory(mem);
|
||||||
|
sceKernelFreeMemBlock(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
|
||||||
|
{
|
||||||
|
void *mem = NULL;
|
||||||
|
|
||||||
|
size = ALIGN(size, 4096);
|
||||||
|
*uid = sceKernelAllocMemBlock("vertex_usse", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL);
|
||||||
|
|
||||||
|
if (sceKernelGetMemBlockBase(*uid, &mem) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (sceGxmMapVertexUsseMemory(mem, size, usse_offset) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vita_mem_vertex_usse_free(SceUID uid)
|
||||||
|
{
|
||||||
|
void *mem = NULL;
|
||||||
|
if (sceKernelGetMemBlockBase(uid, &mem) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sceGxmUnmapVertexUsseMemory(mem);
|
||||||
|
sceKernelFreeMemBlock(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
|
||||||
|
{
|
||||||
|
void *mem = NULL;
|
||||||
|
|
||||||
|
size = ALIGN(size, 4096);
|
||||||
|
*uid = sceKernelAllocMemBlock("fragment_usse", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL);
|
||||||
|
|
||||||
|
if (sceKernelGetMemBlockBase(*uid, &mem) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (sceGxmMapFragmentUsseMemory(mem, size, usse_offset) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vita_mem_fragment_usse_free(SceUID uid)
|
||||||
|
{
|
||||||
|
void *mem = NULL;
|
||||||
|
if (sceKernelGetMemBlockBase(uid, &mem) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sceGxmUnmapFragmentUsseMemory(mem);
|
||||||
|
sceKernelFreeMemBlock(uid);
|
||||||
|
}
|
||||||
25
miniwin/src/d3drm/backends/gxm/memory.h
Normal file
25
miniwin/src/d3drm/backends/gxm/memory.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psp2/types.h>
|
||||||
|
#include <psp2/kernel/sysmem.h>
|
||||||
|
#include <psp2/kernel/clib.h>
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
|
||||||
|
void *patcher_host_alloc(void *user_data, unsigned int size);
|
||||||
|
void patcher_host_free(void *user_data, void *mem);
|
||||||
|
|
||||||
|
void* vita_mem_alloc(
|
||||||
|
unsigned int type,
|
||||||
|
size_t size,
|
||||||
|
size_t alignment,
|
||||||
|
int attribs,
|
||||||
|
SceUID* uid,
|
||||||
|
const char* name,
|
||||||
|
size_t* alignedSize
|
||||||
|
);
|
||||||
|
void vita_mem_free(SceUID uid);
|
||||||
|
|
||||||
|
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);
|
||||||
948
miniwin/src/d3drm/backends/gxm/renderer.cpp
Normal file
948
miniwin/src/d3drm/backends/gxm/renderer.cpp
Normal file
@ -0,0 +1,948 @@
|
|||||||
|
#include "d3drmrenderer_gxm.h"
|
||||||
|
#include "meshutils.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <GLES2/gl2ext.h>
|
||||||
|
|
||||||
|
#include <psp2/gxm.h>
|
||||||
|
#include <psp2/display.h>
|
||||||
|
#include <psp2/types.h>
|
||||||
|
#include <psp2/kernel/modulemgr.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_gxm.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
bool with_razor = false;
|
||||||
|
|
||||||
|
|
||||||
|
#define VITA_GXM_SCREEN_WIDTH 960
|
||||||
|
#define VITA_GXM_SCREEN_HEIGHT 544
|
||||||
|
#define VITA_GXM_SCREEN_STRIDE 960
|
||||||
|
|
||||||
|
#define VITA_GXM_COLOR_FORMAT SCE_GXM_COLOR_FORMAT_A8B8G8R8
|
||||||
|
#define VITA_GXM_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8
|
||||||
|
|
||||||
|
struct SceneLightGXM {
|
||||||
|
float color[4];
|
||||||
|
float position[4];
|
||||||
|
float direction[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Vertex {
|
||||||
|
float position[3];
|
||||||
|
float normal[3];
|
||||||
|
float texCoord[2];
|
||||||
|
} Vertex;
|
||||||
|
|
||||||
|
|
||||||
|
static bool make_fragment_program(
|
||||||
|
GXMRendererData* data,
|
||||||
|
const SceGxmProgram* vertexProgramGxp,
|
||||||
|
const SceGxmBlendInfo *blendInfo,
|
||||||
|
SceGxmFragmentProgram** fragmentProgram
|
||||||
|
) {
|
||||||
|
return SCE_ERR(sceGxmShaderPatcherCreateFragmentProgram,
|
||||||
|
data->shaderPatcher,
|
||||||
|
data->mainFragmentProgramId,
|
||||||
|
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
|
||||||
|
SCE_GXM_MULTISAMPLE_NONE,
|
||||||
|
blendInfo,
|
||||||
|
vertexProgramGxp,
|
||||||
|
fragmentProgram
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
INCBIN("main.vert.gxp", main_vert_gxp_start);
|
||||||
|
INCBIN("main.frag.gxp", main_frag_gxp_start);
|
||||||
|
INCBIN("clear.vert.gxp", clear_vert_gxp_start);
|
||||||
|
INCBIN("clear.frag.gxp", clear_frag_gxp_start);
|
||||||
|
|
||||||
|
const SceGxmProgram* clearVertexProgramGxp = (const SceGxmProgram*)&clear_vert_gxp_start;
|
||||||
|
const SceGxmProgram* clearFragmentProgramGxp = (const SceGxmProgram*)&clear_frag_gxp_start;
|
||||||
|
const SceGxmProgram* mainVertexProgramGxp = (const SceGxmProgram*)&main_vert_gxp_start;
|
||||||
|
const SceGxmProgram* mainFragmentProgramGxp = (const SceGxmProgram*)&main_frag_gxp_start;
|
||||||
|
|
||||||
|
|
||||||
|
static const size_t clearMeshVerticiesSize = 3 * sizeof(float)*2;
|
||||||
|
static const size_t clearMeshIndiciesSize = 3 * sizeof(uint16_t);
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int sceRazorGpuCaptureSetTrigger(int frames, const char* path);
|
||||||
|
extern "C" int sceRazorGpuCaptureEnableSalvage(const char* path);
|
||||||
|
extern "C" int sceRazorGpuCaptureSetTriggerNextFrame(const char* path);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define GET_SHADER_PARAM(var, gxp, name) \
|
||||||
|
const SceGxmProgramParameter* var = sceGxmProgramFindParameterByName(gxp, name); \
|
||||||
|
if(!var) { \
|
||||||
|
SDL_Log("Failed to find param %s", name); \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool create_gxm_renderer(int width, int height, GXMRendererData* data) {
|
||||||
|
const unsigned int alignedWidth = ALIGN(width, SCE_GXM_TILE_SIZEX);
|
||||||
|
const unsigned int alignedHeight = ALIGN(height, SCE_GXM_TILE_SIZEY);
|
||||||
|
|
||||||
|
unsigned int sampleCount = alignedWidth * alignedHeight;
|
||||||
|
unsigned int depthStrideInSamples = alignedWidth;
|
||||||
|
|
||||||
|
const unsigned int patcherBufferSize = 64 * 1024;
|
||||||
|
const unsigned int patcherVertexUsseSize = 64 * 1024;
|
||||||
|
const unsigned int patcherFragmentUsseSize = 64 * 1024;
|
||||||
|
|
||||||
|
|
||||||
|
static const SceGxmBlendInfo blendInfoOpaque = {
|
||||||
|
.colorMask = SCE_GXM_COLOR_MASK_ALL,
|
||||||
|
.colorFunc = SCE_GXM_BLEND_FUNC_NONE,
|
||||||
|
.alphaFunc = SCE_GXM_BLEND_FUNC_NONE,
|
||||||
|
.colorSrc = SCE_GXM_BLEND_FACTOR_ZERO,
|
||||||
|
.colorDst = SCE_GXM_BLEND_FACTOR_ZERO,
|
||||||
|
.alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO,
|
||||||
|
.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const SceGxmBlendInfo blendInfoTransparent = {
|
||||||
|
.colorMask = SCE_GXM_COLOR_MASK_ALL,
|
||||||
|
.colorFunc = SCE_GXM_BLEND_FUNC_ADD,
|
||||||
|
.alphaFunc = SCE_GXM_BLEND_FUNC_ADD,
|
||||||
|
.colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA,
|
||||||
|
.colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||||
|
.alphaSrc = SCE_GXM_BLEND_FACTOR_ONE,
|
||||||
|
.alphaDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||||
|
};
|
||||||
|
|
||||||
|
data->cdramPool = SDL_gxm_get_cdramPool();
|
||||||
|
if(!data->cdramPool) {
|
||||||
|
SDL_Log("failed to allocate cdramPool");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate buffers
|
||||||
|
data->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,
|
||||||
|
"vdmRingBuffer",
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
data->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,
|
||||||
|
"vertexRingBuffer",
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
data->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,
|
||||||
|
"fragmentRingBuffer",
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
data->fragmentUsseRingBuffer = vita_mem_fragment_usse_alloc(
|
||||||
|
SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE,
|
||||||
|
&data->fragmentUsseRingBufferUid,
|
||||||
|
&data->fragmentUsseRingBufferOffset);
|
||||||
|
|
||||||
|
// create context
|
||||||
|
SceGxmContextParams contextParams;
|
||||||
|
memset(&contextParams, 0, sizeof(SceGxmContextParams));
|
||||||
|
contextParams.hostMem = SDL_malloc(SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE);
|
||||||
|
contextParams.hostMemSize = SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE;
|
||||||
|
contextParams.vdmRingBufferMem = data->vdmRingBuffer;
|
||||||
|
contextParams.vdmRingBufferMemSize = SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE;
|
||||||
|
contextParams.vertexRingBufferMem = data->vertexRingBuffer;
|
||||||
|
contextParams.vertexRingBufferMemSize = SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE;
|
||||||
|
contextParams.fragmentRingBufferMem = data->fragmentRingBuffer;
|
||||||
|
contextParams.fragmentRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE;
|
||||||
|
contextParams.fragmentUsseRingBufferMem = data->fragmentUsseRingBuffer;
|
||||||
|
contextParams.fragmentUsseRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE;
|
||||||
|
contextParams.fragmentUsseRingBufferOffset = data->fragmentUsseRingBufferOffset;
|
||||||
|
|
||||||
|
if(SCE_ERR(sceGxmCreateContext, &contextParams, &data->context)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data->contextHostMem = contextParams.hostMem;
|
||||||
|
|
||||||
|
// shader patcher
|
||||||
|
data->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,
|
||||||
|
"patcherBuffer",
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
data->patcherVertexUsse = vita_mem_vertex_usse_alloc(
|
||||||
|
patcherVertexUsseSize,
|
||||||
|
&data->patcherVertexUsseUid,
|
||||||
|
&data->patcherVertexUsseOffset);
|
||||||
|
|
||||||
|
data->patcherFragmentUsse = vita_mem_fragment_usse_alloc(
|
||||||
|
patcherFragmentUsseSize,
|
||||||
|
&data->patcherFragmentUsseUid,
|
||||||
|
&data->patcherFragmentUsseOffset);
|
||||||
|
|
||||||
|
SceGxmShaderPatcherParams patcherParams;
|
||||||
|
memset(&patcherParams, 0, sizeof(SceGxmShaderPatcherParams));
|
||||||
|
patcherParams.userData = NULL;
|
||||||
|
patcherParams.hostAllocCallback = &patcher_host_alloc;
|
||||||
|
patcherParams.hostFreeCallback = &patcher_host_free;
|
||||||
|
patcherParams.bufferAllocCallback = NULL;
|
||||||
|
patcherParams.bufferFreeCallback = NULL;
|
||||||
|
patcherParams.bufferMem = data->patcherBuffer;
|
||||||
|
patcherParams.bufferMemSize = patcherBufferSize;
|
||||||
|
patcherParams.vertexUsseAllocCallback = NULL;
|
||||||
|
patcherParams.vertexUsseFreeCallback = NULL;
|
||||||
|
patcherParams.vertexUsseMem = data->patcherVertexUsse;
|
||||||
|
patcherParams.vertexUsseMemSize = patcherVertexUsseSize;
|
||||||
|
patcherParams.vertexUsseOffset = data->patcherVertexUsseOffset;
|
||||||
|
patcherParams.fragmentUsseAllocCallback = NULL;
|
||||||
|
patcherParams.fragmentUsseFreeCallback = NULL;
|
||||||
|
patcherParams.fragmentUsseMem = data->patcherFragmentUsse;
|
||||||
|
patcherParams.fragmentUsseMemSize = patcherFragmentUsseSize;
|
||||||
|
patcherParams.fragmentUsseOffset = data->patcherFragmentUsseOffset;
|
||||||
|
|
||||||
|
if(SCE_ERR(sceGxmShaderPatcherCreate, &patcherParams, &data->shaderPatcher)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// render target
|
||||||
|
SceGxmRenderTargetParams renderTargetParams;
|
||||||
|
memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams));
|
||||||
|
renderTargetParams.flags = 0;
|
||||||
|
renderTargetParams.width = width;
|
||||||
|
renderTargetParams.height = height;
|
||||||
|
renderTargetParams.scenesPerFrame = 1;
|
||||||
|
renderTargetParams.multisampleMode = 0;
|
||||||
|
renderTargetParams.multisampleLocations = 0;
|
||||||
|
renderTargetParams.driverMemBlock = -1; // Invalid UID
|
||||||
|
|
||||||
|
if(SCE_ERR(sceGxmCreateRenderTarget, &renderTargetParams, &data->renderTarget)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->renderBuffer = vita_mem_alloc(
|
||||||
|
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
|
||||||
|
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
|
||||||
|
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
|
||||||
|
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||||
|
&data->renderBufferUid, "display", nullptr);
|
||||||
|
|
||||||
|
// color surface
|
||||||
|
if(SCE_ERR(sceGxmColorSurfaceInit,
|
||||||
|
&data->renderSurface,
|
||||||
|
SCE_GXM_COLOR_FORMAT_A8B8G8R8,
|
||||||
|
SCE_GXM_COLOR_SURFACE_LINEAR,
|
||||||
|
SCE_GXM_COLOR_SURFACE_SCALE_NONE,
|
||||||
|
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
|
||||||
|
width, height,
|
||||||
|
width,
|
||||||
|
data->renderBuffer
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(SCE_ERR(sceGxmSyncObjectCreate, &data->renderBufferSync)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// depth & stencil
|
||||||
|
data->depthBufferData = vita_mem_alloc(
|
||||||
|
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
|
||||||
|
4 * sampleCount,
|
||||||
|
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
|
||||||
|
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||||
|
&data->depthBufferUid,
|
||||||
|
"depthBufferData",
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
data->stencilBufferData = vita_mem_alloc(
|
||||||
|
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
|
||||||
|
4 * sampleCount,
|
||||||
|
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
|
||||||
|
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||||
|
&data->stencilBufferUid,
|
||||||
|
"stencilBufferData",
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
if(SCE_ERR(sceGxmDepthStencilSurfaceInit,
|
||||||
|
&data->depthSurface,
|
||||||
|
SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24,
|
||||||
|
SCE_GXM_DEPTH_STENCIL_SURFACE_TILED,
|
||||||
|
depthStrideInSamples,
|
||||||
|
data->depthBufferData,
|
||||||
|
data->stencilBufferData
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// clear shader
|
||||||
|
{
|
||||||
|
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, clearVertexProgramGxp, &data->clearVertexProgramId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, clearFragmentProgramGxp, &data->clearFragmentProgramId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GET_SHADER_PARAM(positionAttribute, clearVertexProgramGxp, "aPosition");
|
||||||
|
|
||||||
|
SceGxmVertexAttribute vertexAttributes[1];
|
||||||
|
SceGxmVertexStream vertexStreams[1];
|
||||||
|
vertexAttributes[0].streamIndex = 0;
|
||||||
|
vertexAttributes[0].offset = 0;
|
||||||
|
vertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||||
|
vertexAttributes[0].componentCount = 2;
|
||||||
|
vertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(positionAttribute);
|
||||||
|
vertexStreams[0].stride = sizeof(float)*2;
|
||||||
|
vertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
|
||||||
|
|
||||||
|
if(SCE_ERR(sceGxmShaderPatcherCreateVertexProgram,
|
||||||
|
data->shaderPatcher,
|
||||||
|
data->clearVertexProgramId,
|
||||||
|
vertexAttributes, 1,
|
||||||
|
vertexStreams, 1,
|
||||||
|
&data->clearVertexProgram
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SCE_ERR(sceGxmShaderPatcherCreateFragmentProgram,
|
||||||
|
data->shaderPatcher,
|
||||||
|
data->clearFragmentProgramId,
|
||||||
|
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
|
||||||
|
SCE_GXM_MULTISAMPLE_NONE,
|
||||||
|
NULL,
|
||||||
|
clearVertexProgramGxp,
|
||||||
|
&data->clearFragmentProgram
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// main shader
|
||||||
|
{
|
||||||
|
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, mainVertexProgramGxp, &data->mainVertexProgramId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(SCE_ERR(sceGxmShaderPatcherRegisterProgram, data->shaderPatcher, mainFragmentProgramGxp, &data->mainFragmentProgramId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GET_SHADER_PARAM(positionAttribute, mainVertexProgramGxp, "aPosition");
|
||||||
|
GET_SHADER_PARAM(normalAttribute, mainVertexProgramGxp, "aNormal");
|
||||||
|
GET_SHADER_PARAM(texCoordAttribute, mainVertexProgramGxp, "aTexCoord");
|
||||||
|
|
||||||
|
SceGxmVertexAttribute vertexAttributes[3];
|
||||||
|
SceGxmVertexStream vertexStreams[1];
|
||||||
|
|
||||||
|
// position
|
||||||
|
vertexAttributes[0].streamIndex = 0;
|
||||||
|
vertexAttributes[0].offset = 0;
|
||||||
|
vertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||||
|
vertexAttributes[0].componentCount = 3;
|
||||||
|
vertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(positionAttribute);
|
||||||
|
|
||||||
|
// normal
|
||||||
|
vertexAttributes[1].streamIndex = 0;
|
||||||
|
vertexAttributes[1].offset = 12;
|
||||||
|
vertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||||
|
vertexAttributes[1].componentCount = 3;
|
||||||
|
vertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(normalAttribute);
|
||||||
|
|
||||||
|
vertexAttributes[2].streamIndex = 0;
|
||||||
|
vertexAttributes[2].offset = 24;
|
||||||
|
vertexAttributes[2].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||||
|
vertexAttributes[2].componentCount = 2;
|
||||||
|
vertexAttributes[2].regIndex = sceGxmProgramParameterGetResourceIndex(texCoordAttribute);
|
||||||
|
|
||||||
|
vertexStreams[0].stride = sizeof(Vertex);
|
||||||
|
vertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
|
||||||
|
|
||||||
|
if(SCE_ERR(sceGxmShaderPatcherCreateVertexProgram,
|
||||||
|
data->shaderPatcher,
|
||||||
|
data->mainVertexProgramId,
|
||||||
|
vertexAttributes, 3,
|
||||||
|
vertexStreams, 1,
|
||||||
|
&data->mainVertexProgram
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(make_fragment_program(data, mainVertexProgramGxp, &blendInfoOpaque, &data->opaqueFragmentProgram)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(make_fragment_program(data, mainVertexProgramGxp, &blendInfoTransparent, &data->transparentFragmentProgram)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vertex uniforms
|
||||||
|
data->uModelViewMatrixParam = sceGxmProgramFindParameterByName(mainVertexProgramGxp, "uModelViewMatrix");
|
||||||
|
data->uNormalMatrixParam = sceGxmProgramFindParameterByName(mainVertexProgramGxp, "uNormalMatrix");
|
||||||
|
data->uProjectionMatrixParam = sceGxmProgramFindParameterByName(mainVertexProgramGxp, "uProjectionMatrix");
|
||||||
|
|
||||||
|
// fragment uniforms
|
||||||
|
data->uLights = sceGxmProgramFindParameterByName(mainFragmentProgramGxp, "uLights"); // SceneLight[3]
|
||||||
|
data->uLightCount = sceGxmProgramFindParameterByName(mainFragmentProgramGxp, "uLightCount"); // int
|
||||||
|
data->uShininess = sceGxmProgramFindParameterByName(mainFragmentProgramGxp, "uShininess"); // float
|
||||||
|
data->uColor = sceGxmProgramFindParameterByName(mainFragmentProgramGxp, "uColor"); // vec4
|
||||||
|
data->uUseTexture = sceGxmProgramFindParameterByName(mainFragmentProgramGxp, "uUseTexture"); // int
|
||||||
|
|
||||||
|
|
||||||
|
// clear mesh
|
||||||
|
data->clearMeshBuffer = sceClibMspaceMalloc(data->cdramPool, clearMeshVerticiesSize + clearMeshIndiciesSize);
|
||||||
|
data->clearVerticies = (float*)data->clearMeshBuffer;
|
||||||
|
data->clearIndicies = (uint16_t*)((uint8_t*)(data->clearMeshBuffer)+clearMeshVerticiesSize);
|
||||||
|
|
||||||
|
data->clearVerticies[0] = -1.0 * width;
|
||||||
|
data->clearVerticies[1] = -1.0 * height;
|
||||||
|
data->clearVerticies[2] = 3.0 * width;
|
||||||
|
data->clearVerticies[3] = -1.0 * height;
|
||||||
|
data->clearVerticies[4] = -1.0;
|
||||||
|
data->clearVerticies[5] = 3.0;
|
||||||
|
|
||||||
|
data->clearIndicies[0] = 0;
|
||||||
|
data->clearIndicies[1] = 1;
|
||||||
|
data->clearIndicies[2] = 2;
|
||||||
|
|
||||||
|
// light uniforms buffer
|
||||||
|
data->lightDataBuffer = sceClibMspaceMalloc(data->cdramPool,
|
||||||
|
3 * sizeof(SceneLightGXM) + 4 // 3 lights + light count
|
||||||
|
);
|
||||||
|
sceGxmSetFragmentUniformBuffer(data->context, 0, data->lightDataBuffer);
|
||||||
|
|
||||||
|
sceGxmSetFrontStencilRef(data->context, 1);
|
||||||
|
sceGxmSetFrontStencilFunc(
|
||||||
|
data->context,
|
||||||
|
SCE_GXM_STENCIL_FUNC_ALWAYS,
|
||||||
|
SCE_GXM_STENCIL_OP_KEEP,
|
||||||
|
SCE_GXM_STENCIL_OP_KEEP,
|
||||||
|
SCE_GXM_STENCIL_OP_KEEP,
|
||||||
|
0xFF,
|
||||||
|
0xFF
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define VITA_GXM_PENDING_SWAPS 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <taihen.h>
|
||||||
|
static tai_hook_ref_t local_open_hook;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
SceUID hook_local_open(const char *path, int flags, SceMode mode) {
|
||||||
|
SceUID fd = ({
|
||||||
|
struct _tai_hook_user *cur, *next;
|
||||||
|
cur = (struct _tai_hook_user *)(local_open_hook);
|
||||||
|
next = (struct _tai_hook_user *)cur->next;
|
||||||
|
(next == __null) ?
|
||||||
|
((SceUID(*)(const char*, int, int))cur->old)(path, flags, mode) :
|
||||||
|
((SceUID(*)(const char*, int, int))next->func)(path, flags, mode);
|
||||||
|
});
|
||||||
|
|
||||||
|
printf("open in razor: %s, ret: %x", path, fd);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" void load_razor() {
|
||||||
|
int mod_id = _sceKernelLoadModule("app0:librazorcapture_es4.suprx", 0, nullptr);
|
||||||
|
int status;
|
||||||
|
if(!SCE_ERR(sceKernelStartModule, mod_id, 0, nullptr, 0, nullptr, &status)) {
|
||||||
|
with_razor = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(with_razor) {
|
||||||
|
sceRazorGpuCaptureEnableSalvage("ux0:data/gpu_crash.sgx");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool gxm_init() {
|
||||||
|
if(SDL_gxm_is_init()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_gxm_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
SceGxmInitializeParams initializeParams;
|
||||||
|
SDL_memset(&initializeParams, 0, sizeof(SceGxmInitializeParams));
|
||||||
|
initializeParams.flags = 0;
|
||||||
|
initializeParams.displayQueueMaxPendingCount = VITA_GXM_PENDING_SWAPS;
|
||||||
|
initializeParams.displayQueueCallback = display_callback;
|
||||||
|
initializeParams.displayQueueCallbackDataSize = sizeof(GXMDisplayData);
|
||||||
|
initializeParams.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE;
|
||||||
|
|
||||||
|
int err = sceGxmInitialize(&initializeParams);
|
||||||
|
if (err != 0) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "gxm init failed: %d", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Direct3DRMRenderer* GXMRenderer::Create(DWORD width, DWORD height)
|
||||||
|
{
|
||||||
|
SDL_Log("GXMRenderer::Create width=%d height=%d", width, height);
|
||||||
|
|
||||||
|
bool success = gxm_init();
|
||||||
|
if(!success) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GXMRendererData gxm_data;
|
||||||
|
success = create_gxm_renderer(width, height, &gxm_data);
|
||||||
|
if(!success) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GXMRenderer(width, height, gxm_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
GXMRenderer::GXMRenderer(
|
||||||
|
DWORD width,
|
||||||
|
DWORD height,
|
||||||
|
GXMRendererData data
|
||||||
|
) : m_width(width), m_height(height), m_data(data) {
|
||||||
|
}
|
||||||
|
|
||||||
|
GXMRenderer::~GXMRenderer() {
|
||||||
|
if(!m_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sceGxmShaderPatcherDestroy(this->m_data.shaderPatcher);
|
||||||
|
sceGxmDestroyRenderTarget(this->m_data.renderTarget);
|
||||||
|
|
||||||
|
vita_mem_free(this->m_data.renderBufferUid);
|
||||||
|
sceGxmSyncObjectDestroy(this->m_data.renderBufferSync);
|
||||||
|
|
||||||
|
vita_mem_free(this->m_data.depthBufferUid);
|
||||||
|
this->m_data.depthBufferData = nullptr;
|
||||||
|
vita_mem_free(this->m_data.stencilBufferUid);
|
||||||
|
this->m_data.stencilBufferData = nullptr;
|
||||||
|
|
||||||
|
sceGxmDestroyContext(this->m_data.context);
|
||||||
|
vita_mem_fragment_usse_free(this->m_data.fragmentUsseRingBufferUid);
|
||||||
|
vita_mem_free(this->m_data.fragmentRingBufferUid);
|
||||||
|
vita_mem_free(this->m_data.vertexRingBufferUid);
|
||||||
|
vita_mem_free(this->m_data.vdmRingBufferUid);
|
||||||
|
SDL_free(this->m_data.contextHostMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GXMRenderer::AllocateGpu(size_t size, size_t align) {
|
||||||
|
return sceClibMspaceMemalign(this->m_data.cdramPool, align, size);
|
||||||
|
}
|
||||||
|
void GXMRenderer::FreeGpu(void* ptr) {
|
||||||
|
sceClibMspaceFree(this->m_data.cdramPool, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GXMRenderer::PushLights(const SceneLight* lightsArray, size_t count)
|
||||||
|
{
|
||||||
|
if (count > 3) {
|
||||||
|
SDL_Log("Unsupported number of lights (%d)", static_cast<int>(count));
|
||||||
|
count = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lights.assign(lightsArray, lightsArray + count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GXMRenderer::SetFrustumPlanes(const Plane* frustumPlanes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GXMRenderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
|
||||||
|
{
|
||||||
|
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
|
||||||
|
m_projection[1][1] *= -1.0f; // OpenGL is upside down
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TextureDestroyContextGLS2 {
|
||||||
|
GXMRenderer* renderer;
|
||||||
|
Uint32 textureId;
|
||||||
|
};
|
||||||
|
|
||||||
|
void GXMRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture)
|
||||||
|
{
|
||||||
|
auto* ctx = new TextureDestroyContextGLS2{this, id};
|
||||||
|
texture->AddDestroyCallback(
|
||||||
|
[](IDirect3DRMObject* obj, void* arg) {
|
||||||
|
auto* ctx = static_cast<TextureDestroyContextGLS2*>(arg);
|
||||||
|
auto& cache = ctx->renderer->m_textures[ctx->textureId];
|
||||||
|
void* textureData = sceGxmTextureGetData(&cache.gxmTexture);
|
||||||
|
ctx->renderer->FreeGpu(textureData);
|
||||||
|
delete ctx;
|
||||||
|
},
|
||||||
|
ctx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 GXMRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||||
|
{
|
||||||
|
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
|
||||||
|
auto surface = static_cast<DirectDrawSurfaceImpl*>(texture->m_surface);
|
||||||
|
|
||||||
|
for (Uint32 i = 0; i < m_textures.size(); ++i) {
|
||||||
|
auto& tex = m_textures[i];
|
||||||
|
if (tex.texture == texture) {
|
||||||
|
if (tex.version != texture->m_version) {
|
||||||
|
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888);
|
||||||
|
if (!surf) {
|
||||||
|
return NO_TEXTURE_ID;
|
||||||
|
}
|
||||||
|
void* textureData = sceGxmTextureGetData(&tex.gxmTexture);
|
||||||
|
memcpy(textureData, surf->pixels, surf->w*surf->h*4);
|
||||||
|
SDL_DestroySurface(surf);
|
||||||
|
tex.version = texture->m_version;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_ABGR8888);
|
||||||
|
if (!surf) {
|
||||||
|
return NO_TEXTURE_ID;
|
||||||
|
}
|
||||||
|
void* textureData = this->AllocateGpu(surf->w*surf->h*4, SCE_GXM_TEXTURE_ALIGNMENT);
|
||||||
|
memcpy(textureData, surf->pixels, surf->w*surf->h*4);
|
||||||
|
SDL_DestroySurface(surf);
|
||||||
|
|
||||||
|
SceGxmTexture gxmTexture;
|
||||||
|
sceGxmTextureInitLinear(&gxmTexture, textureData, SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_RGBA, surf->w, surf->h, 1);
|
||||||
|
sceGxmTextureSetMinFilter(&gxmTexture, SCE_GXM_TEXTURE_FILTER_LINEAR);
|
||||||
|
sceGxmTextureSetMagFilter(&gxmTexture, SCE_GXM_TEXTURE_FILTER_LINEAR);
|
||||||
|
|
||||||
|
for (Uint32 i = 0; i < m_textures.size(); ++i) {
|
||||||
|
auto& tex = m_textures[i];
|
||||||
|
if (!tex.texture) {
|
||||||
|
tex.texture = texture;
|
||||||
|
tex.version = texture->m_version;
|
||||||
|
tex.gxmTexture = gxmTexture;
|
||||||
|
AddTextureDestroyCallback(i, texture);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_textures.push_back({texture, texture->m_version, gxmTexture});
|
||||||
|
AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture);
|
||||||
|
return (Uint32) (m_textures.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GXMMeshCacheEntry GXMRenderer::GXMUploadMesh(const MeshGroup& meshGroup)
|
||||||
|
{
|
||||||
|
GXMMeshCacheEntry cache{&meshGroup, meshGroup.version};
|
||||||
|
|
||||||
|
cache.flat = meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT;
|
||||||
|
|
||||||
|
std::vector<D3DRMVERTEX> vertices;
|
||||||
|
std::vector<uint16_t> indices;
|
||||||
|
if (cache.flat) {
|
||||||
|
FlattenSurfaces(
|
||||||
|
meshGroup.vertices.data(),
|
||||||
|
meshGroup.vertices.size(),
|
||||||
|
meshGroup.indices.data(),
|
||||||
|
meshGroup.indices.size(),
|
||||||
|
meshGroup.texture != nullptr,
|
||||||
|
vertices,
|
||||||
|
indices
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vertices = meshGroup.vertices;
|
||||||
|
indices.resize(meshGroup.indices.size());
|
||||||
|
std::transform(meshGroup.indices.begin(), meshGroup.indices.end(), indices.begin(), [](DWORD index) {
|
||||||
|
return static_cast<uint16_t>(index);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t vertexBufferSize = sizeof(Vertex)*vertices.size();
|
||||||
|
size_t indexBufferSize = sizeof(uint16_t)*indices.size();
|
||||||
|
void* meshData = this->AllocateGpu(vertexBufferSize+indexBufferSize);
|
||||||
|
|
||||||
|
Vertex* vertexBuffer = (Vertex*)meshData;
|
||||||
|
uint16_t* indexBuffer = (uint16_t*)((uint8_t*)meshData + vertexBufferSize);
|
||||||
|
|
||||||
|
for(int i = 0; i < vertices.size(); i++) {
|
||||||
|
D3DRMVERTEX vertex = vertices.data()[i];
|
||||||
|
vertexBuffer[i] = Vertex{
|
||||||
|
.position = {
|
||||||
|
vertex.position.x,
|
||||||
|
vertex.position.y,
|
||||||
|
vertex.position.z,
|
||||||
|
},
|
||||||
|
.normal = {
|
||||||
|
vertex.normal.x,
|
||||||
|
vertex.normal.y,
|
||||||
|
vertex.normal.z,
|
||||||
|
},
|
||||||
|
.texCoord = {
|
||||||
|
vertex.tu,
|
||||||
|
vertex.tv,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
memcpy(indexBuffer, indices.data(), indices.size()*sizeof(uint16_t));
|
||||||
|
|
||||||
|
cache.meshData = meshData;
|
||||||
|
cache.vertexBuffer = vertexBuffer;
|
||||||
|
cache.indexBuffer = indexBuffer;
|
||||||
|
cache.indexCount = indices.size();
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GXMMeshDestroyContext {
|
||||||
|
GXMRenderer* renderer;
|
||||||
|
Uint32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
void GXMRenderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
|
||||||
|
{
|
||||||
|
auto* ctx = new GXMMeshDestroyContext{this, id};
|
||||||
|
mesh->AddDestroyCallback(
|
||||||
|
[](IDirect3DRMObject*, void* arg) {
|
||||||
|
auto* ctx = static_cast<GXMMeshDestroyContext*>(arg);
|
||||||
|
auto& cache = ctx->renderer->m_meshes[ctx->id];
|
||||||
|
cache.meshGroup = nullptr;
|
||||||
|
ctx->renderer->FreeGpu(cache.meshData);
|
||||||
|
delete ctx;
|
||||||
|
},
|
||||||
|
ctx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 GXMRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
|
||||||
|
{
|
||||||
|
for (Uint32 i = 0; i < m_meshes.size(); ++i) {
|
||||||
|
auto& cache = m_meshes[i];
|
||||||
|
if (cache.meshGroup == meshGroup) {
|
||||||
|
if (cache.version != meshGroup->version) {
|
||||||
|
cache = std::move(this->GXMUploadMesh(*meshGroup));
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto newCache = this->GXMUploadMesh(*meshGroup);
|
||||||
|
|
||||||
|
for (Uint32 i = 0; i < m_meshes.size(); ++i) {
|
||||||
|
auto& cache = m_meshes[i];
|
||||||
|
if (!cache.meshGroup) {
|
||||||
|
cache = std::move(newCache);
|
||||||
|
AddMeshDestroyCallback(i, mesh);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_meshes.push_back(std::move(newCache));
|
||||||
|
AddMeshDestroyCallback((Uint32) (m_meshes.size() - 1), mesh);
|
||||||
|
return (Uint32) (m_meshes.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD GXMRenderer::GetWidth()
|
||||||
|
{
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD GXMRenderer::GetHeight()
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GXMRenderer::GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc)
|
||||||
|
{
|
||||||
|
halDesc->dcmColorModel = D3DCOLORMODEL::RGB;
|
||||||
|
halDesc->dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
|
||||||
|
halDesc->dwDeviceZBufferBitDepth = DDBD_16;
|
||||||
|
halDesc->dwDeviceZBufferBitDepth |= DDBD_32;
|
||||||
|
helDesc->dwDeviceRenderBitDepth = DDBD_32;
|
||||||
|
halDesc->dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
||||||
|
halDesc->dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
||||||
|
halDesc->dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
||||||
|
|
||||||
|
memset(helDesc, 0, sizeof(D3DDEVICEDESC));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GXMRenderer::GetName()
|
||||||
|
{
|
||||||
|
return "GXM";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool razor_triggered = false;
|
||||||
|
|
||||||
|
HRESULT GXMRenderer::BeginFrame()
|
||||||
|
{
|
||||||
|
SDL_Log("GXMRenderer::BeginFrame");
|
||||||
|
|
||||||
|
if(with_razor && !razor_triggered) {
|
||||||
|
SDL_Log("trigger razor for next frame");
|
||||||
|
sceRazorGpuCaptureSetTriggerNextFrame("ux0:/data/capture.sgx");
|
||||||
|
razor_triggered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sceGxmBeginScene(
|
||||||
|
this->m_data.context,
|
||||||
|
0,
|
||||||
|
this->m_data.renderTarget,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
this->m_data.renderBufferSync,
|
||||||
|
&this->m_data.renderSurface,
|
||||||
|
&this->m_data.depthSurface
|
||||||
|
);
|
||||||
|
|
||||||
|
sceGxmSetViewport(this->m_data.context, 0, m_width, 0, m_height, 0, 0);
|
||||||
|
|
||||||
|
// clear screen
|
||||||
|
sceGxmSetVertexProgram(this->m_data.context, this->m_data.clearVertexProgram);
|
||||||
|
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.clearFragmentProgram);
|
||||||
|
sceGxmSetVertexStream(this->m_data.context, 0, this->m_data.clearVerticies);
|
||||||
|
sceGxmDraw(
|
||||||
|
this->m_data.context,
|
||||||
|
SCE_GXM_PRIMITIVE_TRIANGLES,
|
||||||
|
SCE_GXM_INDEX_FORMAT_U16,
|
||||||
|
this->m_data.clearIndicies, 3
|
||||||
|
);
|
||||||
|
|
||||||
|
// set light data
|
||||||
|
int lightCount = std::min(static_cast<int>(m_lights.size()), 3);
|
||||||
|
|
||||||
|
SceneLightGXM* lightData = (SceneLightGXM*)this->m_data.lightDataBuffer;
|
||||||
|
int* pLightCount = (int*)((uint8_t*)(this->m_data.lightDataBuffer)+sizeof(SceneLightGXM)*3);
|
||||||
|
*pLightCount = lightCount;
|
||||||
|
|
||||||
|
for (int i = 0; i < lightCount; ++i) {
|
||||||
|
const auto& src = m_lights[i];
|
||||||
|
lightData[i].color[0] = src.color.r;
|
||||||
|
lightData[i].color[1] = src.color.g;
|
||||||
|
lightData[i].color[2] = src.color.b;
|
||||||
|
lightData[i].color[3] = src.color.a;
|
||||||
|
|
||||||
|
lightData[i].position[0] = src.position.x;
|
||||||
|
lightData[i].position[1] = src.position.y;
|
||||||
|
lightData[i].position[2] = src.position.z;
|
||||||
|
lightData[i].position[3] = src.positional;
|
||||||
|
|
||||||
|
lightData[i].direction[0] = src.direction.x;
|
||||||
|
lightData[i].direction[1] = src.direction.y;
|
||||||
|
lightData[i].direction[2] = src.direction.z;
|
||||||
|
lightData[i].direction[3] = src.directional;
|
||||||
|
}
|
||||||
|
|
||||||
|
sceGxmSetVertexProgram(this->m_data.context, this->m_data.mainVertexProgram);
|
||||||
|
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.opaqueFragmentProgram);
|
||||||
|
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GXMRenderer::EnableTransparency()
|
||||||
|
{
|
||||||
|
sceGxmSetFragmentProgram(this->m_data.context, this->m_data.transparentFragmentProgram);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_UNIFORM(buffer, param, value) \
|
||||||
|
do { \
|
||||||
|
size_t __offset = sceGxmProgramParameterGetResourceIndex(param); \
|
||||||
|
void* __dst = (uint8_t*)(buffer) + (__offset * sizeof(uint32_t)); \
|
||||||
|
memcpy(__dst, reinterpret_cast<const void*>(&(value)), sizeof(value)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
void TransposeD3DRMMATRIX4D(const D3DRMMATRIX4D input, D3DRMMATRIX4D output) {
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
for (int j = 0; j < 4; ++j) {
|
||||||
|
output[j][i] = input[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GXMRenderer::SubmitDraw(
|
||||||
|
DWORD meshId,
|
||||||
|
const D3DRMMATRIX4D& modelViewMatrix,
|
||||||
|
const Matrix3x3& normalMatrix,
|
||||||
|
const Appearance& appearance
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto& mesh = m_meshes[meshId];
|
||||||
|
|
||||||
|
void* vertUniforms;
|
||||||
|
void* fragUniforms;
|
||||||
|
sceGxmReserveVertexDefaultUniformBuffer(this->m_data.context, &vertUniforms);
|
||||||
|
sceGxmReserveFragmentDefaultUniformBuffer(this->m_data.context, &fragUniforms);
|
||||||
|
|
||||||
|
SET_UNIFORM(vertUniforms, this->m_data.uModelViewMatrixParam, modelViewMatrix);
|
||||||
|
SET_UNIFORM(vertUniforms, this->m_data.uNormalMatrixParam, normalMatrix);
|
||||||
|
SET_UNIFORM(vertUniforms, this->m_data.uProjectionMatrixParam, m_projection);
|
||||||
|
|
||||||
|
float color[4] = {
|
||||||
|
appearance.color.r / 255.0f,
|
||||||
|
appearance.color.g / 255.0f,
|
||||||
|
appearance.color.b / 255.0f,
|
||||||
|
appearance.color.a / 255.0f
|
||||||
|
};
|
||||||
|
SET_UNIFORM(fragUniforms, this->m_data.uColor, color);
|
||||||
|
SET_UNIFORM(fragUniforms, this->m_data.uShininess, appearance.shininess);
|
||||||
|
|
||||||
|
int useTexture = appearance.textureId != NO_TEXTURE_ID ? 1 : 0;
|
||||||
|
SET_UNIFORM(fragUniforms, this->m_data.uUseTexture, useTexture);
|
||||||
|
if(useTexture) {
|
||||||
|
auto& texture = m_textures[appearance.textureId];
|
||||||
|
sceGxmSetFragmentTexture(this->m_data.context, 0, &texture.gxmTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
sceGxmSetVertexStream(this->m_data.context, 0, mesh.vertexBuffer);
|
||||||
|
sceGxmDraw(
|
||||||
|
this->m_data.context,
|
||||||
|
SCE_GXM_PRIMITIVE_TRIANGLES,
|
||||||
|
SCE_GXM_INDEX_FORMAT_U16,
|
||||||
|
mesh.indexBuffer,
|
||||||
|
mesh.indexCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT GXMRenderer::FinalizeFrame()
|
||||||
|
{
|
||||||
|
sceGxmEndScene(
|
||||||
|
this->m_data.context,
|
||||||
|
nullptr, nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
SDL_Surface* renderedImage = SDL_CreateSurfaceFrom(
|
||||||
|
m_width, m_height, SDL_PIXELFORMAT_ABGR8888,
|
||||||
|
this->m_data.renderBuffer, this->m_width*4
|
||||||
|
);
|
||||||
|
SDL_BlitSurface(renderedImage, nullptr, DDBackBuffer, nullptr);
|
||||||
|
SDL_DestroySurface(renderedImage);
|
||||||
|
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
24
miniwin/src/d3drm/backends/gxm/utils.h
Normal file
24
miniwin/src/d3drm/backends/gxm/utils.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL3/SDL_log.h>
|
||||||
|
|
||||||
|
static bool _sce_err(const char* expr, int err) {
|
||||||
|
if(err >= 0) {
|
||||||
|
SDL_Log("sce: %s", expr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SDL_Log("SCE_ERR: %s failed 0x%x", expr, err);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SCE_ERR(func, ...) _sce_err(#func, func(__VA_ARGS__))
|
||||||
|
|
||||||
|
#define ALIGN(x, a) (((x) + ((a)-1)) & ~((a)-1))
|
||||||
|
|
||||||
|
#define INCBIN(filename, symbol) \
|
||||||
|
__asm__( \
|
||||||
|
".balign 16 \n" \
|
||||||
|
#symbol ":" \
|
||||||
|
".incbin \"" filename "\"" \
|
||||||
|
); \
|
||||||
|
extern const void* symbol
|
||||||
@ -16,6 +16,9 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "d3drmrenderer_directx9.h"
|
#include "d3drmrenderer_directx9.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __vita__
|
||||||
|
#include "d3drmrenderer_gxm.h"
|
||||||
|
#endif
|
||||||
#include "d3drmrenderer_sdl3gpu.h"
|
#include "d3drmrenderer_sdl3gpu.h"
|
||||||
#include "d3drmrenderer_software.h"
|
#include "d3drmrenderer_software.h"
|
||||||
#include "d3drmtexture_impl.h"
|
#include "d3drmtexture_impl.h"
|
||||||
@ -164,6 +167,11 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface(
|
|||||||
else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) {
|
else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) {
|
||||||
renderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
renderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __vita__
|
||||||
|
else if (SDL_memcmp(&guid, &GXM_GUID, sizeof(GUID)) == 0) {
|
||||||
|
renderer = GXMRenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized");
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized");
|
||||||
|
|||||||
@ -7,6 +7,9 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "d3drmrenderer_directx9.h"
|
#include "d3drmrenderer_directx9.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __vita__
|
||||||
|
#include "d3drmrenderer_gxm.h"
|
||||||
|
#endif
|
||||||
#include "d3drmrenderer_sdl3gpu.h"
|
#include "d3drmrenderer_sdl3gpu.h"
|
||||||
#include "d3drmrenderer_software.h"
|
#include "d3drmrenderer_software.h"
|
||||||
#include "ddpalette_impl.h"
|
#include "ddpalette_impl.h"
|
||||||
@ -222,15 +225,20 @@ void EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx, Direct3DRMRenderer* devi
|
|||||||
|
|
||||||
HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
||||||
{
|
{
|
||||||
|
#ifndef __vita__
|
||||||
Direct3DRMSDL3GPU_EnumDevice(cb, ctx);
|
Direct3DRMSDL3GPU_EnumDevice(cb, ctx);
|
||||||
|
#endif
|
||||||
#ifdef USE_OPENGLES2
|
#ifdef USE_OPENGLES2
|
||||||
OpenGLES2Renderer_EnumDevice(cb, ctx);
|
//OpenGLES2Renderer_EnumDevice(cb, ctx);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_OPENGL1
|
#ifdef USE_OPENGL1
|
||||||
OpenGL1Renderer_EnumDevice(cb, ctx);
|
OpenGL1Renderer_EnumDevice(cb, ctx);
|
||||||
#endif
|
#endif
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DirectX9Renderer_EnumDevice(cb, ctx);
|
DirectX9Renderer_EnumDevice(cb, ctx);
|
||||||
|
#endif
|
||||||
|
#ifdef __vita__
|
||||||
|
//GXMRenderer_EnumDevice(cb, ctx);
|
||||||
#endif
|
#endif
|
||||||
Direct3DRMSoftware_EnumDevice(cb, ctx);
|
Direct3DRMSoftware_EnumDevice(cb, ctx);
|
||||||
|
|
||||||
@ -296,8 +304,7 @@ HRESULT DirectDrawImpl::SetCooperativeLevel(HWND hWnd, DDSCLFlags dwFlags)
|
|||||||
return DDERR_INVALIDPARAMS;
|
return DDERR_INVALIDPARAMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__vita__) && defined(USE_OPENGLES2)
|
||||||
#ifdef __vita__
|
|
||||||
const char* sdlRendererName = "opengles2";
|
const char* sdlRendererName = "opengles2";
|
||||||
#else
|
#else
|
||||||
const char* sdlRendererName = nullptr;
|
const char* sdlRendererName = nullptr;
|
||||||
@ -350,6 +357,11 @@ HRESULT DirectDrawImpl::CreateDevice(
|
|||||||
else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) {
|
else if (SDL_memcmp(&guid, &DirectX9_GUID, sizeof(GUID)) == 0) {
|
||||||
renderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
renderer = DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef __vita__
|
||||||
|
else if (SDL_memcmp(&guid, &GXM_GUID, sizeof(GUID)) == 0) {
|
||||||
|
renderer = GXMRenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (SDL_memcmp(&guid, &SOFTWARE_GUID, sizeof(GUID)) == 0) {
|
else if (SDL_memcmp(&guid, &SOFTWARE_GUID, sizeof(GUID)) == 0) {
|
||||||
renderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
renderer = new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||||
|
|||||||
167
miniwin/src/internal/d3drmrenderer_gxm.h
Normal file
167
miniwin/src/internal/d3drmrenderer_gxm.h
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "d3drmrenderer.h"
|
||||||
|
#include "d3drmtexture_impl.h"
|
||||||
|
#include "ddraw_impl.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <psp2/gxm.h>
|
||||||
|
#include <psp2/types.h>
|
||||||
|
#include <psp2/kernel/clib.h>
|
||||||
|
|
||||||
|
DEFINE_GUID(GXM_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x58, 0x4D);
|
||||||
|
|
||||||
|
#define VITA_GXM_DISPLAY_BUFFER_COUNT 2
|
||||||
|
|
||||||
|
struct GXMTextureCacheEntry {
|
||||||
|
IDirect3DRMTexture* texture;
|
||||||
|
Uint32 version;
|
||||||
|
SceGxmTexture gxmTexture;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GXMMeshCacheEntry {
|
||||||
|
const MeshGroup* meshGroup;
|
||||||
|
int version;
|
||||||
|
bool flat;
|
||||||
|
|
||||||
|
void* meshData;
|
||||||
|
void* vertexBuffer;
|
||||||
|
void* indexBuffer;
|
||||||
|
uint16_t indexCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct GXMRendererInit {
|
||||||
|
SceGxmContext* context;
|
||||||
|
SceGxmShaderPatcher* shaderPatcher;
|
||||||
|
SceClibMspace gpuPool;
|
||||||
|
} GXMRendererInit;
|
||||||
|
|
||||||
|
typedef struct GXMRendererData {
|
||||||
|
SceUID vdmRingBufferUid;
|
||||||
|
SceUID vertexRingBufferUid;
|
||||||
|
SceUID fragmentRingBufferUid;
|
||||||
|
SceUID fragmentUsseRingBufferUid;
|
||||||
|
size_t fragmentUsseRingBufferOffset;
|
||||||
|
|
||||||
|
void* vdmRingBuffer;
|
||||||
|
void* vertexRingBuffer;
|
||||||
|
void* fragmentRingBuffer;
|
||||||
|
void* fragmentUsseRingBuffer;
|
||||||
|
|
||||||
|
SceClibMspace cdramPool;
|
||||||
|
|
||||||
|
void* contextHostMem;
|
||||||
|
SceGxmContext* context;
|
||||||
|
|
||||||
|
SceGxmRenderTarget* renderTarget;
|
||||||
|
SceUID renderBufferUid;
|
||||||
|
void* renderBuffer;
|
||||||
|
SceGxmColorSurface renderSurface;
|
||||||
|
SceGxmSyncObject* renderBufferSync;
|
||||||
|
|
||||||
|
SceUID depthBufferUid;
|
||||||
|
void* depthBufferData;
|
||||||
|
SceUID stencilBufferUid;
|
||||||
|
void* stencilBufferData;
|
||||||
|
SceGxmDepthStencilSurface depthSurface;
|
||||||
|
|
||||||
|
SceUID patcherBufferUid;
|
||||||
|
void* patcherBuffer;
|
||||||
|
|
||||||
|
SceUID patcherVertexUsseUid;
|
||||||
|
size_t patcherVertexUsseOffset;
|
||||||
|
void* patcherVertexUsse;
|
||||||
|
|
||||||
|
SceUID patcherFragmentUsseUid;
|
||||||
|
size_t patcherFragmentUsseOffset;
|
||||||
|
void* patcherFragmentUsse;
|
||||||
|
|
||||||
|
SceGxmShaderPatcher* shaderPatcher;
|
||||||
|
|
||||||
|
SceGxmShaderPatcherId clearVertexProgramId;
|
||||||
|
SceGxmVertexProgram* clearVertexProgram;
|
||||||
|
SceGxmShaderPatcherId clearFragmentProgramId;
|
||||||
|
SceGxmFragmentProgram* clearFragmentProgram;
|
||||||
|
|
||||||
|
SceGxmShaderPatcherId mainVertexProgramId;
|
||||||
|
SceGxmShaderPatcherId mainFragmentProgramId;
|
||||||
|
SceGxmVertexProgram* mainVertexProgram;
|
||||||
|
SceGxmFragmentProgram* opaqueFragmentProgram;
|
||||||
|
SceGxmFragmentProgram* transparentFragmentProgram;
|
||||||
|
|
||||||
|
const SceGxmProgramParameter* uModelViewMatrixParam;
|
||||||
|
const SceGxmProgramParameter* uNormalMatrixParam;
|
||||||
|
const SceGxmProgramParameter* uProjectionMatrixParam;
|
||||||
|
|
||||||
|
const SceGxmProgramParameter* uLights;
|
||||||
|
const SceGxmProgramParameter* uLightCount;
|
||||||
|
const SceGxmProgramParameter* uShininess;
|
||||||
|
const SceGxmProgramParameter* uColor;
|
||||||
|
const SceGxmProgramParameter* uUseTexture;
|
||||||
|
|
||||||
|
void* clearMeshBuffer;
|
||||||
|
float* clearVerticies;
|
||||||
|
uint16_t* clearIndicies;
|
||||||
|
|
||||||
|
void* lightDataBuffer;
|
||||||
|
} GXMRendererData;
|
||||||
|
|
||||||
|
class GXMRenderer : public Direct3DRMRenderer {
|
||||||
|
public:
|
||||||
|
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
||||||
|
GXMRenderer(
|
||||||
|
DWORD width,
|
||||||
|
DWORD height,
|
||||||
|
GXMRendererData data
|
||||||
|
);
|
||||||
|
GXMRenderer(int forEnum) {};
|
||||||
|
~GXMRenderer() override;
|
||||||
|
|
||||||
|
void PushLights(const SceneLight* lightsArray, size_t count) override;
|
||||||
|
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||||
|
void SetFrustumPlanes(const Plane* frustumPlanes) override;
|
||||||
|
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||||
|
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||||
|
DWORD GetWidth() override;
|
||||||
|
DWORD GetHeight() override;
|
||||||
|
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||||
|
const char* GetName() override;
|
||||||
|
HRESULT BeginFrame() override;
|
||||||
|
void EnableTransparency() override;
|
||||||
|
void SubmitDraw(
|
||||||
|
DWORD meshId,
|
||||||
|
const D3DRMMATRIX4D& modelViewMatrix,
|
||||||
|
const Matrix3x3& normalMatrix,
|
||||||
|
const Appearance& appearance
|
||||||
|
) override;
|
||||||
|
HRESULT FinalizeFrame() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||||
|
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
||||||
|
|
||||||
|
void* AllocateGpu(size_t size, size_t align = 4);
|
||||||
|
void FreeGpu(void* ptr);
|
||||||
|
|
||||||
|
GXMMeshCacheEntry GXMUploadMesh(const MeshGroup& meshGroup);
|
||||||
|
|
||||||
|
std::vector<GXMTextureCacheEntry> m_textures;
|
||||||
|
std::vector<GXMMeshCacheEntry> m_meshes;
|
||||||
|
D3DRMMATRIX4D m_projection;
|
||||||
|
DWORD m_width, m_height;
|
||||||
|
std::vector<SceneLight> m_lights;
|
||||||
|
|
||||||
|
GXMRendererData m_data;
|
||||||
|
bool m_initialized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline static void GXMRenderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
||||||
|
{
|
||||||
|
Direct3DRMRenderer* device = new GXMRenderer(1);
|
||||||
|
if (device) {
|
||||||
|
EnumDevice(cb, ctx, device, GXM_GUID);
|
||||||
|
delete device;
|
||||||
|
}
|
||||||
|
}
|
||||||
413
sdl3.patch
Normal file
413
sdl3.patch
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
diff --git a/include/SDL3/SDL_gxm.h b/include/SDL3/SDL_gxm.h
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..1a80e2664
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/SDL3/SDL_gxm.h
|
||||||
|
@@ -0,0 +1,33 @@
|
||||||
|
+#ifndef SDL_gxm_h_
|
||||||
|
+#define SDL_gxm_h_
|
||||||
|
+
|
||||||
|
+#include <SDL3/SDL_stdinc.h>
|
||||||
|
+#include <SDL3/SDL_error.h>
|
||||||
|
+
|
||||||
|
+#include <psp2/gxm.h>
|
||||||
|
+#include <psp2/kernel/clib.h>
|
||||||
|
+
|
||||||
|
+#include <SDL3/SDL_begin_code.h>
|
||||||
|
+/* Set up for C function definitions, even when using C++ */
|
||||||
|
+#ifdef __cplusplus
|
||||||
|
+extern "C" {
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ void *address;
|
||||||
|
+ Uint8 wait_vblank;
|
||||||
|
+} VITA_GXM_DisplayData;
|
||||||
|
+
|
||||||
|
+extern SceClibMspace SDL_gxm_get_cdramPool();
|
||||||
|
+
|
||||||
|
+extern int SDL_gxm_init();
|
||||||
|
+extern bool SDL_gxm_is_init();
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Ends C function definitions when using C++ */
|
||||||
|
+#ifdef __cplusplus
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+#include <SDL3/SDL_close_code.h>
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/src/SDL_error.c b/src/SDL_error.c
|
||||||
|
index 3f4273b4f..e41b8d81b 100644
|
||||||
|
--- a/src/SDL_error.c
|
||||||
|
+++ b/src/SDL_error.c
|
||||||
|
@@ -66,7 +66,7 @@ bool SDL_SetErrorV(SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap)
|
||||||
|
// Enable this if you want to see all errors printed as they occur.
|
||||||
|
// Note that there are many recoverable errors that may happen internally and
|
||||||
|
// can be safely ignored if the public API doesn't return an error code.
|
||||||
|
-#if 0
|
||||||
|
+#if 1
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "%s", error->str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
|
||||||
|
index 0a088a8b4..cace29340 100644
|
||||||
|
--- a/src/render/SDL_render.c
|
||||||
|
+++ b/src/render/SDL_render.c
|
||||||
|
@@ -2871,7 +2871,7 @@ static void SDL_RenderLogicalPresentation(SDL_Renderer *renderer)
|
||||||
|
|
||||||
|
// now set everything back.
|
||||||
|
view->logical_presentation_mode = mode;
|
||||||
|
- SDL_SetRenderViewport(renderer, &orig_viewport);
|
||||||
|
+ //SDL_SetRenderViewport(renderer, &orig_viewport);
|
||||||
|
if (clipping_enabled) {
|
||||||
|
SDL_SetRenderClipRect(renderer, &orig_cliprect);
|
||||||
|
}
|
||||||
|
@@ -3040,7 +3040,7 @@ bool SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect)
|
||||||
|
SDL_RenderViewState *view = renderer->view;
|
||||||
|
if (rect) {
|
||||||
|
if ((rect->w < 0) || (rect->h < 0)) {
|
||||||
|
- return SDL_SetError("rect has a negative size");
|
||||||
|
+ return SDL_SetError("rect has a negative size %d %d", rect->w, rect->h);
|
||||||
|
}
|
||||||
|
SDL_copyp(&view->viewport, rect);
|
||||||
|
} else {
|
||||||
|
diff --git a/src/render/opengles2/SDL_shaders_gles2.c b/src/render/opengles2/SDL_shaders_gles2.c
|
||||||
|
index 3bff21178..0b6dace68 100644
|
||||||
|
--- a/src/render/opengles2/SDL_shaders_gles2.c
|
||||||
|
+++ b/src/render/opengles2/SDL_shaders_gles2.c
|
||||||
|
@@ -130,9 +130,7 @@ static const char GLES2_Fragment_TextureARGB[] =
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" mediump vec4 color = texture2D(u_texture, v_texCoord);\n"
|
||||||
|
-" gl_FragColor = color;\n"
|
||||||
|
-" gl_FragColor.r = color.b;\n"
|
||||||
|
-" gl_FragColor.b = color.r;\n"
|
||||||
|
+" gl_FragColor.rgba = color.bgra;\n"
|
||||||
|
" gl_FragColor *= v_color;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
@@ -144,9 +142,7 @@ static const char GLES2_Fragment_TextureRGB[] =
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" mediump vec4 color = texture2D(u_texture, v_texCoord);\n"
|
||||||
|
-" gl_FragColor = color;\n"
|
||||||
|
-" gl_FragColor.r = color.b;\n"
|
||||||
|
-" gl_FragColor.b = color.r;\n"
|
||||||
|
+" gl_FragColor.rgb = color.bgr;\n"
|
||||||
|
" gl_FragColor.a = 1.0;\n"
|
||||||
|
" gl_FragColor *= v_color;\n"
|
||||||
|
"}\n"
|
||||||
|
@@ -183,9 +179,7 @@ static const char GLES2_Fragment_TextureARGB_PixelArt[] =
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
RGB_PIXELART_GETCOLOR
|
||||||
|
-" gl_FragColor = color;\n"
|
||||||
|
-" gl_FragColor.r = color.b;\n"
|
||||||
|
-" gl_FragColor.b = color.r;\n"
|
||||||
|
+" gl_FragColor.rgba = color.bgra;\n"
|
||||||
|
" gl_FragColor *= v_color;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
@@ -197,9 +191,7 @@ static const char GLES2_Fragment_TextureRGB_PixelArt[] =
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
RGB_PIXELART_GETCOLOR
|
||||||
|
-" gl_FragColor = color;\n"
|
||||||
|
-" gl_FragColor.r = color.b;\n"
|
||||||
|
-" gl_FragColor.b = color.r;\n"
|
||||||
|
+" gl_FragColor.rgb = color.bgr;\n"
|
||||||
|
" gl_FragColor.a = 1.0;\n"
|
||||||
|
" gl_FragColor *= v_color;\n"
|
||||||
|
"}\n"
|
||||||
|
diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c
|
||||||
|
index 039155b73..dc1640634 100644
|
||||||
|
--- a/src/render/vitagxm/SDL_render_vita_gxm.c
|
||||||
|
+++ b/src/render/vitagxm/SDL_render_vita_gxm.c
|
||||||
|
@@ -1197,6 +1197,11 @@ static bool VITA_GXM_RenderPresent(SDL_Renderer *renderer)
|
||||||
|
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal;
|
||||||
|
SceCommonDialogUpdateParam updateParam;
|
||||||
|
|
||||||
|
+ uint32_t* pixels = data->displayBufferData[data->backBufferIndex];
|
||||||
|
+ for(int i = 0; i < 10*960; i++) {
|
||||||
|
+ pixels[i] = 0xffffffff;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
data->displayData.address = data->displayBufferData[data->backBufferIndex];
|
||||||
|
|
||||||
|
SDL_memset(&updateParam, 0, sizeof(updateParam));
|
||||||
|
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_memory.c b/src/render/vitagxm/SDL_render_vita_gxm_memory.c
|
||||||
|
index e37a345c3..1a3904433 100644
|
||||||
|
--- a/src/render/vitagxm/SDL_render_vita_gxm_memory.c
|
||||||
|
+++ b/src/render/vitagxm/SDL_render_vita_gxm_memory.c
|
||||||
|
@@ -25,6 +25,9 @@
|
||||||
|
|
||||||
|
#include "SDL_render_vita_gxm_memory.h"
|
||||||
|
|
||||||
|
+static SceUID cdramPoolUID = -1;
|
||||||
|
+static SceClibMspace cdramPool = NULL;
|
||||||
|
+
|
||||||
|
void *vita_mem_alloc(unsigned int type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid)
|
||||||
|
{
|
||||||
|
void *mem;
|
||||||
|
@@ -64,61 +67,70 @@ void vita_mem_free(SceUID uid)
|
||||||
|
sceKernelFreeMemBlock(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size)
|
||||||
|
-{
|
||||||
|
- void *mem;
|
||||||
|
+static bool cdramPool_init() {
|
||||||
|
+ if(cdramPool) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ int poolsize;
|
||||||
|
+ int ret;
|
||||||
|
+ void* mem;
|
||||||
|
+ 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);
|
||||||
|
+ }
|
||||||
|
+ poolsize -= 16 * 1024 * 1024;
|
||||||
|
+ cdramPoolUID = sceKernelAllocMemBlock("gpu_cdram_pool", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, poolsize, NULL);
|
||||||
|
+ if (cdramPool < 0) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (!data->texturePool) {
|
||||||
|
- int poolsize;
|
||||||
|
- int ret;
|
||||||
|
- SceKernelFreeMemorySizeInfo info;
|
||||||
|
- info.size = sizeof(SceKernelFreeMemorySizeInfo);
|
||||||
|
- sceKernelGetFreeMemorySize(&info);
|
||||||
|
+ ret = sceKernelGetMemBlockBase(cdramPoolUID, &mem);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ cdramPool = sceClibMspaceCreate(mem, poolsize);
|
||||||
|
|
||||||
|
- 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;
|
||||||
|
- }
|
||||||
|
+ if (!cdramPool) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ ret = sceGxmMapMemory(mem, poolsize, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
|
||||||
|
- ret = sceKernelGetMemBlockBase(data->texturePoolUID, &mem);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
- data->texturePool = sceClibMspaceCreate(mem, poolsize);
|
||||||
|
+SceClibMspace SDL_gxm_get_cdramPool() {
|
||||||
|
+ cdramPool_init();
|
||||||
|
+ return cdramPool;
|
||||||
|
+}
|
||||||
|
|
||||||
|
- if (!data->texturePool) {
|
||||||
|
- 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_alloc(VITA_GXM_RenderData *data, unsigned int alignment, unsigned int size)
|
||||||
|
+{
|
||||||
|
+ cdramPool_init();
|
||||||
|
+ return sceClibMspaceMemalign(cdramPool, alignment, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vita_gpu_mem_free(VITA_GXM_RenderData *data, void *ptr)
|
||||||
|
{
|
||||||
|
- if (data->texturePool) {
|
||||||
|
- sceClibMspaceFree(data->texturePool, ptr);
|
||||||
|
- }
|
||||||
|
+ sceClibMspaceFree(cdramPool, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vita_gpu_mem_destroy(VITA_GXM_RenderData *data)
|
||||||
|
{
|
||||||
|
void *mem = NULL;
|
||||||
|
- if (data->texturePool) {
|
||||||
|
- sceClibMspaceDestroy(data->texturePool);
|
||||||
|
- data->texturePool = NULL;
|
||||||
|
- if (sceKernelGetMemBlockBase(data->texturePoolUID, &mem) < 0) {
|
||||||
|
+ if (cdramPool) {
|
||||||
|
+ sceClibMspaceDestroy(cdramPool);
|
||||||
|
+ cdramPool = NULL;
|
||||||
|
+ if (sceKernelGetMemBlockBase(cdramPoolUID, &mem) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sceGxmUnmapMemory(mem);
|
||||||
|
- sceKernelFreeMemBlock(data->texturePoolUID);
|
||||||
|
+ sceKernelFreeMemBlock(cdramPoolUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_memory.h b/src/render/vitagxm/SDL_render_vita_gxm_memory.h
|
||||||
|
index cc548b3ba..18d011c8b 100644
|
||||||
|
--- a/src/render/vitagxm/SDL_render_vita_gxm_memory.h
|
||||||
|
+++ b/src/render/vitagxm/SDL_render_vita_gxm_memory.h
|
||||||
|
@@ -31,7 +31,7 @@
|
||||||
|
|
||||||
|
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_alloc(VITA_GXM_RenderData *data, unsigned int alignment, 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);
|
||||||
|
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/src/render/vitagxm/SDL_render_vita_gxm_tools.c
|
||||||
|
index 48af7b8f6..b12a5bfd9 100644
|
||||||
|
--- a/src/render/vitagxm/SDL_render_vita_gxm_tools.c
|
||||||
|
+++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.c
|
||||||
|
@@ -291,6 +291,38 @@ void unset_clip_rectangle(VITA_GXM_RenderData *data)
|
||||||
|
0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool gxm_initialized = false;
|
||||||
|
+
|
||||||
|
+bool SDL_gxm_is_init() {
|
||||||
|
+ return gxm_initialized;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+__weak_symbol void load_razor() {}
|
||||||
|
+
|
||||||
|
+int SDL_gxm_init() {
|
||||||
|
+ if(gxm_initialized) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ load_razor();
|
||||||
|
+
|
||||||
|
+ SceGxmInitializeParams initializeParams;
|
||||||
|
+ SDL_memset(&initializeParams, 0, sizeof(SceGxmInitializeParams));
|
||||||
|
+ initializeParams.flags = 0;
|
||||||
|
+ initializeParams.displayQueueMaxPendingCount = VITA_GXM_PENDING_SWAPS;
|
||||||
|
+ initializeParams.displayQueueCallback = display_callback;
|
||||||
|
+ initializeParams.displayQueueCallbackDataSize = sizeof(VITA_GXM_DisplayData);
|
||||||
|
+ initializeParams.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE;
|
||||||
|
+
|
||||||
|
+ int err = sceGxmInitialize(&initializeParams);
|
||||||
|
+ if (err != 0) {
|
||||||
|
+ SDL_LogError(SDL_LOG_CATEGORY_RENDER, "gxm init failed: %d", err);
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+ gxm_initialized = true;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int gxm_init(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
unsigned int i, x, y;
|
||||||
|
@@ -376,18 +408,8 @@ int gxm_init(SDL_Renderer *renderer)
|
||||||
|
|
||||||
|
VITA_GXM_RenderData *data = (VITA_GXM_RenderData *)renderer->internal;
|
||||||
|
|
||||||
|
- SceGxmInitializeParams initializeParams;
|
||||||
|
- SDL_memset(&initializeParams, 0, sizeof(SceGxmInitializeParams));
|
||||||
|
- initializeParams.flags = 0;
|
||||||
|
- initializeParams.displayQueueMaxPendingCount = VITA_GXM_PENDING_SWAPS;
|
||||||
|
- initializeParams.displayQueueCallback = display_callback;
|
||||||
|
- initializeParams.displayQueueCallbackDataSize = sizeof(VITA_GXM_DisplayData);
|
||||||
|
- initializeParams.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE;
|
||||||
|
-
|
||||||
|
- err = sceGxmInitialize(&initializeParams);
|
||||||
|
-
|
||||||
|
- if (err != 0) {
|
||||||
|
- SDL_LogError(SDL_LOG_CATEGORY_RENDER, "gxm init failed: %d", err);
|
||||||
|
+ err = SDL_gxm_init();
|
||||||
|
+ if(err != 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -464,6 +486,10 @@ int gxm_init(SDL_Renderer *renderer)
|
||||||
|
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
|
||||||
|
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||||
|
&data->displayBufferUid[i]);
|
||||||
|
+ if(!data->displayBufferData[i]) {
|
||||||
|
+ SDL_Log("failed to allocate display buffer");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
// SDL_memset the buffer to black
|
||||||
|
for (y = 0; y < VITA_GXM_SCREEN_HEIGHT; y++) {
|
||||||
|
@@ -535,7 +561,6 @@ int gxm_init(SDL_Renderer *renderer)
|
||||||
|
SCE_GXM_STENCIL_OP_KEEP,
|
||||||
|
0xFF,
|
||||||
|
0xFF);
|
||||||
|
-
|
||||||
|
// allocate memory for buffers and USSE code
|
||||||
|
patcherBuffer = vita_mem_alloc(
|
||||||
|
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
|
||||||
|
@@ -1012,6 +1037,7 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig
|
||||||
|
// Allocate a GPU buffer for the texture
|
||||||
|
texture_data = vita_gpu_mem_alloc(
|
||||||
|
data,
|
||||||
|
+ SCE_GXM_TEXTURE_ALIGNMENT,
|
||||||
|
tex_size);
|
||||||
|
|
||||||
|
// Try SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE in case we're out of VRAM
|
||||||
|
diff --git a/src/render/vitagxm/SDL_render_vita_gxm_types.h b/src/render/vitagxm/SDL_render_vita_gxm_types.h
|
||||||
|
index 6fc2c9e81..06ccecc91 100644
|
||||||
|
--- a/src/render/vitagxm/SDL_render_vita_gxm_types.h
|
||||||
|
+++ b/src/render/vitagxm/SDL_render_vita_gxm_types.h
|
||||||
|
@@ -25,6 +25,7 @@
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
|
#include "../SDL_sysrender.h"
|
||||||
|
+#include <SDL3/SDL_gxm.h>
|
||||||
|
|
||||||
|
#include <psp2/kernel/processmgr.h>
|
||||||
|
#include <psp2/appmgr.h>
|
||||||
|
@@ -47,12 +48,6 @@
|
||||||
|
#define VITA_GXM_PENDING_SWAPS 2
|
||||||
|
#define VITA_GXM_POOL_SIZE 2 * 1024 * 1024
|
||||||
|
|
||||||
|
-typedef struct
|
||||||
|
-{
|
||||||
|
- void *address;
|
||||||
|
- Uint8 wait_vblank;
|
||||||
|
-} VITA_GXM_DisplayData;
|
||||||
|
-
|
||||||
|
typedef struct clear_vertex
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
@@ -193,8 +188,6 @@ typedef struct
|
||||||
|
blend_fragment_programs blendFragmentPrograms;
|
||||||
|
|
||||||
|
gxm_drawstate_cache drawstate;
|
||||||
|
- SceClibMspace texturePool;
|
||||||
|
- SceUID texturePoolUID;
|
||||||
|
} VITA_GXM_RenderData;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c
|
||||||
|
index f40a92d85..b46b94730 100644
|
||||||
|
--- a/src/video/SDL_surface.c
|
||||||
|
+++ b/src/video/SDL_surface.c
|
||||||
|
@@ -271,6 +271,7 @@ SDL_Surface *SDL_CreateSurfaceFrom(int width, int height, SDL_PixelFormat format
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pitch < 0 || (size_t)pitch < minimalPitch) {
|
||||||
|
+ SDL_Log("pitch=%d minimalPitch=%d", pitch, minimalPitch);
|
||||||
|
SDL_InvalidParamError("pitch");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user