summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/render')
-rw-r--r--src/render/meson.build2
-rw-r--r--src/render/queue_libplacebo.c20
-rw-r--r--src/render/renderer_libplacebo.c64
-rw-r--r--src/render/renderer_libplacebo.h1
-rw-r--r--src/render/shaders/vr_video.h46
5 files changed, 101 insertions, 32 deletions
diff --git a/src/render/meson.build b/src/render/meson.build
index b7927bb..af68036 100644
--- a/src/render/meson.build
+++ b/src/render/meson.build
@@ -128,7 +128,7 @@ endif
if get_option('subtitles').enabled()
libass = dependency('libass', required: false, allow_fallback: false)
if not libass.found()
- libass_opts = []
+ libass_opts = ['test=disabled']
if not is_windows
libass_opts += ['fontconfig=enabled']
# libass(e46aede):meson.build:126
diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c
index 5932944..488c3b5 100644
--- a/src/render/queue_libplacebo.c
+++ b/src/render/queue_libplacebo.c
@@ -22,6 +22,7 @@ static bool queue_lp_configure_subtitles(struct camu_frame_queue *queue, u32 wid
log_error("Failed to initialize ass renderer.");
return false;
}
+ ass_set_shaper(lq->ass_renderer, ASS_SHAPING_COMPLEX);
lq->ass_track = ass_new_track(lq->ass);
if (!lq->ass_track) {
log_error("Failed to create ass track.");
@@ -49,7 +50,7 @@ static bool queue_lp_configure_subtitles(struct camu_frame_queue *queue, u32 wid
static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src,
struct pl_frame *out_frame)
{
- struct camu_codec_frame *frame = src->frame_data;
+ struct camu_codec_frame *frame = (struct camu_codec_frame *)src->frame_data;
u64 masks[4] = { 0 };
s32 pixel_stride;
@@ -120,7 +121,7 @@ static void unmap_frame(pl_gpu gpu, struct pl_frame *frame, const struct pl_sour
static void discard_frame(const struct pl_source_frame *src)
{
- struct camu_codec_frame *frame = src->frame_data;
+ struct camu_codec_frame *frame = (struct camu_codec_frame *)src->frame_data;
camu_codec_frame_discard(frame);
}
@@ -142,7 +143,6 @@ static void queue_lp_push(struct camu_frame_queue *queue, struct camu_codec_fram
static struct camu_overlay_lp *create_subtitle_overlay(pl_gpu gpu, ASS_Image *ass_frame)
{
struct camu_overlay_lp *overlay = al_alloc_object(struct camu_overlay_lp);
-
for (; ass_frame; ass_frame = ass_frame->next) {
pl_tex tex = pl_tex_create(gpu, pl_tex_params(
.w = ass_frame->w,
@@ -166,14 +166,11 @@ static struct camu_overlay_lp *create_subtitle_overlay(pl_gpu gpu, ASS_Image *as
if (overlay->num >= overlay->alloc) {
s32 old_alloc = overlay->alloc;
overlay->alloc = old_alloc ? al_next_power_of_two(overlay->alloc + 1) : 8;
- if (!overlay->overlays) {
- overlay->overlays = al_malloc(sizeof(struct pl_overlay) * overlay->alloc);
- } else {
- overlay->overlays = al_realloc(overlay->overlays, sizeof(struct pl_overlay) * overlay->alloc);
- }
+ overlay->overlays = (struct pl_overlay *)al_realloc(overlay->overlays,
+ sizeof(struct pl_overlay) * overlay->alloc);
for (s32 i = old_alloc; i < overlay->alloc; i++) {
current = (struct pl_overlay *)&overlay->overlays[i];
- current->parts = al_malloc(sizeof(struct pl_overlay_part) * 1);
+ current->parts = (struct pl_overlay_part *)al_malloc(sizeof(struct pl_overlay_part));
current->num_parts = 0;
}
}
@@ -209,7 +206,6 @@ static struct camu_overlay_lp *create_subtitle_overlay(pl_gpu gpu, ASS_Image *as
current->coords = PL_OVERLAY_COORDS_SRC_FRAME;
current->num_parts = 1;
}
-
return overlay;
}
#endif
@@ -217,7 +213,7 @@ static struct camu_overlay_lp *create_subtitle_overlay(pl_gpu gpu, ASS_Image *as
static bool map_av_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src,
struct pl_frame *out_frame)
{
- AVFrame *frame = src->frame_data;
+ AVFrame *frame = (AVFrame *)src->frame_data;
struct camu_frame_queue_lp *lq = (struct camu_frame_queue_lp *)frame->opaque;
AVStream *stream = lq->q.buf->stream->av.stream;
@@ -316,7 +312,7 @@ static void unmap_av_frame(pl_gpu gpu, struct pl_frame *frame, const struct pl_s
static void discard_av_frame(const struct pl_source_frame *src)
{
- AVFrame *frame = src->frame_data;
+ AVFrame *frame = (AVFrame *)src->frame_data;
av_frame_free(&frame);
log_warn("Dropped frame with PTS %.3f.", src->pts);
}
diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c
index 5ef2a34..191c40d 100644
--- a/src/render/renderer_libplacebo.c
+++ b/src/render/renderer_libplacebo.c
@@ -15,6 +15,8 @@
#include <libplacebo/d3d11.h>
#endif
+#include "shaders/vr_video.h"
+
#include "renderer_libplacebo.h"
#include "queue_libplacebo.h"
@@ -276,19 +278,15 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
lr->params.correct_subpixel_offsets = true;
//lr->params.distort_params = pl_distort_params(.unscaled = false);
-#if 0
+ lr->vr_emulation_hook[0] = pl_mpv_user_shader_parse(lr->gpu, vr_video_shader, sizeof(vr_video_shader) - 1);
+ /*
struct nn_file file;
if (nn_file_open(&file, &al_str_c(""), 0)) {
char *c_str;
size_t length = nn_file_read_as_c_str(&file, &c_str);
const struct pl_hook *hook = pl_mpv_user_shader_parse(lr->gpu, (const char *)c_str, length);
- const struct pl_hook **hooks = al_malloc(sizeof(struct pl_hook *));
- hooks[0] = al_malloc(sizeof(struct pl_hook));
- al_memcpy((void *)hooks[0], (void *)hook, sizeof(struct pl_hook));
- lr->params.hooks = hooks;
- lr->params.num_hooks = 1;
}
-#endif
+ */
#ifdef CAMU_HAVE_FFMPEG
lr->r.get_buffer2 = pl_get_buffer2;
@@ -345,6 +343,19 @@ static u32 renderer_lp_get_latency(struct camu_renderer *renderer)
return (u32)pl_swapchain_latency(lr->swapchain);
}
+// This is a completely broken "hash" of the f64 pts value, but it works for now.
+// https://www.virtualdub.org/blog2/entry_259.html
+static inline intptr_t float_64_hash(f64 value)
+{
+ union { f64 f; u64 u; } fv;
+ fv.f = value;
+ intptr_t hash = (intptr_t)fv.u;
+#ifdef AL_WE_32BIT
+ hash += (intptr_t)(fv.u >> 32);
+#endif
+ return hash;
+}
+
static void renderer_lp_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
{
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
@@ -368,6 +379,20 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
lr->have_frame = true;
}
+ f64 mouse_x, mouse_y;
+ bool vr_emulation = scr->vr_emulation && lr->vr_emulation_hook[0];
+ if (vr_emulation) {
+ mouse_x = (scr->last_pointer_x - (scr->calibrate_x - (scr->width / 2.0))) / (f64)scr->width;
+ mouse_y = (scr->last_pointer_y - (scr->calibrate_y - (scr->height / 2.0))) / (f64)scr->height;
+ mouse_y = 1.0 - mouse_y;
+ mouse_x = CLAMP(mouse_x, -0.5, 1.5);
+ mouse_y = CLAMP(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;
+ }
+
struct pl_frame *target = &lr->target;
struct pl_frame_mix mix;
@@ -385,16 +410,15 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
do_gpu_finish |= weighted;
// Terrible hack. Lets us distinguish single frames with the same dimensions.
// Tied to a libplacebo patch to consider info_priv in the hash.
- // Also, add in reset_pts to account for buffer resets. This is a completely
- // broken "hash" of the f64 pts value but hopefully it works for now.
- // https://www.virtualdub.org/blog2/entry_259.html
+ // Also, add in reset_pts to account for buffer resets.
intptr_t hash = (intptr_t)video->buf;
- union { f64 f; u64 u; } pts_hash;
- pts_hash.f = video->buf->reset_pts;
- hash += (intptr_t)pts_hash.u;
-#ifdef AL_WE_32BIT
- hash += (intptr_t)(pts_hash.u >> 32);
-#endif
+ hash += float_64_hash(video->buf->reset_pts);
+ if (vr_emulation) {
+ hash += float_64_hash(mouse_x);
+ hash += float_64_hash(mouse_y);
+ hash += float_64_hash(video->view.fov);
+ lr->params.hooks[0]->parameters[2].data->f = (f32)video->view.fov;
+ }
lr->params.info_priv = (void *)hash;
target->crop = mix.frames[0]->crop;
target->crop.x1 *= video->view.zoom / video->view.stretch;
@@ -404,9 +428,7 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
target->crop.x1 += video->view.x_offset;
target->crop.y1 += video->view.y_offset;
target->rotation = video->view.rotation;
- //lr->params.color_adjustment = pl_color_adjustment(
- // .saturation = 0.0
- //);
+ //lr->params.color_adjustment = pl_color_adjustment(.saturation = 0.0);
pl_render_image_mix(lr->renderer, &mix, target, &lr->params);
}
} else {
@@ -424,6 +446,9 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
}
}
+ lr->params.hooks = NULL;
+ lr->params.num_hooks = 0;
+
if (!scr->videos.count && !force) {
// Don't spin too hard on a potential error state.
nn_thread_sleep(NNWT_TS_FROM_USEC(192));
@@ -462,6 +487,7 @@ void renderer_lp_free(struct camu_renderer **renderer)
if (lr->gl) pl_opengl_destroy(&lr->gl);
#endif
if (lr->logger) pl_log_destroy(&lr->logger);
+ if (lr->vr_emulation_hook[0]) pl_mpv_user_shader_destroy(&lr->vr_emulation_hook[0]);
#ifdef CAMU_HAVE_SUBTITLES
if (lr->ass) ass_library_done(lr->ass);
#endif
diff --git a/src/render/renderer_libplacebo.h b/src/render/renderer_libplacebo.h
index a0125ba..c8962d2 100644
--- a/src/render/renderer_libplacebo.h
+++ b/src/render/renderer_libplacebo.h
@@ -37,6 +37,7 @@ struct camu_renderer_lp {
pl_renderer renderer;
f64 last_render_tick;
struct pl_render_params params;
+ const struct pl_hook *vr_emulation_hook[1];
#ifdef CAMU_HAVE_SUBTITLES
ASS_Library *ass;
#endif
diff --git a/src/render/shaders/vr_video.h b/src/render/shaders/vr_video.h
new file mode 100644
index 0000000..fc2d192
--- /dev/null
+++ b/src/render/shaders/vr_video.h
@@ -0,0 +1,46 @@
+#pragma once
+
+// https://gist.github.com/tesu/196db5421559de3e9555d4f9da9d847d
+// FOV: [0 to M_PI] horizontal field of view, range is exclusive
+// 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
+//" const float yaw = M_PI*(-1.0+(mouse_x*2.0));\n" // 360
+static const char vr_video_shader[] = \
+"//!PARAM mouse_x\n"
+"//!TYPE float\n"
+"//!MINIMUM -0.5\n"
+"//!MAXIMUM 1.5\n"
+"0.0\n"
+"//!PARAM mouse_y\n"
+"//!TYPE float\n"
+"//!MINIMUM -0.5\n"
+"//!MAXIMUM 1.5\n"
+"0.5\n"
+"//!PARAM fov\n"
+"//!TYPE float\n"
+"//!MINIMUM 0\n"
+"//!MAXIMUM 3.141592653589793\n"
+"1.5707963267948966\n"
+"//!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";