summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/render')
-rw-r--r--src/render/meson.build4
-rw-r--r--src/render/momo/momo.c4
-rw-r--r--src/render/renderer_libplacebo.c50
-rw-r--r--src/render/renderer_libplacebo.h2
-rw-r--r--src/render/shaders/vr_video.h47
5 files changed, 62 insertions, 45 deletions
diff --git a/src/render/meson.build b/src/render/meson.build
index d0ad643..10cb98e 100644
--- a/src/render/meson.build
+++ b/src/render/meson.build
@@ -56,7 +56,7 @@ elif get_option('renderer') == 'libplacebo'
shaderc_opts.add_cmake_defines({ 'ENABLE_EXCEPTIONS_ON_MSVC': false })
shaderc_proj = cmake.subproject('shaderc', options: shaderc_opts)
shaderc = shaderc_proj.dependency('shaderc')
- meson.override_dependency('shaderc', shaderc)
+ meson.override_dependency('shaderc', declare_dependency(dependencies: shaderc, version: '2026.1'))
render_deps += [
shaderc_proj.dependency('shaderc_util'),
shaderc_proj.dependency('glslang'),
@@ -148,7 +148,7 @@ elif get_option('renderer') == 'libplacebo'
spirv_cross_proj.dependency('spirv-cross-core'),
spirv_cross_c_shared
]
- meson.override_dependency('spirv-cross-c-shared', spirv_cross_c_shared)
+ meson.override_dependency('spirv-cross-c-shared', declare_dependency(dependencies: spirv_cross_c_shared, version: '0.29.0'))
libplacebo_opts += ['d3d11=enabled', 'vulkan=disabled', 'opengl=disabled']
else
libplacebo_opts += ['opengl=enabled', 'vulkan=disabled', 'd3d11=disabled']
diff --git a/src/render/momo/momo.c b/src/render/momo/momo.c
index 5239efd..8b1b78d 100644
--- a/src/render/momo/momo.c
+++ b/src/render/momo/momo.c
@@ -3,6 +3,8 @@
#include "momo.h"
+#define CRT_BACKGROUND_COLOR (1.f / 7.5f)
+
bool MOMO_Init(MOMO_Renderer *mmr,
#ifdef STELA_API_OPENGL
bool (*MakeCurrent)(void *),
@@ -17,6 +19,7 @@ bool MOMO_Init(MOMO_Renderer *mmr,
mmr->GL.ReleaseCurrent = ReleaseCurrent;
mmr->GL.SwapBuffers = SwapBuffers;
mmr->GL.MakeCurrent(mmr->Private);
+ glClearColor(CRT_BACKGROUND_COLOR, CRT_BACKGROUND_COLOR, CRT_BACKGROUND_COLOR, 1.f);
const char *gl_version = (const char *)glGetString(GL_VERSION);
if (gl_version) {
log_info("GL context version: %s.", gl_version);
@@ -30,6 +33,7 @@ bool MOMO_Init(MOMO_Renderer *mmr,
void MOMO_Render(MOMO_Renderer *mmr)
{
#ifdef STELA_API_OPENGL
+ glClear(GL_COLOR_BUFFER_BIT);
mmr->GL.SwapBuffers(mmr->Private);
#endif
}
diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c
index 3551979..0995f6f 100644
--- a/src/render/renderer_libplacebo.c
+++ b/src/render/renderer_libplacebo.c
@@ -3,6 +3,7 @@
#include <al/log.h>
#include <al/lib.h>
#include <nnwt/file.h>
+#include <nnwt/time.h>
#include "../screen/screen.h"
#include "../util/color_palette.h"
@@ -27,10 +28,11 @@ static inline void pl_swapchain_resize_compat(pl_swapchain swapchain, u32 *width
{
s32 req_width = (s32)*width;
s32 req_height = (s32)*height;
- pl_swapchain_resize(swapchain, &req_width, &req_height);
- al_assert(req_width > 0 && req_height > 0);
- *width = (u32)req_width;
- *height = (u32)req_height;
+ if (pl_swapchain_resize(swapchain, &req_width, &req_height)) {
+ al_assert(req_width > 0 && req_height > 0);
+ *width = (u32)req_width;
+ *height = (u32)req_height;
+ }
}
static void renderer_lp_resize(struct camu_renderer *renderer, u32 *width, u32 *height)
@@ -109,7 +111,7 @@ static void ass_log_callback(s32 level, const char *fmt, va_list args, void *use
al_logv(AL_LOG_ERROR, "ass", fmt, args);
} else if (level <= 3) {
al_logv(AL_LOG_WARN, "ass", fmt, args);
- } else if (level <= 6) {
+ } else if (level <= 5) {
#ifdef AL_DEBUG
al_logv(AL_LOG_DEBUG, "ass", fmt, args);
#endif
@@ -214,8 +216,11 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
goto err;
}
+ // https://learn.microsoft.com/en-us/windows/win32/api/dxgi/ne-dxgi-dxgi_swap_chain_flag
lr->swapchain = pl_d3d11_create_swapchain(lr->d3d11, pl_d3d11_swapchain_params(
.window = win32_window,
+ //.blit = true,
+ //.flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING
));
if (!lr->swapchain) {
log_error("Failed to create D3D11 swapchain.");
@@ -245,8 +250,10 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
goto err;
}
+ // max_swapchain_depth is returned as-is by pl_swapchain_latency().
+ // Combined with eglSwapInterval(1), I don't think that's the value we're looking for.
lr->swapchain = pl_opengl_create_swapchain(lr->gl, pl_opengl_swapchain_params(
- .max_swapchain_depth = 1,
+ //.max_swapchain_depth = 1,
.swap_buffers = gl_swap_buffers,
.priv = priv
));
@@ -277,17 +284,12 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
// Clear manually so we can draw multiple images per frame.
lr->params.border = PL_CLEAR_SKIP;
lr->params.background = PL_CLEAR_TILES;
- /*
- lr->params.background_color[0] = clear_color[0];
- lr->params.background_color[1] = clear_color[1];
- lr->params.background_color[2] = clear_color[2];
- lr->params.background_transparency = clear_color[3];
- */
+ lr->params.blend_params = &pl_alpha_overlay;
// Prioritize a more consistent image.
lr->params.correct_subpixel_offsets = true;
- //lr->params.distort_params = pl_distort_params(.unscaled = false);
+ //lr->params.distort_params = pl_distort_params(.unscaled = false);
lr->vr_emulation_hook[0] = pl_mpv_user_shader_parse(lr->gpu, vr_video_shader, sizeof(vr_video_shader) - 1);
/*
struct nn_file file;
@@ -308,7 +310,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
ass_set_message_cb(lr->ass, ass_log_callback, lr);
#endif
- lr->last_render_tick = nn_get_tick();
+ lr->last_swap_tick = nn_get_tick();
return true;
err:
@@ -369,8 +371,6 @@ static inline intptr_t float_64_hash(f64 value)
return hash;
}
-
-
static bool renderer_lp_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
{
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
@@ -400,14 +400,17 @@ static bool renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
mouse_y = (scr->last_pointer_y / scr->height) - (scr->vr_calibrate_y - 0.5);
if (scr->vr_emulation == CAMU_VR_360) {
mouse_x = CLAMP(mouse_x * 2.0, -1.0, 3.0);
- } else {
+ } else if (scr->vr_left_eye) {
mouse_x = CLAMP(mouse_x, -0.5, 1.5);
+ } else {
+ mouse_x = CLAMP(1.0 + mouse_x, -1.5, 2.5);
}
mouse_y = CLAMP(1.0 - mouse_y, -0.5, 1.5);
lr->params.hooks = lr->vr_emulation_hook;
lr->params.num_hooks = 1;
lr->params.hooks[0]->parameters[0].data->f = (f32)mouse_x;
lr->params.hooks[0]->parameters[1].data->f = (f32)mouse_y;
+ lr->params.hooks[0]->parameters[3].data->f = (scr->vr_emulation == CAMU_VR_360) ? 2.0 : 1.0 - (f32)scr->vr_left_eye;
}
enum {
@@ -492,11 +495,11 @@ static bool renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
// Considerations about the result of the loop above.
// 1. Any given call to video_buffer_read() may not produce a frame.
- // 2. If a buffer signals EOF, by the time run_queue() happens at the bottom of the loop all
- // previous buffers could have been queued for removal. Meaning, at this point, videos.count
- // would be 0 while there could be data we want to display rendered to the frame.
+ // 2. If any buffer signals EOF, by the time run_queue() is called at the bottom of the loop,
+ // all previous buffers could have been queued for removal. Meaning scr->videos would be
+ // empty while there could still be data we want to display rendered to the frame.
if (!(result & RESULT_SUBMIT) && !force) {
- nn_thread_sleep(NNWT_TS_FROM_USEC(192));
+ nn_thread_sleep(NNWT_TS_FROM_USEC(256));
return true;
}
@@ -509,6 +512,11 @@ static bool renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
pl_swapchain_swap_buffers(lr->swapchain);
+ f64 tick = nn_get_tick();
+ // This is mainly to log when render() is being called, not to be an accurate measurement.
+ log_trace("swap_buffers(), (interval: %f).", tick - lr->last_swap_tick);
+ lr->last_swap_tick = tick;
+
if (result & RESULT_SUBMIT_AND_WAIT) {
pl_gpu_finish(lr->gpu);
}
diff --git a/src/render/renderer_libplacebo.h b/src/render/renderer_libplacebo.h
index 727e0b3..921c7ac 100644
--- a/src/render/renderer_libplacebo.h
+++ b/src/render/renderer_libplacebo.h
@@ -34,7 +34,7 @@ struct camu_renderer_lp {
struct pl_frame target;
bool have_frame;
pl_renderer renderer;
- f64 last_render_tick;
+ f64 last_swap_tick;
struct pl_render_params params;
const struct pl_hook *vr_emulation_hook[1];
#ifdef CAMU_HAVE_SUBTITLES
diff --git a/src/render/shaders/vr_video.h b/src/render/shaders/vr_video.h
index 73869eb..c892601 100644
--- a/src/render/shaders/vr_video.h
+++ b/src/render/shaders/vr_video.h
@@ -5,7 +5,7 @@
// YAW: [any float] polar angle, one full revolution is 2*M_PI
// PITCH: [any float] vertical tilt, positive is up
// ROLL: [any float] view rotation, positive is clockwise
-static const char vr_video_shader[] = \
+static char vr_video_shader[] = \
"//!PARAM mouse_x\n"
"//!TYPE float\n"
"//!MINIMUM -1.0\n"
@@ -18,28 +18,33 @@ static const char vr_video_shader[] = \
"0.5\n"
"//!PARAM fov\n"
"//!TYPE float\n"
-"//!MINIMUM 0\n"
+"//!MINIMUM 0.0\n"
"//!MAXIMUM 3.141592653589793\n"
"1.5707963267948966\n"
+"//!PARAM mode\n"
+"//!TYPE float\n"
+"//!MINIMUM 0.0\n"
+"//!MAXIMUM 2.0\n"
+"1.0\n" // 0.0 = Left eye, 1.0 = Right eye, 2.0 = 360 degrees.
"//!HOOK MAINPRESUB\n"
"//!BIND HOOKED\n"
"//!DESC un360\n"
-"const float M_PI = 3.141592653589793;\n"
-"vec4 hook() {\n"
-" float yaw = M_PI*mouse_x;\n"
-" float pitch = M_PI*(-0.5+mouse_y);\n"
-" float roll = M_PI*0.0;\n"
-" float t = tan(fov/2);\n"
-" float c = cos(pitch);\n"
-" float s = sin(pitch);\n"
-" float r = target_size.y/target_size.x;\n"
-" float sR = sin(roll);\n"
-" float cR = cos(roll);\n"
-" mat3 m = mat3(2*t*cR, 2*sR*t*r, -t*(cR+sR*r), -2*sR*t*c, 2*cR*t*c*r, t*c*(sR-cR*r)-s, -2*sR*t*s, 2*cR*t*s*r, t*s*(sR-cR*r)+c);\n"
-" vec3 p = vec3(HOOKED_pos, 1.0) * m;\n"
-" float theta = atan(p.x, p.z) + yaw;\n"
-" float phi = atan(p.y, length(p.xz)) + M_PI/2;\n"
-" float x = fract(theta / (2*M_PI));\n"
-" float y = phi / M_PI;\n"
-" return HOOKED_tex(vec2(x, y));\n"
-"}\n";
+"const float M_PI = 3.141592653589793;"
+"vec4 hook() {"
+" float yaw = M_PI*mouse_x;"
+" float pitch = M_PI*(-0.5+mouse_y);"
+" float roll = M_PI*0.0;"
+" float t = tan(fov/2.0);"
+" float c = cos(pitch);"
+" float s = sin(pitch);"
+" float r = target_size.y/target_size.x;"
+" float sR = sin(roll);"
+" float cR = cos(roll);"
+" mat3 m = mat3(2.0*t*cR, 2.0*sR*t*r, -t*(cR+sR*r), -2.0*sR*t*c, 2.0*cR*t*c*r, t*c*(sR-cR*r)-s, -2.0*sR*t*s, 2.0*cR*t*s*r, t*s*(sR-cR*r)+c);"
+" vec3 p = vec3(HOOKED_pos, 1.0)*m;"
+" float theta = atan(p.x, p.z)+yaw;"
+" float phi = atan(p.y, length(p.xz))+M_PI/2.0;"
+" float x = fract(theta/(2.0*M_PI));"
+" float y = phi/M_PI;" // Range: [M_PI, 2.0*M_PI] = Right eye 180 degrees. float(max(theta, mode-1.0) > 0.0) = Always true except mode = 0.0 and theta < 0.0.
+" return HOOKED_tex(vec2(x, y))*clamp(abs((1.0-mode)-(step(M_PI, theta)-step(2.0*M_PI, theta)))*float(max(theta, mode-1.0)>=0.0), 0.0, 1.0);"
+"}";