summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-05-25 18:49:20 -0400
committerAndrew Opalach <andrew@akon.city> 2025-05-25 18:49:20 -0400
commit2fa7ea95c891981684a55b41977172d040c2cc55 (patch)
treed349e810b3178045a420b625f6dbe5634b64807b /src
parent01f852081b1291da7fc342976bf5228ffb618736 (diff)
downloadcamu-2fa7ea95c891981684a55b41977172d040c2cc55.tar.gz
camu-2fa7ea95c891981684a55b41977172d040c2cc55.tar.bz2
camu-2fa7ea95c891981684a55b41977172d040c2cc55.zip
Support Windows XP (Old FFmpeg and build fixes)
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src')
-rw-r--r--src/codec/codec.h47
-rw-r--r--src/codec/ffmpeg/avio.c12
-rw-r--r--src/codec/ffmpeg/avio.h5
-rw-r--r--src/codec/ffmpeg/common.c4
-rw-r--r--src/codec/ffmpeg/decoder.c4
-rw-r--r--src/codec/ffmpeg/decoder.h4
-rw-r--r--src/codec/ffmpeg/demuxer.c7
-rw-r--r--src/codec/ffmpeg/encoder.c25
-rw-r--r--src/codec/ffmpeg/encoder.h2
-rw-r--r--src/codec/ffmpeg/meson.build20
-rw-r--r--src/codec/ffmpeg/packet_ext.c18
-rw-r--r--src/codec/ffmpeg/packet_ext.h3
-rw-r--r--src/codec/ffmpeg/resampler.c33
-rw-r--r--src/fruits/cmc/meson.build2
-rw-r--r--src/fruits/cmc/ui/util/waveform.c2
-rw-r--r--src/fruits/cmsrv/meson.build2
-rw-r--r--src/fruits/cmv/cmv.c14
-rw-r--r--src/fruits/cmv/meson.build2
-rw-r--r--src/fruits/droid/ctv/gradle/libs.versions.toml2
-rw-r--r--src/liana/client.c13
-rw-r--r--src/liana/handlers/codec_client.c2
-rw-r--r--src/liana/handlers/codec_server.c2
-rw-r--r--src/liana/process.c8
-rw-r--r--src/liana/vcr.c6
-rw-r--r--src/libsink/desktop.c17
-rw-r--r--src/libsink/sink.c23
-rw-r--r--src/mixer/audio_miniaudio.c7
-rw-r--r--src/mixer/audio_null.c2
-rw-r--r--src/mixer/meson.build6
-rw-r--r--src/render/meson.build53
-rw-r--r--src/render/momo/meson.build12
-rw-r--r--src/render/momo/momo.c35
-rw-r--r--src/render/momo/momo.h25
-rw-r--r--src/render/queue_libplacebo.c1
-rw-r--r--src/render/queue_momo.c68
-rw-r--r--src/render/queue_momo.h9
-rw-r--r--src/render/queue_tiger.c130
-rw-r--r--src/render/queue_tiger.h18
-rw-r--r--src/render/renderer.h20
-rw-r--r--src/render/renderer_libplacebo.c73
-rw-r--r--src/render/renderer_libplacebo.h12
-rw-r--r--src/render/renderer_momo.c97
-rw-r--r--src/render/renderer_momo.h19
-rw-r--r--src/render/renderer_tiger.c320
-rw-r--r--src/render/renderer_tiger.h31
-rw-r--r--src/screen/screen.c33
-rw-r--r--src/screen/screen.h1
-rw-r--r--src/server/server.c3
48 files changed, 607 insertions, 647 deletions
diff --git a/src/codec/codec.h b/src/codec/codec.h
index 14727d3..16e408c 100644
--- a/src/codec/codec.h
+++ b/src/codec/codec.h
@@ -35,8 +35,8 @@ enum {
enum {
CAMU_STREAM_UNKNOWN = AVMEDIA_TYPE_UNKNOWN,
- CAMU_STREAM_AUDIO = AVMEDIA_TYPE_AUDIO, // 1
CAMU_STREAM_VIDEO = AVMEDIA_TYPE_VIDEO, // 0
+ CAMU_STREAM_AUDIO = AVMEDIA_TYPE_AUDIO, // 1
CAMU_STREAM_SUBTITLE = AVMEDIA_TYPE_SUBTITLE,
CAMU_STREAM_ATTACHMENT = AVMEDIA_TYPE_ATTACHMENT
};
@@ -77,12 +77,13 @@ enum {
CAMU_SEEK_SIZE = 0x10000
};
+// Using values from FFmpeg for potentially less confusing errors.
enum {
CAMU_STREAM_UNKNOWN = -1,
- CAMU_STREAM_AUDIO,
- CAMU_STREAM_VIDEO,
- CAMU_STREAM_SUBTITLE,
- CAMU_STREAM_ATTACHMENT
+ CAMU_STREAM_VIDEO = 0,
+ CAMU_STREAM_AUDIO = 1,
+ CAMU_STREAM_SUBTITLE = 3,
+ CAMU_STREAM_ATTACHMENT = 4
};
enum {
@@ -126,7 +127,11 @@ struct camu_audio_format {
s32 format;
s32 sample_rate;
#ifdef CAMU_HAVE_FFMPEG
+#ifndef CAMU_OLD_FFMPEG
AVChannelLayout channel_layout;
+#else
+ u64 channel_layout;
+#endif
#endif
s32 channel_count;
};
@@ -239,17 +244,49 @@ static inline bool camu_resampler_format_matches(struct camu_resampler_format *f
return fmt->in.format == fmt->req.format
&& fmt->in.sample_rate == fmt->req.sample_rate
#ifdef CAMU_HAVE_FFMPEG
+#ifndef CAMU_OLD_FFMPEG
&& av_channel_layout_compare(&fmt->in.channel_layout, &fmt->req.channel_layout) == 0
+#else
+ && fmt->in.channel_layout == fmt->req.channel_layout
+#endif
#endif
&& fmt->in.channel_count == fmt->req.channel_count;
}
+#ifndef CAMU_OLD_FFMPEG
+#define AV_CODECPAR_CHANNEL_LAYOUT(codecpar) ((codecpar)->ch_layout)
+#define AV_CODECPAR_CHANNELS(codecpar) ((codecpar)->ch_layout.nb_channels)
+static inline void camu_default_channel_layout(AVChannelLayout *ch_layout, s32 channels)
+{
+ av_channel_layout_default(ch_layout, channels);
+}
+static inline void camu_copy_channel_layout(AVChannelLayout *dest, AVChannelLayout *src)
+{
+ av_channel_layout_copy(dest, src);
+}
+#else
+#define AV_CODECPAR_CHANNEL_LAYOUT(codecpar) ((codecpar)->channel_layout)
+#define AV_CODECPAR_CHANNELS(codecpar) ((codecpar)->channels)
+static inline void camu_default_channel_layout(u64 *channel_layout, s32 channels)
+{
+ *channel_layout = av_get_default_channel_layout(channels);
+}
+static inline void camu_copy_channel_layout(u64 *dest, u64 *src)
+{
+ *dest = *src;
+}
+#endif
+
static inline void camu_audio_format_copy(struct camu_audio_format *dest, struct camu_audio_format *src)
{
dest->format = src->format;
dest->sample_rate = src->sample_rate;
#ifdef CAMU_HAVE_FFMPEG
+#ifndef CAMU_OLD_FFMPEG
av_channel_layout_copy(&dest->channel_layout, &src->channel_layout);
+#else
+ dest->channel_layout = src->channel_layout;
+#endif
#endif
dest->channel_count = src->channel_count;
}
diff --git a/src/codec/ffmpeg/avio.c b/src/codec/ffmpeg/avio.c
index 154152e..86130d8 100644
--- a/src/codec/ffmpeg/avio.c
+++ b/src/codec/ffmpeg/avio.c
@@ -2,20 +2,20 @@
#include "../../cache/handle.h"
-s32 camu_avio_read(void *data, u8 *buf, s32 count)
+s32 camu_avio_read(void *opaque, u8 *buf, s32 count)
{
- struct cch_handle *handle = (struct cch_handle *)data;
+ struct cch_handle *handle = (struct cch_handle *)opaque;
return cch_handle_read(handle, buf, count);
}
-s32 camu_avio_write(void *data, const u8 *buf, s32 count)
+s32 camu_avio_write(void *opaque, u8 *buf, s32 count)
{
- struct cch_handle *handle = (struct cch_handle *)data;
+ struct cch_handle *handle = (struct cch_handle *)opaque;
return cch_handle_write(handle, buf, count);
}
-s64 camu_avio_seek(void *data, s64 offset, s32 whence)
+s64 camu_avio_seek(void *opaque, s64 offset, s32 whence)
{
- struct cch_handle *handle = (struct cch_handle *)data;
+ struct cch_handle *handle = (struct cch_handle *)opaque;
return (s64)cch_handle_seek(handle, offset, whence);
}
diff --git a/src/codec/ffmpeg/avio.h b/src/codec/ffmpeg/avio.h
index 04aeeb4..bb67c58 100644
--- a/src/codec/ffmpeg/avio.h
+++ b/src/codec/ffmpeg/avio.h
@@ -2,5 +2,6 @@
#include <al/types.h>
-s32 camu_avio_read(void *data, u8 *buf, s32 buf_size);
-s64 camu_avio_seek(void *data, s64 offset, s32 whence);
+s32 camu_avio_read(void *opaque, u8 *buf, s32 buf_size);
+s32 camu_avio_write(void *opaque, u8 *buf, s32 count);
+s64 camu_avio_seek(void *opaque, s64 offset, s32 whence);
diff --git a/src/codec/ffmpeg/common.c b/src/codec/ffmpeg/common.c
index 259ba90..5226df6 100644
--- a/src/codec/ffmpeg/common.c
+++ b/src/codec/ffmpeg/common.c
@@ -2,6 +2,7 @@
#include <al/log.h>
#include <al/lib.h>
#include <libavutil/log.h>
+#include <libavformat/avformat.h>
#include "common.h"
@@ -55,5 +56,8 @@ void camu_ff_set_log_callback(void (*callback)(void *, s32, const char *, va_lis
void camu_ff_common_init(void)
{
log_info("Using FFmpeg version "FFMPEG_VERSION".");
+#ifdef CAMU_OLD_FFMPEG
+ av_register_all();
+#endif
camu_ff_set_log_callback(av_log_callback);
}
diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c
index c22d1c1..e097e0c 100644
--- a/src/codec/ffmpeg/decoder.c
+++ b/src/codec/ffmpeg/decoder.c
@@ -10,11 +10,11 @@
#endif
#ifdef CAMU_FF_DECODER_HWACCEL
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
static const char *hwdevces[] = { "vulkan" };
#elif defined NAUNET_ON_WINDOWS
static const char *hwdevces[] = { "d3d11va" };
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
static const char *hwdevces[] = { "vaapi" };
#endif
diff --git a/src/codec/ffmpeg/decoder.h b/src/codec/ffmpeg/decoder.h
index ab60ef3..4797060 100644
--- a/src/codec/ffmpeg/decoder.h
+++ b/src/codec/ffmpeg/decoder.h
@@ -4,8 +4,8 @@
#include "../codec.h"
-#ifndef CAMU_SINK_NO_VIDEO
-//#define CAMU_FF_DECODER_HWACCEL
+#ifdef CAMU_USE_HWACCEL
+#define CAMU_FF_DECODER_HWACCEL
#endif
struct camu_ff_decoder {
diff --git a/src/codec/ffmpeg/demuxer.c b/src/codec/ffmpeg/demuxer.c
index bf2039f..a5821a2 100644
--- a/src/codec/ffmpeg/demuxer.c
+++ b/src/codec/ffmpeg/demuxer.c
@@ -88,6 +88,13 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl
for (u32 i = 0; i < av->format_context->nb_streams; i++) {
AVStream *stream = av->format_context->streams[i];
enum AVMediaType type = stream->codecpar->codec_type;
+#ifdef CAMU_OLD_FFMPEG
+ // This is probably not correct.
+ if (stream->codecpar->channel_layout == 0) {
+ stream->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ stream->codecpar->channels = 2;
+ }
+#endif
u64 duration = 0;
if (type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_SUBTITLE) {
// Try to detect attached images.
diff --git a/src/codec/ffmpeg/encoder.c b/src/codec/ffmpeg/encoder.c
index 50e80e4..5d90785 100644
--- a/src/codec/ffmpeg/encoder.c
+++ b/src/codec/ffmpeg/encoder.c
@@ -32,7 +32,7 @@ bool camu_ff_encoder_init(struct camu_ff_encoder *enc, char *encoder_name, char
}
enc->codec_context->sample_rate = 48000;
- av_channel_layout_default(&enc->codec_context->ch_layout, CHANNELS);
+ camu_default_channel_layout(&AV_CODECPAR_CHANNEL_LAYOUT(enc->codec_context), CHANNELS);
enc->codec_context->sample_fmt = AV_SAMPLE_FMT_FLT;
enc->codec_context->bit_rate = bitrate;
enc->codec_context->frame_size = SAMPLES_PER_FRAME;
@@ -62,19 +62,20 @@ bool camu_ff_encoder_init(struct camu_ff_encoder *enc, char *encoder_name, char
av_dict_free(&opts);
AVCodecContext *out_codec = enc->codec_context;
+ AVFrame *frame = av_frame_alloc();
+ frame->format = out_codec->sample_fmt;
+ frame->sample_rate = out_codec->sample_rate;
+ camu_copy_channel_layout(&AV_CODECPAR_CHANNEL_LAYOUT(frame), &AV_CODECPAR_CHANNEL_LAYOUT(out_codec));
+ av_samples_alloc(frame->data, NULL, AV_CODECPAR_CHANNELS(out_codec), SAMPLES_PER_FRAME, frame->format, 1);
+ frame->nb_samples = SAMPLES_PER_FRAME;
+ frame->pts = 0;
- enc->fmt.req.format = out_codec->sample_fmt;
- enc->fmt.req.sample_rate = out_codec->sample_rate;
- av_channel_layout_copy(&enc->fmt.req.channel_layout, &out_codec->ch_layout);
- enc->fmt.req.channel_count = out_codec->ch_layout.nb_channels;
+ enc->fmt.format = frame->format;
+ enc->fmt.sample_rate = frame->sample_rate;
+ camu_copy_channel_layout(&enc->fmt.channel_layout, &AV_CODECPAR_CHANNEL_LAYOUT(frame));
+ enc->fmt.channel_count = AV_CODECPAR_CHANNELS(frame);
- enc->frame = av_frame_alloc();
- enc->frame->format = enc->fmt.req.format;
- enc->frame->sample_rate = enc->fmt.req.sample_rate;
- av_channel_layout_copy(&enc->frame->ch_layout, &enc->fmt.req.channel_layout);
- av_samples_alloc(enc->frame->data, NULL, enc->frame->ch_layout.nb_channels, SAMPLES_PER_FRAME, enc->frame->format, 1);
- enc->frame->nb_samples = SAMPLES_PER_FRAME;
- enc->frame->pts = 0;
+ enc->frame = frame;
return true;
err:
diff --git a/src/codec/ffmpeg/encoder.h b/src/codec/ffmpeg/encoder.h
index 5f7d06f..3ace4d8 100644
--- a/src/codec/ffmpeg/encoder.h
+++ b/src/codec/ffmpeg/encoder.h
@@ -9,7 +9,7 @@ struct camu_ff_encoder {
AVCodecContext *codec_context;
const AVOutputFormat *output_format;
- struct camu_resampler_format fmt;
+ struct camu_audio_format fmt;
AVFrame *frame;
void (*callback)(void *, AVPacket *);
diff --git a/src/codec/ffmpeg/meson.build b/src/codec/ffmpeg/meson.build
index eb68fad..56a75b2 100644
--- a/src/codec/ffmpeg/meson.build
+++ b/src/codec/ffmpeg/meson.build
@@ -3,6 +3,9 @@ ffmpeg_src = [
'packet_ext.c',
]
ffmpeg_args = ['-DCAMU_HAVE_FFMPEG']
+if get_option('codec-hwaccel').enabled()
+ ffmpeg_args += ['-DCAMU_USE_HWACCEL']
+endif
ffmpeg_deps = []
ffmpeg_server_src = [
@@ -16,8 +19,7 @@ ffmpeg_client_src = [
ffmpeg_src,
'decoder.c',
'resampler.c',
- 'scaler.c',
- 'encoder.c'
+ 'scaler.c'
]
ffmpeg_client_deps = []
@@ -38,7 +40,12 @@ libavcodec = dependency('libavcodec', required: false)
libswresample = dependency('libswresample', required: false)
libswscale = dependency('libswscale', required: false)
if not (libavutil.found() and libavformat.found() and libavcodec.found() and libswresample.found() and libswscale.found())
- ffmpeg_proj = subproject('ffmpeg', required: false)
+ if get_option('win32-compat')
+ ffmpeg_proj = subproject('ffmpeg-compat', required: false)
+ ffmpeg_args += ['-DCAMU_OLD_FFMPEG']
+ else
+ ffmpeg_proj = subproject('ffmpeg', required: false)
+ endif
if ffmpeg_proj.found()
libavutil = ffmpeg_proj.get_variable('avutil')
libavformat = ffmpeg_proj.get_variable('avformat')
@@ -48,9 +55,12 @@ if not (libavutil.found() and libavformat.found() and libavcodec.found() and lib
libswscale = ffmpeg_proj.get_variable('swscale')
# Only used to set include dirs for FFmpeg.
ffmpeg_deps += [ffmpeg_proj.get_variable('ffmpeg_include')]
- # We explicitly enable zlib in the FFmpeg build.
+ # We explicitly enable zlib and maybe bzlib in the FFmpeg build.
ffmpeg_deps += [dependency('zlib')]
- if is_windows
+ if not get_option('sink-only')
+ ffmpeg_deps += [dependency('bzip2')]
+ endif
+ if is_windows and not get_option('win32-compat')
# Extra static dependencies for Windows.
ffmpeg_client_deps += [compiler.find_library('bcrypt')]
elif is_android
diff --git a/src/codec/ffmpeg/packet_ext.c b/src/codec/ffmpeg/packet_ext.c
index acf5bbd..a1a6a5e 100644
--- a/src/codec/ffmpeg/packet_ext.c
+++ b/src/codec/ffmpeg/packet_ext.c
@@ -16,7 +16,7 @@ void nn_packet_write_av_codec_parameters(struct nn_packet *packet, AVCodecParame
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->width);
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->height);
NNWT_PACKET_WRITE_TYPE(packet, AVRational, codecpar->sample_aspect_ratio);
-#if LIBAVCODEC_VERSION_INT >= 60
+#if !defined CAMU_OLD_FFMPEG && LIBAVCODEC_VERSION_INT >= 60
NNWT_PACKET_WRITE_TYPE(packet, AVRational, codecpar->framerate);
#endif
NNWT_PACKET_WRITE_TYPE(packet, enum AVFieldOrder, codecpar->field_order);
@@ -26,6 +26,7 @@ void nn_packet_write_av_codec_parameters(struct nn_packet *packet, AVCodecParame
NNWT_PACKET_WRITE_TYPE(packet, enum AVColorSpace, codecpar->color_space);
NNWT_PACKET_WRITE_TYPE(packet, enum AVChromaLocation, codecpar->chroma_location);
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->video_delay);
+#ifndef CAMU_OLD_FFMPEG
// Incomplete.
NNWT_PACKET_WRITE_TYPE(packet, enum AVChannelOrder, codecpar->ch_layout.order);
if (codecpar->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
@@ -33,6 +34,10 @@ void nn_packet_write_av_codec_parameters(struct nn_packet *packet, AVCodecParame
} else {
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->ch_layout.nb_channels);
}
+#else
+ NNWT_PACKET_WRITE_TYPE(packet, u64, codecpar->channel_layout);
+ NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->channels);
+#endif
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->sample_rate);
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->block_align);
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->frame_size);
@@ -98,7 +103,9 @@ void nn_packet_write_av_packet(struct nn_packet *packet, AVPacket *pkt)
}
NNWT_PACKET_WRITE_TYPE(packet, s64, pkt->duration);
NNWT_PACKET_WRITE_TYPE(packet, s64, pkt->pos);
+#ifndef CAMU_OLD_FFMPEG
NNWT_PACKET_WRITE_TYPE(packet, AVRational, pkt->time_base);
+#endif
}
void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParameters *codecpar)
@@ -120,7 +127,7 @@ void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParamet
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->width);
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->height);
NNWT_PACKET_READ_TYPE(packet, AVRational, codecpar->sample_aspect_ratio);
-#if LIBAVCODEC_VERSION_INT >= 60
+#if !defined CAMU_OLD_FFMPEG && LIBAVCODEC_VERSION_INT >= 60
NNWT_PACKET_READ_TYPE(packet, AVRational, codecpar->framerate);
#endif
NNWT_PACKET_READ_TYPE(packet, enum AVFieldOrder, codecpar->field_order);
@@ -130,6 +137,7 @@ void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParamet
NNWT_PACKET_READ_TYPE(packet, enum AVColorSpace, codecpar->color_space);
NNWT_PACKET_READ_TYPE(packet, enum AVChromaLocation, codecpar->chroma_location);
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->video_delay);
+#ifndef CAMU_OLD_FFMPEG
enum AVChannelOrder order;
NNWT_PACKET_READ_TYPE(packet, enum AVChannelOrder, order);
if (order == AV_CHANNEL_ORDER_NATIVE) {
@@ -141,6 +149,10 @@ void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParamet
NNWT_PACKET_READ_TYPE(packet, s32, nb_channels);
av_channel_layout_default(&codecpar->ch_layout, nb_channels);
}
+#else
+ NNWT_PACKET_READ_TYPE(packet, u64, codecpar->channel_layout);
+ NNWT_PACKET_READ_TYPE(packet, s32, codecpar->channels);
+#endif
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->sample_rate);
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->block_align);
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->frame_size);
@@ -214,5 +226,7 @@ void nn_packet_read_av_packet(struct nn_packet *packet, AVPacket *pkt)
}
NNWT_PACKET_READ_TYPE(packet, s64, pkt->duration);
NNWT_PACKET_READ_TYPE(packet, s64, pkt->pos);
+#ifndef CAMU_OLD_FFMPEG
NNWT_PACKET_READ_TYPE(packet, AVRational, pkt->time_base);
+#endif
}
diff --git a/src/codec/ffmpeg/packet_ext.h b/src/codec/ffmpeg/packet_ext.h
index fab9b36..540cdcb 100644
--- a/src/codec/ffmpeg/packet_ext.h
+++ b/src/codec/ffmpeg/packet_ext.h
@@ -1,8 +1,7 @@
#pragma once
#include <nnwt/packet.h>
-#include <libavcodec/packet.h>
-#include <libavcodec/codec_par.h>
+#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
diff --git a/src/codec/ffmpeg/resampler.c b/src/codec/ffmpeg/resampler.c
index eacc75b..48cca8e 100644
--- a/src/codec/ffmpeg/resampler.c
+++ b/src/codec/ffmpeg/resampler.c
@@ -12,26 +12,35 @@ static bool ff_resampler_init(struct camu_resampler *resamp, struct camu_resampl
camu_audio_format_copy(&av->fmt, &fmt->req);
- s32 ret = swr_alloc_set_opts2(&av->resample_context,
- &fmt->req.channel_layout, fmt->req.format, fmt->req.sample_rate,
- &fmt->in.channel_layout, fmt->in.format, fmt->in.sample_rate, 0, NULL);
- if (ret != 0) {
- log_error("Failed to configure resampler context.");
- return false;
- }
+ SwrContext *swr = swr_alloc();
+
+#ifndef CAMU_OLD_FFMPEG
+ av_opt_set_chlayout(swr, "in_chlayout", &fmt->in.channel_layout, 0);
+ av_opt_set_chlayout(swr, "out_chlayout", &fmt->req.channel_layout, 0);
+#else
+ av_opt_set_channel_layout(swr, "in_channel_layout", fmt->in.channel_layout, 0);
+ av_opt_set_channel_layout(swr, "out_channel_layout", fmt->req.channel_layout, 0);
+#endif
+ av_opt_set_int(swr, "in_sample_rate", fmt->in.sample_rate, 0);
+ av_opt_set_int(swr, "out_sample_rate", fmt->req.sample_rate, 0);
+ av_opt_set_sample_fmt(swr, "in_sample_fmt", fmt->in.format, 0);
+ av_opt_set_sample_fmt(swr, "out_sample_fmt", fmt->req.format, 0);
#ifdef CAMU_HAVE_SOXR
// Slower but more accurate resampler.
- av_opt_set_int(av->resample_context, "resampler", SWR_ENGINE_SOXR, 0);
+ av_opt_set_int(swr, "resampler", SWR_ENGINE_SOXR, 0);
log_info("Using SoX resampler.");
#endif
- if (swr_init(av->resample_context) != 0) {
- swr_free(&av->resample_context);
- log_error("Failed to init resampler context.");
+ s32 ret = swr_init(swr);
+ if (ret != 0) {
+ swr_free(&swr);
+ log_error("Failed to init resampler context (%s).", av_err2str(ret));
return false;
}
+ av->resample_context = swr;
+
return true;
}
@@ -44,7 +53,7 @@ static inline void alloc_sample_data(struct camu_ff_resampler *av, s32 sample_co
{
if (av->sample_count >= sample_count) return;
free_sample_data(av);
- s32 nb_channels = av->fmt.channel_layout.nb_channels;
+ s32 nb_channels = av->fmt.channel_count;
av_samples_alloc(av->data, NULL, nb_channels, sample_count, av->fmt.format, 32);
av->sample_count = sample_count;
}
diff --git a/src/fruits/cmc/meson.build b/src/fruits/cmc/meson.build
index 864af8a..de6d335 100644
--- a/src/fruits/cmc/meson.build
+++ b/src/fruits/cmc/meson.build
@@ -19,7 +19,7 @@ if use_tui
cmc_deps += [notcurses, notcurses_core, codecs_client]
endif
-if is_windows and meson.is_cross_build()
+if is_windows and not is_msvc
cmc_args += ['-static', '-static-libgcc', '-static-libstdc++', '-municode', '-mwindows']
endif
diff --git a/src/fruits/cmc/ui/util/waveform.c b/src/fruits/cmc/ui/util/waveform.c
index 535f219..b114a5e 100644
--- a/src/fruits/cmc/ui/util/waveform.c
+++ b/src/fruits/cmc/ui/util/waveform.c
@@ -5,7 +5,7 @@
#define WITHIN_RMS(low, high, rms) \
((low >= 0 && low <= rms) || (high < 0 && high >= -rms) || (low < 0 && high > 0 && rms > 0))
-#define OUTPUT_WAVEFORM_PNG
+//#define OUTPUT_WAVEFORM_PNG
//#define WAVEFORM_REFERENCE_MODE
#ifdef OUTPUT_WAVEFORM_PNG
#include <nnwt/file.h>
diff --git a/src/fruits/cmsrv/meson.build b/src/fruits/cmsrv/meson.build
index dce3d94..b12d00d 100644
--- a/src/fruits/cmsrv/meson.build
+++ b/src/fruits/cmsrv/meson.build
@@ -8,7 +8,7 @@ if use_tui
cmsrv_deps += [notcurses_core]
endif
-if is_windows and meson.is_cross_build()
+if is_windows and not is_msvc
cmsrv_args += ['-static', '-static-libgcc', '-static-libstdc++', '-municode', '-mwindows']
endif
diff --git a/src/fruits/cmv/cmv.c b/src/fruits/cmv/cmv.c
index 70a0b28..28dcbb5 100644
--- a/src/fruits/cmv/cmv.c
+++ b/src/fruits/cmv/cmv.c
@@ -3,14 +3,16 @@
#include <nnwt/event_loop.h>
#include <nnwt/thread.h>
-#include "../../util/color_palette.h"
-#include "../../codec/ffmpeg/common.h"
#include "../../libsink/desktop.h"
#include "../../server/common.h"
#ifndef CAMU_SINK_ONLY
#include "../../server/server.h"
#endif
#include "../../server/common.h"
+#include "../../util/color_palette.h"
+#ifdef CAMU_HAVE_FFMPEG
+#include "../../codec/ffmpeg/common.h"
+#endif
#include "../common.h"
@@ -95,7 +97,11 @@ static bool parse_exe_name_params(str *exe_name, str *addr, struct lia_prefs *pr
return true;
def:
+#ifdef CAMU_HAVE_SUBTITLES
prefs->enabled_mask = CAMU_MASK_AUDIO | CAMU_MASK_VIDEO | CAMU_MASK_SUBTITLE;
+#else
+ prefs->enabled_mask = CAMU_MASK_AUDIO | CAMU_MASK_VIDEO;
+#endif
prefs->audio_lang = CAMU_LANG_JAPANESE;
prefs->subtitle_lang = CAMU_LANG_ENGLISH;
@@ -175,8 +181,10 @@ s32 window_system_main(u32 argc, str *argv, void *extra)
c.desktop.exit_callback = exit_callback;
c.desktop.userdata = &c;
}
-#endif
str *name = local ? &al_str_c("local") : &al_str_c("desktop");
+#else
+ str *name = &al_str_c("desktop");
+#endif
if (!camu_desktop_connect(&c.desktop, name, &c.loop, type, &addr, CAMU_PORT)) {
return EXIT_FAILURE;
}
diff --git a/src/fruits/cmv/meson.build b/src/fruits/cmv/meson.build
index 870345e..bfd2182 100644
--- a/src/fruits/cmv/meson.build
+++ b/src/fruits/cmv/meson.build
@@ -14,7 +14,7 @@ if use_tui
endif
cmv_link_args = []
-if is_windows and meson.is_cross_build()
+if is_windows and not is_msvc
cmv_link_args += ['-static', '-static-libgcc', '-static-libstdc++', '-municode', '-mwindows']
endif
diff --git a/src/fruits/droid/ctv/gradle/libs.versions.toml b/src/fruits/droid/ctv/gradle/libs.versions.toml
index 4a8d0bc..95dfb43 100644
--- a/src/fruits/droid/ctv/gradle/libs.versions.toml
+++ b/src/fruits/droid/ctv/gradle/libs.versions.toml
@@ -1,5 +1,5 @@
[versions]
-agp = "8.9.1"
+agp = "8.10.0"
[libraries]
diff --git a/src/liana/client.c b/src/liana/client.c
index 164a4d1..626a752 100644
--- a/src/liana/client.c
+++ b/src/liana/client.c
@@ -27,7 +27,12 @@ static void data_packet_callback(void *userdata, struct nn_packet_stream *stream
static s32 stream_compare(const void *a, const void *b)
{
- return (s32)((struct camu_codec_stream *)a)->type - (s32)((struct camu_codec_stream *)b)->type;
+ struct camu_codec_stream *aa = (struct camu_codec_stream *)a;
+ struct camu_codec_stream *bb = (struct camu_codec_stream *)b;
+ if (aa->type == bb->type) {
+ return aa->index - bb->index;
+ }
+ return aa->type - bb->type;
}
static void collect_streams(struct lia_client *client, struct nn_packet *packet)
@@ -49,7 +54,7 @@ static void collect_streams(struct lia_client *client, struct nn_packet *packet)
fmt->sample_rate = nn_packet_read_s32(packet);
fmt->channel_count = nn_packet_read_s32(packet);
#ifdef CAMU_HAVE_FFMPEG
- av_channel_layout_default(&fmt->channel_layout, fmt->channel_count);
+ camu_default_channel_layout(&fmt->channel_layout, fmt->channel_count);
#endif
} else if (type == CAMU_STREAM_VIDEO) {
struct camu_video_format *fmt = &stream.video.fmt;
@@ -80,8 +85,8 @@ static void collect_streams(struct lia_client *client, struct nn_packet *packet)
struct camu_audio_format *fmt = &stream.audio.fmt;
fmt->format = codecpar->format;
fmt->sample_rate = codecpar->sample_rate;
- av_channel_layout_copy(&fmt->channel_layout, &codecpar->ch_layout);
- fmt->channel_count = codecpar->ch_layout.nb_channels;
+ camu_copy_channel_layout(&fmt->channel_layout, &AV_CODECPAR_CHANNEL_LAYOUT(codecpar));
+ fmt->channel_count = AV_CODECPAR_CHANNELS(codecpar);
break;
}
case CAMU_STREAM_VIDEO: {
diff --git a/src/liana/handlers/codec_client.c b/src/liana/handlers/codec_client.c
index fd2569b..38b5d3b 100644
--- a/src/liana/handlers/codec_client.c
+++ b/src/liana/handlers/codec_client.c
@@ -132,9 +132,9 @@ static bool codec_client_handle_packet(struct lia_client_handler *handler, struc
#endif
break;
}
+#endif
default:
al_assert_and_return(false);
-#endif
}
// Restore packet rindex in case we resue it.
diff --git a/src/liana/handlers/codec_server.c b/src/liana/handlers/codec_server.c
index de2c927..3b7d31e 100644
--- a/src/liana/handlers/codec_server.c
+++ b/src/liana/handlers/codec_server.c
@@ -149,7 +149,7 @@ static void codec_server_write_packet(struct lia_server_handler *handler, struct
nn_packet_write_u8(packet, LIANA_PACKET_EOF);
#ifdef LIANA_SERVER_LOOP
codec->pts_offset += codec->demux->get_duration(codec->demux);
- codec->demux->seek(codec->demux, 0);
+ codec->demux->seek(codec->demux, 0, false);
#endif
} else {
nn_packet_write_u8(packet, LIANA_PACKET_ERROR);
diff --git a/src/liana/process.c b/src/liana/process.c
index 0a6d6b6..a8b57d0 100644
--- a/src/liana/process.c
+++ b/src/liana/process.c
@@ -65,10 +65,10 @@ bool lia_prepare_visual_data(struct cch_handle *handle, struct lia_visual_data *
fmt.req.format = CAMU_SAMPLE_FORMAT_S16;
fmt.in.sample_rate = codecpar->sample_rate;
fmt.req.sample_rate = codecpar->sample_rate;
- av_channel_layout_copy(&fmt.in.channel_layout, &codecpar->ch_layout);
- av_channel_layout_copy(&fmt.req.channel_layout, &codecpar->ch_layout);
- fmt.in.channel_count = codecpar->ch_layout.nb_channels;
- fmt.req.channel_count = codecpar->ch_layout.nb_channels;
+ camu_copy_channel_layout(&fmt.in.channel_layout, &AV_CODECPAR_CHANNEL_LAYOUT(codecpar));
+ camu_copy_channel_layout(&fmt.req.channel_layout, &AV_CODECPAR_CHANNEL_LAYOUT(codecpar));
+ fmt.in.channel_count = AV_CODECPAR_CHANNELS(codecpar);
+ fmt.req.channel_count = AV_CODECPAR_CHANNELS(codecpar);
struct raw_samples_data raw;
raw.resampler = resampler;
diff --git a/src/liana/vcr.c b/src/liana/vcr.c
index 4500681..78c2b9c 100644
--- a/src/liana/vcr.c
+++ b/src/liana/vcr.c
@@ -126,9 +126,11 @@ static nn_thread_result NNWT_THREADCALL vcr_track_thread(void *userdata)
continue;
}
- index++; // Count of packets consumed.
+ index++; // Count of packets consumed, also increment for WHOLE_FILE mode.
+#ifndef VCR_BUFFER_WHOLE_FILE
nn_packet_stream_return_packets(vcr->data, al_array_offset(track->cache.cache, 0), index);
al_array_remove_range(track->cache.cache, 0, index);
+#endif
nn_packet_cache_unlock(&track->cache);
@@ -153,7 +155,9 @@ static nn_thread_result NNWT_THREADCALL vcr_track_thread(void *userdata)
if (corked) {
// The cache is already unlocked here.
+#ifndef VCR_BUFFER_WHOLE_FILE
index = 0;
+#endif
} else {
#ifndef VCR_BUFFER_WHOLE_FILE
al_assert(index == packets);
diff --git a/src/libsink/desktop.c b/src/libsink/desktop.c
index 2bbe906..a2d02c9 100644
--- a/src/libsink/desktop.c
+++ b/src/libsink/desktop.c
@@ -8,8 +8,8 @@
#else
#include "../mixer/audio_miniaudio.h"
#endif
-#if defined CAMU_RENDERER_TIGER
-#include "../render/renderer_tiger.h"
+#if defined CAMU_RENDERER_MOMO
+#include "../render/renderer_momo.h"
#elif defined CAMU_RENDERER_LIBPLACEBO
#include "../render/renderer_libplacebo.h"
#endif
@@ -111,8 +111,9 @@ static u8 sink_callback(void *userdata, u8 op, u8 type, void *opaque)
}
static char status[64];
-static void log_playback_pos(struct camu_sink *sink)
+static void log_sink_status(struct camu_desktop *c)
{
+ struct camu_sink *sink = &c->sink;
struct camu_sink_entry *current = camu_sink_get_current(sink);
if (!current) {
camu_sink_return_current(sink);
@@ -140,10 +141,10 @@ static void log_playback_pos(struct camu_sink *sink)
offset += al_snprintf(status + offset, sizeof(status) - offset, "]");
status[offset] = '\0';
- log_info("%s", status);
+ log_info("%s, window size: %ux%u", status, c->scr.width, c->scr.height);
return;
notplaying:
- log_info("Not playing.");
+ log_info("Not playing, window size: %ux%u", c->scr.width, c->scr.height);
}
static void screen_callback(void *userdata, u8 op, void *opaque)
@@ -175,7 +176,7 @@ static void screen_callback(void *userdata, u8 op, void *opaque)
camu_sink_shuffle(&c->sink);
break;
case CAMU_SCREEN_STATUS:
- log_playback_pos(&c->sink);
+ log_sink_status(c);
break;
#ifdef CAMU_SCREEN_DEBUG_KEY
case CAMU_SCREEN_DEBUG:
@@ -199,8 +200,8 @@ bool camu_desktop_open(struct camu_desktop *c, const char *window_name)
if (!camu_screen_init(&c->scr) || !camu_screen_create_window(&c->scr, window_name)) {
return false;
}
-#if defined CAMU_RENDERER_TIGER
- c->renderer = camu_renderer_tiger_create();
+#if defined CAMU_RENDERER_MOMO
+ c->renderer = camu_renderer_momo_create();
#elif defined CAMU_RENDERER_LIBPLACEBO
c->renderer = camu_renderer_lp_create();
#endif
diff --git a/src/libsink/sink.c b/src/libsink/sink.c
index 07bb604..56be556 100644
--- a/src/libsink/sink.c
+++ b/src/libsink/sink.c
@@ -468,18 +468,17 @@ static void mixer_callback(void *userdata, u8 op)
struct camu_sink *sink = (struct camu_sink *)userdata;
if (op == CAMU_MIXER_EMPTY) {
log_info("Mixer empty.");
-#ifndef LIANA_LIST_SCUFFED_LOOP
// We need to sync with do_add_entry() because the order of
// the START/STOP's in the queue matters.
nn_mutex_lock(&sink->lock);
- queue_cmd(sink, (struct camu_sink_cmd){
- .op = STOP,
- .value.i = CAMU_SINK_AUDIO
- });
+ // This feels a bit too loose.
+ if (!(sink->current && AUDIO_STATE(sink->current) == BUFFER_ADDED)) {
+ queue_cmd(sink, (struct camu_sink_cmd){
+ .op = STOP,
+ .value.i = CAMU_SINK_AUDIO
+ });
+ }
nn_mutex_unlock(&sink->lock);
-#else
- (void)sink;
-#endif
}
}
@@ -1526,11 +1525,15 @@ static struct nn_rpc_command commands[] = {
{ .op = CAMU_SINK_SEEK, .callback = seek_command_callback, .userdata = NULL }
};
+// @TODO: Send sink id from list.
static void identify_callback(void *userdata, struct nn_rpc_connection *conn, struct nn_packet *packet)
{
struct camu_sink *sink = (struct camu_sink *)userdata;
- (void)sink;
- // @TODO: Send sink id from list.
+ if (sink->type == NNWT_SOCKET_UNIX) {
+ log_info("Sink connected to %.*s.", al_str_x(&sink->addr));
+ } else {
+ log_info("Sink connected to %.*s:%hu.", al_str_x(&sink->addr), sink->port);
+ }
nn_packet_stream_return_packet(conn->stream, packet);
}
diff --git a/src/mixer/audio_miniaudio.c b/src/mixer/audio_miniaudio.c
index 7e31abf..a0db3f3 100644
--- a/src/mixer/audio_miniaudio.c
+++ b/src/mixer/audio_miniaudio.c
@@ -27,6 +27,9 @@ static ma_backend backends[] = {
#ifdef MA_ENABLE_WASAPI
ma_backend_wasapi,
#endif
+#ifdef MA_ENABLE_DSOUND
+ ma_backend_dsound,
+#endif
#ifdef MA_ENABLE_AAUDIO
ma_backend_aaudio,
#endif
@@ -142,7 +145,7 @@ static void audio_miniaudio_pick_format(struct camu_audio *audio, struct camu_re
fmt->req.sample_rate = ma->device.playback.internalSampleRate;
u32 channels = ma->device.playback.channels;
#ifdef CAMU_HAVE_FFMPEG
- av_channel_layout_default(&fmt->req.channel_layout, channels);
+ camu_default_channel_layout(&fmt->req.channel_layout, channels);
#endif
fmt->req.channel_count = channels;
}
@@ -162,7 +165,7 @@ static void data_callback(ma_device *device, void *output, const void *input, u3
#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 8
#else
#define DEFAULT_PERIODS 3
-#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 48
+#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 64
#endif
static bool audio_miniaudio_configure_stream(struct camu_audio *audio, void *opaque)
diff --git a/src/mixer/audio_null.c b/src/mixer/audio_null.c
index a6eeea3..2fa5ddb 100644
--- a/src/mixer/audio_null.c
+++ b/src/mixer/audio_null.c
@@ -15,7 +15,7 @@ static void audio_null_pick_format(struct camu_audio *audio, struct camu_resampl
fmt->req.format = fmt->in.format;
fmt->req.channel_count = fmt->in.channel_count;
#ifdef CAMU_HAVE_FFMPEG
- av_channel_layout_default(&fmt->req.channel_layout, fmt->in.channel_count);
+ camu_default_channel_layout(&fmt->req.channel_layout, fmt->in.channel_count);
#endif
fmt->req.sample_rate = fmt->in.sample_rate;
}
diff --git a/src/mixer/meson.build b/src/mixer/meson.build
index c09f779..e4840c1 100644
--- a/src/mixer/meson.build
+++ b/src/mixer/meson.build
@@ -22,7 +22,11 @@ if use_miniaudio
mixer_deps += [libpulse, alsa]
mixer_args += ['-DMA_ENABLE_ALSA', '-DMA_ENABLE_PULSEAUDIO', '-DMA_NO_RUNTIME_LINKING']
elif is_windows
- mixer_args += ['-DMA_ENABLE_WASAPI']
+ if get_option('win32-compat')
+ mixer_args += ['-DMA_ENABLE_DSOUND']
+ else
+ mixer_args += ['-DMA_ENABLE_WASAPI']
+ endif
elif is_android
mixer_args += ['-DMA_ENABLE_AAUDIO']
endif
diff --git a/src/render/meson.build b/src/render/meson.build
index 98b86ec..7e3e394 100644
--- a/src/render/meson.build
+++ b/src/render/meson.build
@@ -2,23 +2,20 @@ render_src = []
render_deps = []
render_args = []
-if get_option('renderer') == 'tiger'
- render_src += ['renderer_tiger.c', 'queue_tiger.c']
- linmath_h = subproject('linmath.h').get_variable('linmath_h')
- render_deps += [linmath_h]
- libm = compiler.find_library('m', required: false)
- if libm.found()
- render_deps += [libm]
- endif
- render_args += ['-DCAMU_RENDERER_TIGER']
+if get_option('renderer') == 'momo'
+ render_src += ['renderer_momo.c', 'queue_momo.c']
+ subdir('momo')
+ render_deps += [momo]
+ render_args += ['-DCAMU_RENDERER_MOMO']
elif get_option('renderer') == 'libplacebo'
libplacebo_opts = ['warning_level=2', 'demos=false', 'tests=false', 'bench=false', 'fuzz=false',
'glslang=disabled',
'gl-proc-addr=disabled',
'vk-proc-addr=disabled',
- 'lcms=disabled',
- 'dovi=disabled',
- 'libdovi=disabled'
+ 'lcms=auto',
+ 'dovi=auto',
+ 'libdovi=auto',
+ 'xxhash=auto'
]
if get_option('renderer-api') == 'vulkan' or get_option('renderer-api') == 'dx11'
@@ -27,12 +24,19 @@ elif get_option('renderer') == 'libplacebo'
render_deps += [shaderc]
else
shaderc_opts = cmake.subproject_options()
+ shaderc_opts.set_override_option('warning_level', '0') # Doesn't work.
reltype = is_minsize ? 'MinSizeRel' : 'Release'
shaderc_opts.add_cmake_defines({ 'CMAKE_BUILD_TYPE': is_debug ? 'Debug' : reltype })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_INSTALL': true })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_TESTS': true })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_EXAMPLES': true })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_COPYRIGHT_CHECK': true })
+ shaderc_opts.add_cmake_defines({ 'ENABLE_GLSLANG_BINARIES': false })
+ shaderc_opts.add_cmake_defines({ 'ENABLE_SPVREMAPPER': false })
+ shaderc_opts.add_cmake_defines({ 'ENABLE_HLSL': false })
+ spirv_optimizer = true
+ shaderc_opts.add_cmake_defines({ 'ENABLE_OPT': spirv_optimizer })
+ 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)
@@ -43,20 +47,31 @@ elif get_option('renderer') == 'libplacebo'
shaderc_proj.dependency('OSDependent'),
shaderc_proj.dependency('GenericCodeGen'),
shaderc_proj.dependency('SPIRV'),
- shaderc_proj.dependency('SPIRV-Tools-opt'),
shaderc_proj.dependency('SPIRV-Tools-static')
]
+ if spirv_optimizer
+ render_deps += [
+ shaderc_proj.dependency('SPIRV-Tools-opt'),
+ ]
+ endif
endif
#glslang = dependency('glslang', required: false, allow_fallback: false)
#if glslang.found()
# render_deps += [glslang]
#else
+ # #spirv_tools_opts = cmake.subproject_options()
+ # #spirv_tools_opts.set_override_option('warning_level', '0')
+ # #reltype = is_minsize ? 'MinSizeRel' : 'Release'
+ # #spirv_tools_opts.add_cmake_defines({ 'CMAKE_BUILD_TYPE': is_debug ? 'Debug' : reltype })
+ # #spirv_tools_proj = cmake.subproject('SPIRV-Tools', options: spirv_tools_opts)
# glslang_opts = cmake.subproject_options()
+ # glslang_opts.set_override_option('warning_level', '0')
# reltype = is_minsize ? 'MinSizeRel' : 'Release'
# glslang_opts.add_cmake_defines({ 'CMAKE_BUILD_TYPE': is_debug ? 'Debug' : reltype })
+ # #glslang_opts.add_cmake_defines({ 'ALLOW_EXTERNAL_SPIRV_TOOLS': true })
# glslang_opts.add_cmake_defines({ 'ENABLE_OPT': '0' })
# glslang_proj = cmake.subproject('glslang', options: glslang_opts)
- # message('CMake targets:\n - ' + '\n - '.join(glslang_proj.target_list()))
+ # #message('CMake targets:\n - ' + '\n - '.join(glslang_proj.target_list()))
# glslang = glslang_proj.dependency('glslang')
# spirv = glslang_proj.dependency('SPIRV')
# glslang_default_resource_limits = glslang_proj.dependency('glslang-default-resource-limits')
@@ -118,22 +133,27 @@ if get_option('subtitles').enabled()
default_options: [
'doc=disabled',
'nls=disabled',
- 'tests=disabled',
'tools=disabled',
'cache-build=disabled'
])
+ else
+ libass_opts += ['directwrite=enabled']
endif
# libass(e46aede):meson.build:84
# fontconfig(72b9a48):meson.build:28
freetype = dependency('freetype2',
version: '>=9.17.3',
default_options: [
- 'harfbuzz=disabled'
+ 'warning_level=0',
+ 'harfbuzz=disabled',
+ 'png=disabled'
])
# libass(e46aede):meson.build:90
fribidi = dependency('fribidi',
version: '>=0.19.1',
default_options: [
+ 'warning_level=0',
+ 'c_args=-Wno-stringop-overflow', # This doesn't work.
'docs=false',
'tests=false',
'bin=false'
@@ -143,7 +163,6 @@ if get_option('subtitles').enabled()
version: '>=2.0.0',
default_options: [
'freetype=disabled',
- 'tests=disabled',
'introspection=disabled',
'docs=disabled',
'utilities=disabled',
diff --git a/src/render/momo/meson.build b/src/render/momo/meson.build
new file mode 100644
index 0000000..092293a
--- /dev/null
+++ b/src/render/momo/meson.build
@@ -0,0 +1,12 @@
+momo_src = ['momo.c']
+momo_deps = []
+momo_args = []
+
+libm = compiler.find_library('m', required: false)
+if libm.found()
+ momo_deps += [libm]
+endif
+linmath_h = subproject('linmath.h').get_variable('linmath_h')
+momo_deps += [linmath_h]
+
+momo = declare_dependency(sources: momo_src, dependencies: momo_deps, compile_args: momo_args)
diff --git a/src/render/momo/momo.c b/src/render/momo/momo.c
new file mode 100644
index 0000000..5239efd
--- /dev/null
+++ b/src/render/momo/momo.c
@@ -0,0 +1,35 @@
+#define AL_LOG_SECTION "momo"
+#include <al/log.h>
+
+#include "momo.h"
+
+bool MOMO_Init(MOMO_Renderer *mmr,
+#ifdef STELA_API_OPENGL
+ bool (*MakeCurrent)(void *),
+ void (*ReleaseCurrent)(void *),
+ void (*SwapBuffers)(void *),
+#endif
+ void *Private)
+{
+ mmr->Private = Private;
+#ifdef STELA_API_OPENGL
+ mmr->GL.MakeCurrent = MakeCurrent;
+ mmr->GL.ReleaseCurrent = ReleaseCurrent;
+ mmr->GL.SwapBuffers = SwapBuffers;
+ mmr->GL.MakeCurrent(mmr->Private);
+ const char *gl_version = (const char *)glGetString(GL_VERSION);
+ if (gl_version) {
+ log_info("GL context version: %s.", gl_version);
+ } else {
+ log_warn("Somehow failed to retrive GL_VERSION.");
+ }
+#endif
+ return true;
+}
+
+void MOMO_Render(MOMO_Renderer *mmr)
+{
+#ifdef STELA_API_OPENGL
+ mmr->GL.SwapBuffers(mmr->Private);
+#endif
+}
diff --git a/src/render/momo/momo.h b/src/render/momo/momo.h
new file mode 100644
index 0000000..76686ba
--- /dev/null
+++ b/src/render/momo/momo.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <al/types.h>
+
+#ifdef STELA_API_OPENGL
+#include <stl/gl.h>
+#endif
+
+typedef struct {
+ struct {
+ bool (*MakeCurrent)(void *);
+ void (*ReleaseCurrent)(void *);
+ void (*SwapBuffers)(void *);
+ } GL;
+ void *Private;
+} MOMO_Renderer;
+
+bool MOMO_Init(MOMO_Renderer *mmr,
+#ifdef STELA_API_OPENGL
+ bool (*MakeCurrent)(void *),
+ void (*ReleaseCurrent)(void *),
+ void (*SwapBuffers)(void *),
+#endif
+ void *Private);
+void MOMO_Render(MOMO_Renderer *mmr);
diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c
index 7fe9258..5932944 100644
--- a/src/render/queue_libplacebo.c
+++ b/src/render/queue_libplacebo.c
@@ -30,6 +30,7 @@ static bool queue_lp_configure_subtitles(struct camu_frame_queue *queue, u32 wid
ass_set_frame_size(lq->ass_renderer, width, height);
ass_set_storage_size(lq->ass_renderer, width, height);
ass_set_fonts(lq->ass_renderer, NULL, NULL, ASS_FONTPROVIDER_AUTODETECT, NULL, 0);
+ ass_set_hinting(lq->ass_renderer, ASS_HINTING_NONE);
AVCodecParameters *codecpar = stream->av.stream->codecpar;
ass_process_codec_private(lq->ass_track, (const char *)codecpar->extradata,
codecpar->extradata_size);
diff --git a/src/render/queue_momo.c b/src/render/queue_momo.c
new file mode 100644
index 0000000..8e8d7e3
--- /dev/null
+++ b/src/render/queue_momo.c
@@ -0,0 +1,68 @@
+#include "queue_momo.h"
+
+static void queue_momo_push(struct camu_frame_queue *queue, struct camu_codec_frame *frame, f64 pts)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)queue;
+ (void)mq;
+ (void)pts;
+ camu_codec_frame_discard(frame);
+}
+
+#ifdef CAMU_HAVE_FFMPEG
+static void queue_momo_push_av_frame(struct camu_frame_queue *queue, AVFrame *frame, f64 pts)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)queue;
+ (void)mq;
+ (void)pts;
+ av_frame_free(&frame);
+}
+#endif
+
+static void queue_momo_flush(struct camu_frame_queue *queue)
+{
+ (void)queue;
+}
+
+static s32 queue_momo_count(struct camu_frame_queue *queue)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)queue;
+ (void)mq;
+ return 1;
+}
+
+static u8 queue_momo_read(struct camu_frame_queue *queue, f64 pts, void *out)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)queue;
+ (void)mq;
+ (void)pts;
+ (void)out;
+ return CAMU_QUEUE_OK;
+}
+
+static void queue_momo_reset(struct camu_frame_queue *queue)
+{
+ struct camu_frame_queue_momo *tq = (struct camu_frame_queue_momo *)queue;
+ (void)tq;
+}
+
+static void queue_momo_free(struct camu_frame_queue **queue)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)*queue;
+ al_free(mq);
+ *queue = NULL;
+}
+
+struct camu_frame_queue *camu_frame_queue_momo_create(void)
+{
+ struct camu_frame_queue_momo *mq = al_alloc_object(struct camu_frame_queue_momo);
+ mq->q.push = queue_momo_push;
+#ifdef CAMU_HAVE_FFMPEG
+ mq->q.push_av_frame = queue_momo_push_av_frame;
+#endif
+ mq->q.flush = queue_momo_flush;
+ mq->q.count = queue_momo_count;
+ mq->q.read = queue_momo_read;
+ mq->q.reset = queue_momo_reset;
+ mq->q.free = queue_momo_free;
+ return (struct camu_frame_queue *)mq;
+}
diff --git a/src/render/queue_momo.h b/src/render/queue_momo.h
new file mode 100644
index 0000000..c4bf5d1
--- /dev/null
+++ b/src/render/queue_momo.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "../buffer/frame_queue.h"
+
+struct camu_frame_queue_momo {
+ struct camu_frame_queue q;
+};
+
+struct camu_frame_queue *camu_frame_queue_momo_create(void);
diff --git a/src/render/queue_tiger.c b/src/render/queue_tiger.c
deleted file mode 100644
index df072d2..0000000
--- a/src/render/queue_tiger.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <al/lib.h>
-#include <stl/gl.h>
-
-#include "queue_tiger.h"
-
-#define GL_UNPACK_ROW_LENGTH 0x0CF2
-
-static void upload_texture(struct camu_frame_queue_tiger *tq, u8 *data, u32 width, u32 height, s32 format, s32 linesize)
-{
- glGenTextures(1, &tq->texture_id);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, tq->texture_id);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- //if (frame->flags & CAMU_FRAME_DEVICE_ALLOCATED) {
- // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tq->tr->texture_buffer);
- //}
- glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 0);
- switch (format) {
- case CAMU_PIXEL_FORMAT_RGBA:
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
- 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
- break;
- case CAMU_PIXEL_FORMAT_RGB:
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
- 0, GL_RGB, GL_UNSIGNED_BYTE, data);
- break;
- default:
- al_assert(false);
- }
- //glGenerateMipmap(GL_TEXTURE_2D);
-}
-
-static void queue_tiger_push(struct camu_frame_queue *queue, struct camu_codec_frame *frame, f64 pts)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)pts;
- tq->queued_frame = frame;
-}
-
-#ifdef CAMU_HAVE_FFMPEG
-static void queue_tiger_push_av_frame(struct camu_frame_queue *queue, AVFrame *frame, f64 pts)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)pts;
- tq->queued_av_frame = frame;
-}
-#endif
-
-static void queue_tiger_flush(struct camu_frame_queue *queue)
-{
- (void)queue;
-}
-
-static s32 queue_tiger_count(struct camu_frame_queue *queue)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)tq;
- return 1;
-}
-
-static u8 queue_tiger_read(struct camu_frame_queue *queue, f64 pts, void *out)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)pts;
- if (tq->queued_frame) {
- struct camu_codec_frame *frame = tq->queued_frame;
- s32 linesize = frame->video.width;
- upload_texture(tq, frame->data, frame->video.width, frame->video.height, frame->format, linesize);
- camu_codec_frame_discard(frame);
- tq->queued_frame = NULL;
- tq->uploaded = true;
- }
-#ifdef CAMU_HAVE_FFMPEG
- if (tq->queued_av_frame) {
- AVFrame *frame = tq->queued_av_frame;
- s32 linesize = frame->linesize[0];
- switch (frame->format) {
- case CAMU_PIXEL_FORMAT_RGBA:
- linesize /= 4;
- break;
- case CAMU_PIXEL_FORMAT_RGB:
- linesize /= 3;
- break;
- }
- upload_texture(tq, frame->data[0], frame->width, frame->height, frame->format, linesize);
- av_frame_free(&frame);
- tq->queued_av_frame = NULL;
- tq->uploaded = true;
- }
-#endif
- if (!tq->uploaded) return CAMU_QUEUE_MORE;
- *((GLuint *)out) = tq->texture_id;
- return CAMU_QUEUE_OK;
-}
-
-static void queue_tiger_reset(struct camu_frame_queue *queue)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)tq;
-}
-
-static void queue_tiger_free(struct camu_frame_queue **queue)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)*queue;
- glDeleteTextures(1, &tq->texture_id);
- al_free(tq);
- *queue = NULL;
-}
-
-struct camu_frame_queue *camu_frame_queue_tiger_create(void)
-{
- struct camu_frame_queue_tiger *tq = al_alloc_object(struct camu_frame_queue_tiger);
- tq->queued_frame = NULL;
- tq->queued_av_frame = NULL;
- tq->uploaded = false;
- tq->q.push = queue_tiger_push;
-#ifdef CAMU_HAVE_FFMPEG
- tq->q.push_av_frame = queue_tiger_push_av_frame;
-#endif
- tq->q.flush = queue_tiger_flush;
- tq->q.count = queue_tiger_count;
- tq->q.read = queue_tiger_read;
- tq->q.reset = queue_tiger_reset;
- tq->q.free = queue_tiger_free;
- return (struct camu_frame_queue *)tq;
-}
diff --git a/src/render/queue_tiger.h b/src/render/queue_tiger.h
deleted file mode 100644
index af0e229..0000000
--- a/src/render/queue_tiger.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include <stl/gl.h>
-
-#include "../buffer/frame_queue.h"
-
-struct camu_frame_queue_tiger {
- struct camu_frame_queue q;
- GLuint texture_id;
- struct camu_renderer_tiger *tr;
- struct camu_codec_frame *queued_frame;
-#ifdef CAMU_HAVE_FFMPEG
- struct AVFrame *queued_av_frame;
-#endif
- bool uploaded;
-};
-
-struct camu_frame_queue *camu_frame_queue_tiger_create(void);
diff --git a/src/render/renderer.h b/src/render/renderer.h
index 1e6ffc0..d2590b1 100644
--- a/src/render/renderer.h
+++ b/src/render/renderer.h
@@ -7,14 +7,9 @@
#endif
#if defined STELA_API_OPENGL
-#define CAMU_RENDERER_OPENGL
#ifdef STELA_USE_EGL
#include <stl/egl.h>
#endif
-#elif defined STELA_API_VULKAN
-#define CAMU_RENDERER_VULKAN
-#elif defined STELA_API_DX11
-#define CAMU_RENDERER_DX11
#endif
#include "../codec/codec.h"
@@ -24,28 +19,32 @@ enum {
CAMU_SCALING_NEAREST
};
+enum {
+ CAMU_BACKGROUND_DEFAULT = 0,
+ CAMU_BACKGROUND_TRANSPARENT
+};
+
struct camu_frame_queue;
struct camu_screen;
struct camu_renderer {
bool (*create_renderer)(
struct camu_renderer *, u32 *, u32 *,
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *),
VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *),
const char *const *(*vk_get_extensions)(u32 *),
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
HWND win32_window,
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
#ifdef STELA_USE_EGL
EGLDisplay display,
EGLContext context,
#endif
- void (*get_gl_proc_address(char const *procname))(void),
+ void (*get_gl_proc_address(char const *))(void),
bool (*gl_load_loader)(void *),
bool (*gl_make_current)(void *),
void (*gl_release_current)(void *),
void (*gl_swap_buffers)(void *),
-#elif defined CAMU_RENDERER_DX11
#endif
void *priv);
struct camu_frame_queue *(*create_queue)(struct camu_renderer *);
@@ -54,6 +53,7 @@ struct camu_renderer {
void (*resize)(struct camu_renderer *, u32 *, u32 *);
void (*set_fullscreen)(struct camu_renderer *, bool);
void (*set_scaling)(struct camu_renderer *, u8);
+ void (*set_background)(struct camu_renderer *, u8);
void (*render)(struct camu_renderer *, struct camu_screen *, bool);
#ifdef CAMU_HAVE_FFMPEG
s32 (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, s32 flags);
diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c
index a2105d6..bfe8c47 100644
--- a/src/render/renderer_libplacebo.c
+++ b/src/render/renderer_libplacebo.c
@@ -9,7 +9,7 @@
#include "../screen/screen.h"
#include "../util/color_palette.h"
-#ifdef CAMU_RENDERER_DX11
+#ifdef STELA_API_DX11
#include <nnwt/windows.h>
#define COBJMACROS
#include <libplacebo/d3d11.h>
@@ -42,7 +42,7 @@ static void renderer_lp_resize(struct camu_renderer *renderer, u32 *width, u32 *
}
}
-#ifdef CAMU_RENDERER_DX11
+#ifdef STELA_API_DX11
static void renderer_lp_set_fullscreen(struct camu_renderer *renderer, bool fullscreen)
{
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
@@ -69,6 +69,21 @@ static void renderer_lp_set_scaling(struct camu_renderer *renderer, u8 mode)
}
}
+static void renderer_lp_set_background(struct camu_renderer *renderer, u8 mode)
+{
+ struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
+ switch (mode) {
+ case CAMU_BACKGROUND_DEFAULT:
+ clear_color[3] = 1.f;
+ lr->params.background = PL_CLEAR_TILES;
+ break;
+ case CAMU_BACKGROUND_TRANSPARENT:
+ clear_color[3] = 0.f;
+ lr->params.background = PL_CLEAR_SKIP;
+ break;
+ }
+}
+
static void log_callback(void *userdata, enum pl_log_level level, const char *message)
{
(void)userdata;
@@ -79,19 +94,34 @@ static void log_callback(void *userdata, enum pl_log_level level, const char *me
}
}
+#ifdef CAMU_HAVE_SUBTITLES
+// level = 0(FATAL)-7(VERBOSE).
+static void ass_log_callback(s32 level, const char *fmt, va_list args, void *userdata)
+{
+ (void)userdata;
+ if (level <= 1) {
+ al_logv(AL_LOG_ERROR, "ass", fmt, args);
+ } else {
+#ifdef AL_DEBUG
+ al_logv(AL_LOG_DEBUG, "ass", fmt, args);
+#endif
+ }
+}
+#endif
+
static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *width, u32 *height,
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *),
VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *),
const char *const *(*vk_get_extensions)(u32 *),
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
HWND win32_window,
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
#ifdef STELA_USE_EGL
EGLDisplay display,
EGLContext context,
#endif
- void (*get_gl_proc_address(char const *procname))(void),
+ void (*get_gl_proc_address(char const *))(void),
bool (*gl_load_loader)(void *),
bool (*gl_make_current)(void *),
void (*gl_release_current)(void *),
@@ -111,13 +141,18 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
clear_color[2] = 255.f;
*/
+//#define LIBPLACEBO_LOG_TRACE
lr->logger = pl_log_create(PL_API_VER, pl_log_params(
.log_cb = log_callback,
.log_priv = NULL,
+#ifdef LIBPLACEBO_LOG_TRACE
+ .log_level = PL_LOG_TRACE
+#else
.log_level = PL_LOG_INFO
+#endif
));
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
VkResult err;
u32 num;
@@ -153,6 +188,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
lr->swapchain = pl_vulkan_create_swapchain(lr->vk, pl_vulkan_swapchain_params(
.surface = lr->surface,
.present_mode = VK_PRESENT_MODE_FIFO_KHR
+ //.present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR
));
if (!lr->swapchain) {
log_error("Failed to create vulkan swapchain.");
@@ -162,7 +198,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
lr->gpu = lr->vk->gpu;
log_info("Using Vulkan.");
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
(void)priv;
lr->d3d11 = pl_d3d11_create(lr->logger, pl_d3d11_params(
.debug = false
@@ -183,7 +219,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
lr->gpu = lr->d3d11->gpu;
log_info("Using DirectX 11.");
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
(void)gl_load_loader;
lr->gl = pl_opengl_create(lr->logger, pl_opengl_params(
.debug = false,
@@ -230,8 +266,17 @@ 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];
+ */
+
// Prioritize a more consistent image.
lr->params.correct_subpixel_offsets = true;
+ //lr->params.distort_params = pl_distort_params(.unscaled = false);
#if 0
struct nn_file file;
@@ -254,6 +299,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
#ifdef CAMU_HAVE_SUBTITLES
lr->ass = ass_library_init();
+ ass_set_message_cb(lr->ass, ass_log_callback, lr);
#endif
lr->last_render_tick = nn_get_tick();
@@ -339,7 +385,7 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
if (mix.frames) {
// weighted is only set when read() returns QUEUE_OK.
do_gpu_finish |= weighted;
- // Terrible hack. Let's us distinguish single frames with the same dimensions.
+ // 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.
@@ -413,8 +459,8 @@ void renderer_lp_free(struct camu_renderer **renderer)
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)*renderer;
if (lr->renderer) pl_renderer_destroy(&lr->renderer);
if (lr->swapchain) pl_swapchain_destroy(&lr->swapchain);
-#if defined CAMU_RENDERER_VULKAN
-#elif defined CAMU_RENDERER_OPENGL
+#if defined STELA_API_VULKAN
+#elif defined STELA_API_OPENGL
if (lr->gl) pl_opengl_destroy(&lr->gl);
#endif
if (lr->logger) pl_log_destroy(&lr->logger);
@@ -433,12 +479,13 @@ struct camu_renderer *camu_renderer_lp_create(void)
lr->r.add_font = renderer_lp_add_font;
lr->r.get_latency = renderer_lp_get_latency;
lr->r.resize = renderer_lp_resize;
-#ifdef CAMU_RENDERER_DX11
+#ifdef STELA_API_DX11
lr->r.set_fullscreen = renderer_lp_set_fullscreen;
#else
lr->r.set_fullscreen = NULL;
#endif
lr->r.set_scaling = renderer_lp_set_scaling;
+ lr->r.set_background = renderer_lp_set_background;
lr->r.render = renderer_lp_render;
lr->r.free = renderer_lp_free;
return (struct camu_renderer *)lr;
diff --git a/src/render/renderer_libplacebo.h b/src/render/renderer_libplacebo.h
index 7b1cfa2..a0125ba 100644
--- a/src/render/renderer_libplacebo.h
+++ b/src/render/renderer_libplacebo.h
@@ -10,23 +10,23 @@
#include "renderer.h"
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
#include <libplacebo/vulkan.h>
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
#include <libplacebo/d3d11.h>
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
#include <libplacebo/opengl.h>
#endif
struct camu_renderer_lp {
struct camu_renderer r;
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
VkSurfaceKHR surface;
pl_vulkan vk;
pl_vk_inst vk_inst;
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
pl_d3d11 d3d11;
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
pl_opengl gl;
#endif
pl_gpu gpu;
diff --git a/src/render/renderer_momo.c b/src/render/renderer_momo.c
new file mode 100644
index 0000000..9f217bf
--- /dev/null
+++ b/src/render/renderer_momo.c
@@ -0,0 +1,97 @@
+#define AL_LOG_SECTION "renderer_momo"
+#include <al/log.h>
+
+#include "renderer_momo.h"
+#include "queue_momo.h"
+
+static void renderer_momo_resize(struct camu_renderer *renderer, u32 *width, u32 *height)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)renderer;
+ (void)mr;
+ (void)width;
+ (void)height;
+}
+
+static bool renderer_momo_create_renderer(struct camu_renderer *renderer, u32 *width, u32 *height,
+#if defined STELA_API_OPENGL
+#ifdef STELA_USE_EGL
+ EGLDisplay display,
+ EGLContext context,
+#endif
+ void (*get_gl_proc_address(char const *))(void),
+ bool (*gl_load_loader)(void *),
+ bool (*gl_make_current)(void *),
+ void (*gl_release_current)(void *),
+ void (*gl_swap_buffers)(void *),
+#endif
+ void *priv)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)renderer;
+ (void)width;
+ (void)height;
+#if defined STELA_API_OPENGL
+#ifdef STELA_USE_EGL
+ (void)display;
+ (void)context;
+#endif
+ (void)get_gl_proc_address;
+ (void)gl_load_loader;
+ MOMO_Init(&mr->mmr, gl_make_current, gl_release_current, gl_swap_buffers, priv);
+#endif
+#ifdef CAMU_HAVE_SUBTITLES
+ mr->ass = ass_library_init();
+ // Just to keep these linked in the exe for platform testing.
+ ASS_Renderer *ar = ass_renderer_init(mr->ass);
+ ASS_Track *at = ass_new_track(mr->ass);
+ (void)at;
+ u32 w = *width, h = *height;
+ ass_set_frame_size(ar, w, h);
+ ass_set_storage_size(ar, w, h);
+ ass_set_fonts(ar, NULL, NULL, ASS_FONTPROVIDER_AUTODETECT, NULL, 0);
+ ass_set_hinting(ar, ASS_HINTING_NONE);
+#endif
+ return true;
+}
+
+static struct camu_frame_queue *renderer_momo_create_queue(struct camu_renderer *renderer)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)renderer;
+ struct camu_frame_queue *q = camu_frame_queue_momo_create();
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)q;
+ (void)mr;
+ (void)mq;
+ return q;
+}
+
+static u32 renderer_momo_get_latency(struct camu_renderer *renderer)
+{
+ (void)renderer;
+ return 0;
+}
+
+static void renderer_momo_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)renderer;
+ (void)scr;
+ (void)force;
+ MOMO_Render(&mr->mmr);
+}
+
+static void renderer_momo_free(struct camu_renderer **renderer)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)*renderer;
+ al_free(mr);
+ *renderer = NULL;
+}
+
+struct camu_renderer *camu_renderer_momo_create(void)
+{
+ struct camu_renderer_momo *mr = al_alloc_object(struct camu_renderer_momo);
+ mr->r.create_renderer = renderer_momo_create_renderer;
+ mr->r.create_queue = renderer_momo_create_queue;
+ mr->r.get_latency = renderer_momo_get_latency;
+ mr->r.resize = renderer_momo_resize;
+ mr->r.render = renderer_momo_render;
+ mr->r.free = renderer_momo_free;
+ return (struct camu_renderer *)mr;
+}
diff --git a/src/render/renderer_momo.h b/src/render/renderer_momo.h
new file mode 100644
index 0000000..3b9084b
--- /dev/null
+++ b/src/render/renderer_momo.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#ifdef CAMU_HAVE_SUBTITLES
+#include <ass/ass.h>
+#endif
+
+#include "momo/momo.h"
+
+#include "renderer.h"
+
+struct camu_renderer_momo {
+ struct camu_renderer r;
+ MOMO_Renderer mmr;
+#ifdef CAMU_HAVE_SUBTITLES
+ ASS_Library *ass;
+#endif
+};
+
+struct camu_renderer *camu_renderer_momo_create(void);
diff --git a/src/render/renderer_tiger.c b/src/render/renderer_tiger.c
deleted file mode 100644
index eb99e0c..0000000
--- a/src/render/renderer_tiger.c
+++ /dev/null
@@ -1,320 +0,0 @@
-#define AL_LOG_SECTION "renderer_tiger"
-#include <al/log.h>
-#include <al/lib.h>
-#include <linmath.h>
-
-#include "../screen/view.h"
-#include "../screen/screen.h"
-#include "../util/color_palette.h"
-
-#include "renderer_tiger.h"
-#include "queue_tiger.h"
-
-#ifdef CAMU_RENDERER_OPENGL
-static const GLfloat default_vertices[] = {
- 0.f, 0.f, 0.f, 0.f, 0.f,
- 0.f, 1.f, 0.f, 0.f, 1.f,
- 1.f, 0.f, 0.f, 1.f, 0.f,
- 1.f, 0.f, 0.f, 1.f, 0.f,
- 0.f, 1.f, 0.f, 0.f, 1.f,
- 1.f, 1.f, 0.f, 1.f, 1.f
-};
-
-static GLfloat clear_color[4] = { 0.f, 0.f, 0.f, 1.f };
-
-static const GLchar *default_vs = \
- "#version 100\n" \
- "attribute vec3 a_Position;\n" \
- "attribute vec2 a_TexCoord;\n" \
- "varying vec2 v_TexCoord;\n" \
- "uniform mat4 g_ModelViewProjectionMatrix;\n" \
- "void main() {\n" \
- " gl_Position = g_ModelViewProjectionMatrix * vec4(a_Position, 1.0);\n" \
- " v_TexCoord = a_TexCoord;\n" \
- "}";
-
-static const GLchar *default_fs = \
- "#version 100\n" \
- "precision mediump float;\n" \
- "varying vec2 v_TexCoord;\n" \
- "uniform sampler2D g_Texture0;\n" \
- "void main() {\n" \
- " gl_FragColor = texture2D(g_Texture0, v_TexCoord);\n" \
- "}";
-
-static bool compile(GLuint shader, const GLchar *source, GLchar *error)
-{
- glShaderSource(shader, 1, &source, 0);
- glCompileShader(shader);
-
- GLint status;
-
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
-
- if (status == GL_FALSE) {
- glGetShaderInfoLog(shader, 256, NULL, error);
- return false;
- }
-
- return true;
-}
-
-static bool compile_shaders(struct camu_renderer_tiger *tr)
-{
- tr->program = glCreateProgram();
-
- GLchar error[256];
-
- GLuint vs_shader = glCreateShader(GL_VERTEX_SHADER);
- if (!compile(vs_shader, default_vs, error)) {
- log_error("Failed to compile vertex shader (%.*s)", sizeof(error), error);
- return false;
- }
-
- GLuint fs_shader = glCreateShader(GL_FRAGMENT_SHADER);
- if (!compile(fs_shader, default_fs, error)) {
- log_error("Failed to compile fragment shader (%.*s)", sizeof(error), error);
- return false;
- }
-
- glAttachShader(tr->program, vs_shader);
- glAttachShader(tr->program, fs_shader);
- glLinkProgram(tr->program);
-
- return true;
-}
-#endif
-
-static void renderer_tiger_resize(struct camu_renderer *renderer, u32 *width, u32 *height)
-{
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- (void)tr;
- (void)width;
- (void)height;
-}
-
-static bool renderer_tiger_create_renderer(struct camu_renderer *renderer, u32 *width, u32 *height,
-#if defined CAMU_RENDERER_VULKAN
- VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *),
- void (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *),
- const char *const *(*vk_get_extensions)(u32 *),
-#elif defined CAMU_RENDERER_OPENGL
-#ifdef STELA_USE_EGL
- EGLDisplay display,
- EGLContext context,
-#endif
- void (*get_gl_proc_address(char const *procname))(void),
- bool (*gl_load_loader)(void *),
- bool (*gl_make_current)(void *),
- void (*gl_release_current)(void *),
- void (*gl_swap_buffers)(void *),
-#endif
- void *priv)
-{
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- (void)width;
- (void)height;
-#ifdef CAMU_RENDERER_OPENGL
- (void)display;
- (void)context;
- (void)get_gl_proc_address;
-
- tr->load_loader = gl_load_loader;
- tr->make_current = gl_make_current;
- tr->release_current = gl_release_current;
- tr->swap_buffers = gl_swap_buffers;
- tr->priv = priv;
-
- tr->make_current(tr->priv);
-
- if (!tr->load_loader(tr->priv)) {
- return false;
- }
-
- clear_color[0] = ((global_color_palette.colors[0] >> 16) & 0xff) / 255.f;
- clear_color[1] = ((global_color_palette.colors[0] >> 8) & 0xff) / 255.f;
- clear_color[2] = ((global_color_palette.colors[0]) & 0xff) / 255.f;
-
- glClearColor(clear_color[0], clear_color[1], clear_color[2], 1.f);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glGenBuffers(1, &tr->vbo);
- glBindBuffer(GL_ARRAY_BUFFER, tr->vbo);
- glBufferData(GL_ARRAY_BUFFER, sizeof(default_vertices), default_vertices, GL_STATIC_DRAW);
-
- if (!compile_shaders(tr)) return false;
-
- glUseProgram(tr->program);
-
- GLint pos = glGetAttribLocation(tr->program, "a_Position");
- glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)0);
- if (stl_gl_check_error()) {
- log_error("glVertexAttribPointer returned error, use GLES context.");
- al_assert_and_return(false);
- }
- glEnableVertexAttribArray(pos);
- GLint texcoord = glGetAttribLocation(tr->program, "a_TexCoord");
- glVertexAttribPointer(texcoord, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)12);
- glEnableVertexAttribArray(texcoord);
-
- //glGenBuffers(1, &tr->texture_buffer);
-#endif
-
-#ifdef CAMU_HAVE_FFMPEG
- tr->r.get_buffer2 = NULL;
- tr->r.opaque = NULL;
-#endif
-
- return true;
-}
-
-static struct camu_frame_queue *renderer_tiger_create_queue(struct camu_renderer *renderer)
-{
-#ifdef CAMU_RENDERER_OPENGL
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- struct camu_frame_queue *q = camu_frame_queue_tiger_create();
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)q;
- tq->tr = tr;
- return q;
-#endif
-}
-
-static u32 renderer_tiger_get_latency(struct camu_renderer *renderer)
-{
- (void)renderer;
- return 0;
-}
-
-static void set_uniform(struct camu_renderer_tiger *tr, const GLchar *name,
- u8 type, void *value)
-{
-#ifdef CAMU_RENDERER_OPENGL
- GLint loc = glGetUniformLocation(tr->program, name);
- if (loc == -1) return;
-
- switch (type)
- {
- case TYPE_FLOAT:
- glUniform1f(loc, *((GLfloat *)value));
- break;
- case TYPE_SAMPLER2D:
- glUniform1i(loc, (GLuint)(*((GLfloat *)value)));
- break;
- case TYPE_VEC2:
- glUniform2fv(loc, 1, (GLfloat *)value);
- break;
- case TYPE_VEC3:
- glUniform3fv(loc, 1, (GLfloat *)value);
- break;
- case TYPE_VEC4:
- glUniform4fv(loc, 1, (GLfloat *)value);
- break;
- case TYPE_MAT4:
- glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat *)value);
- break;
- case TYPE_MAT3:
- glUniformMatrix3fv(loc, 1, GL_FALSE, (GLfloat *)value);
- break;
- case TYPE_INVALID:
- break;
- }
-#endif
-}
-
-static void renderer_tiger_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
-{
-#ifdef CAMU_RENDERER_OPENGL
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- (void)force;
-
- tr->make_current(tr->priv);
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- glUseProgram(tr->program);
- glBindBuffer(GL_ARRAY_BUFFER, tr->vbo);
- glActiveTexture(GL_TEXTURE0);
-
-#ifdef CAMU_SCREEN_THREADED
- if (al_atomic_load(u8)(&scr->queued, AL_ATOMIC_RELAXED)) {
- camu_screen_run_queue(scr);
- }
-#endif
-
- if (scr->videos.count > 0) {
- struct camu_screen_video *video = &al_array_last(scr->videos);
-
- GLuint texture_id;
- bool weighted;
- if (camu_video_buffer_read(video->buf, &texture_id, &weighted)) {
- glBindTexture(GL_TEXTURE_2D, texture_id);
-
- mat4x4 model;
- mat4x4_identity(model);
- mat4x4_ortho(model, 0.f, (f32)scr->width, (f32)scr->height, 0.f, -1.f, 1.f);
- mat4x4_translate_in_place(model, (f32)video->view.x_offset, (f32)video->view.y_offset, 0.f);
- mat4x4_scale_aniso(model, model, (f32)video->view.zoom, (f32)video->view.zoom, 1.f);
- mat4x4_scale_aniso(model, model, (f32)video->view.width, (f32)video->view.height, 1.f);
- set_uniform(tr, "g_ModelViewProjectionMatrix", TYPE_MAT4, model);
-
- GLuint texture0 = 0;
- set_uniform(tr, "g_Texture0", TYPE_SAMPLER2D, &texture0);
-
- glViewport(0, 0, scr->width, scr->height);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- }
- }
-
- tr->swap_buffers(tr->priv);
-#endif
-
- tr->release_current(tr->priv);
-}
-
-/*
-static void *renderer_tiger_get_device_ptr(struct camu_renderer *renderer, size_t length)
-{
- (void)renderer;
- (void)length;
- return NULL;
-#ifdef CAMU_RENDERER_OPENGL
- //struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- //glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tr->texture_buffer);
- //glBufferData(GL_PIXEL_UNPACK_BUFFER, length, NULL, GL_STREAM_DRAW);
- //return glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, length, GL_MAP_WRITE_BIT);
-#endif
-}
-
-static void renderer_tiger_commit_device_ptr(struct camu_renderer *renderer)
-{
- (void)renderer;
-#ifdef CAMU_RENDERER_OPENGL
- //struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- //glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tr->texture_buffer);
- //glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
-#endif
-}
-*/
-
-static void renderer_tiger_free(struct camu_renderer **renderer)
-{
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)*renderer;
- glDeleteProgram(tr->program);
- glDeleteBuffers(1, &tr->vbo);
- al_free(tr);
- *renderer = NULL;
-}
-
-struct camu_renderer *camu_renderer_tiger_create(void)
-{
- struct camu_renderer_tiger *tr = al_alloc_object(struct camu_renderer_tiger);
- tr->r.create_renderer = renderer_tiger_create_renderer;
- tr->r.create_queue = renderer_tiger_create_queue;
- tr->r.get_latency = renderer_tiger_get_latency;
- tr->r.resize = renderer_tiger_resize;
- tr->r.render = renderer_tiger_render;
- tr->r.free = renderer_tiger_free;
- return (struct camu_renderer *)tr;
-}
diff --git a/src/render/renderer_tiger.h b/src/render/renderer_tiger.h
deleted file mode 100644
index 5891c20..0000000
--- a/src/render/renderer_tiger.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-#include <stl/gl.h>
-
-#include "renderer.h"
-
-enum {
- TYPE_INVALID = 0,
- TYPE_FLOAT,
- TYPE_VEC4,
- TYPE_VEC3,
- TYPE_VEC2,
- TYPE_MAT4,
- TYPE_MAT3,
- TYPE_SAMPLER2D
-};
-
-struct camu_renderer_tiger {
- struct camu_renderer r;
- GLuint vao;
- GLuint vbo;
- GLuint program;
- GLuint texture_buffer;
- bool (*load_loader)(void *);
- bool (*make_current)(void *);
- void (*release_current)(void *);
- void (*swap_buffers)(void *);
- void *priv;
-};
-
-struct camu_renderer *camu_renderer_tiger_create(void);
diff --git a/src/screen/screen.c b/src/screen/screen.c
index 23afa7e..0ff5eec 100644
--- a/src/screen/screen.c
+++ b/src/screen/screen.c
@@ -51,7 +51,7 @@ static void do_resize(struct camu_screen *scr, u32 width, u32 height)
camu_view_calculate(&video->view, scr->width, scr->height);
}
// No buffers resize.
- al_atomic_store(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
+ al_atomic_add(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
}
static void resize_callback(void *userdata, u32 width, u32 height)
@@ -309,6 +309,18 @@ static bool key_callback(void *userdata, u8 state, u16 button)
log_info("Scaling filters enabled.");
}
return true;
+ case STELA_KEY_C:
+ scr->transparent_background = !scr->transparent_background;
+ if (scr->transparent_background) {
+ scr->renderer->set_background(scr->renderer, CAMU_BACKGROUND_TRANSPARENT);
+ log_info("Background transparent.");
+ } else {
+ scr->renderer->set_background(scr->renderer, CAMU_BACKGROUND_DEFAULT);
+ log_info("Background solid.");
+ }
+ // Force refresh for if there's no video buffer.
+ al_atomic_add(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
+ return true;
default:
break;
}
@@ -402,6 +414,7 @@ bool camu_screen_create_window(struct camu_screen *scr, const char *name)
scr->height = scr->window->height;
scr->fullscreen = false;
scr->scaling_disabled = false;
+ scr->transparent_background = false;
#ifdef STELA_EVENT_BUFFER
nn_thread_create(&scr->thread, event_thread, scr);
#endif
@@ -412,13 +425,13 @@ bool camu_screen_create_renderer(struct camu_screen *scr, struct camu_renderer *
{
scr->renderer = renderer;
return renderer->create_renderer(renderer, &scr->width, &scr->height,
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
scr->window->get_vk_proc_address,
scr->window->vk_create_surface,
scr->window->vk_get_extensions,
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
scr->window->win32_window,
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
#ifdef STELA_USE_EGL
scr->window->egl_display,
scr->window->egl_context,
@@ -587,14 +600,14 @@ void camu_screen_set_state(struct camu_screen *scr, s32 state)
if (al_atomic_load(s32)(&scr->state, AL_ATOMIC_ACQUIRE) != CAMU_SCREEN_STOPPED) {
al_atomic_store(s32)(&scr->state, state, AL_ATOMIC_RELEASE);
if (state == CAMU_SCREEN_PAUSED) {
- al_atomic_store(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
+ al_atomic_add(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
}
}
}
void camu_screen_force_refresh(struct camu_screen *scr)
{
- al_atomic_store(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
+ al_atomic_add(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
camu_screen_wake(scr);
}
@@ -622,13 +635,15 @@ bool camu_screen_tick(struct camu_screen *scr, bool *force)
{
s32 state = al_atomic_load(s32)(&scr->state, AL_ATOMIC_RELAXED);
al_assert(state != CAMU_SCREEN_STOPPED);
- bool paused = state == CAMU_SCREEN_PAUSED;
- bool do_render = camu_screen_poll(scr, paused) || !paused;
u32 force_refresh = al_atomic_load(u32)(&scr->force_refresh, AL_ATOMIC_ACQUIRE);
+ bool paused = state == CAMU_SCREEN_PAUSED && force_refresh == 0;
+ bool do_render = camu_screen_poll(scr, paused) || !paused;
+ // Should be AL_ATOMIC_ACQ_REL.
+ force_refresh = al_atomic_load(u32)(&scr->force_refresh, AL_ATOMIC_ACQUIRE);
do_render |= force_refresh > 0;
*force = force_refresh > 0;
if (force_refresh > 0) {
- al_atomic_store(u32)(&scr->force_refresh, 0, AL_ATOMIC_RELEASE);
+ al_atomic_sub(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELEASE);
}
return do_render;
}
diff --git a/src/screen/screen.h b/src/screen/screen.h
index 4ba07c2..afd2dee 100644
--- a/src/screen/screen.h
+++ b/src/screen/screen.h
@@ -64,6 +64,7 @@ struct camu_screen {
u32 height;
bool fullscreen;
bool scaling_disabled;
+ bool transparent_background;
u64 last_click_ts;
f64 last_mouse_y;
f64 last_mouse_x;
diff --git a/src/server/server.c b/src/server/server.c
index 6f8da78..ec99921 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -616,6 +616,7 @@ static u8 parse_resource_type(str *line)
return CAMU_RESOURCE_HTTP;
#else
if (0) {
+ (void)line;
#endif
#if CACHE_HAVE_CDIO
} else if (al_str_cmp(line, &al_str_c("cdda://"), 0, 7) == 0) {
@@ -812,7 +813,7 @@ static void connection_closed_callback(void *userdata, struct nn_rpc_connection
struct camu_server_sink *sink;
al_array_foreach(server->sinks, i, sink) {
if (sink->conn == conn) {
- log_info("Sink removed.");
+ log_info("Sink \"%.*s\" removed.", al_str_x(&sink->name));
struct lia_list *list;
al_array_foreach(server->lists, j, list) {
lia_list_remove_sink(list, sink);