modrinth-enhanced, modrinth-enhanced-bin: preload vblank shim for the full refresh rate on nvidia
This commit is contained in:
1 parent
7421d40fd2
commit
69d3249c8d
10 files changed
+519
-18
No files matched your search
@@ -1,7 +1,7 @@
|
|||||||
pkgbase = modrinth-enhanced-bin
|
pkgbase = modrinth-enhanced-bin
|
||||||
pkgdesc = Modrinth App without ads or telemetry, with offline and Ely.by accounts and Linux fixes (upstream binary)
|
pkgdesc = Modrinth App without ads or telemetry, with offline and Ely.by accounts and Linux fixes (upstream binary)
|
||||||
pkgver = 0.21.2
|
pkgver = 0.21.2
|
||||||
pkgrel = 1
|
pkgrel = 2
|
||||||
url = https://github.com/Felitendo/Modrinth-Enhanced
|
url = https://github.com/Felitendo/Modrinth-Enhanced
|
||||||
arch = x86_64
|
arch = x86_64
|
||||||
license = GPL-3.0-only
|
license = GPL-3.0-only
|
||||||
@@ -12,6 +12,7 @@ pkgbase = modrinth-enhanced-bin
|
|||||||
depends = glibc
|
depends = glibc
|
||||||
depends = gtk3
|
depends = gtk3
|
||||||
depends = hicolor-icon-theme
|
depends = hicolor-icon-theme
|
||||||
|
depends = libdrm
|
||||||
depends = libgcc
|
depends = libgcc
|
||||||
depends = libsoup3
|
depends = libsoup3
|
||||||
depends = webkit2gtk-4.1
|
depends = webkit2gtk-4.1
|
||||||
@@ -28,6 +29,10 @@ pkgbase = modrinth-enhanced-bin
|
|||||||
options = !strip
|
options = !strip
|
||||||
options = !debug
|
options = !debug
|
||||||
source = modrinth-enhanced-bin-0.21.2.deb::https://github.com/Felitendo/Modrinth-Enhanced/releases/download/v0.21.2/Modrinth.Enhanced_0.21.2_amd64.deb
|
source = modrinth-enhanced-bin-0.21.2.deb::https://github.com/Felitendo/Modrinth-Enhanced/releases/download/v0.21.2/Modrinth.Enhanced_0.21.2_amd64.deb
|
||||||
|
source = vblank-shim.c
|
||||||
|
source = modrinth-enhanced.sh
|
||||||
sha256sums = 32ed32575050b4ac1a990b54a894e82c17860a48d5a228ce0d1ce7fc2c9d5d6f
|
sha256sums = 32ed32575050b4ac1a990b54a894e82c17860a48d5a228ce0d1ce7fc2c9d5d6f
|
||||||
|
sha256sums = 0190921b8ff2fb1deec3209cba71c01541ca1f013e3ba41680f1636e185fd455
|
||||||
|
sha256sums = b24872f82645c52ee4804599cd678d138876fb193c754403fa9c5cf92bd745b9
|
||||||
|
|
||||||
pkgname = modrinth-enhanced-bin
|
pkgname = modrinth-enhanced-bin
|
||||||
@@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
pkgname=modrinth-enhanced-bin
|
pkgname=modrinth-enhanced-bin
|
||||||
pkgver=0.21.2
|
pkgver=0.21.2
|
||||||
pkgrel=1
|
pkgrel=2
|
||||||
pkgdesc="Modrinth App without ads or telemetry, with offline and Ely.by accounts and Linux fixes (upstream binary)"
|
pkgdesc="Modrinth App without ads or telemetry, with offline and Ely.by accounts and Linux fixes (upstream binary)"
|
||||||
arch=('x86_64')
|
arch=('x86_64')
|
||||||
url="https://github.com/Felitendo/Modrinth-Enhanced"
|
url="https://github.com/Felitendo/Modrinth-Enhanced"
|
||||||
license=('GPL-3.0-only')
|
license=('GPL-3.0-only')
|
||||||
depends=('cairo' 'dbus' 'gdk-pixbuf2' 'glib2' 'glibc' 'gtk3' 'hicolor-icon-theme'
|
depends=('cairo' 'dbus' 'gdk-pixbuf2' 'glib2' 'glibc' 'gtk3' 'hicolor-icon-theme'
|
||||||
'libgcc' 'libsoup3' 'webkit2gtk-4.1'
|
'libdrm' 'libgcc' 'libsoup3' 'webkit2gtk-4.1'
|
||||||
# loaded by Minecraft, not by the launcher
|
# loaded by Minecraft, not by the launcher
|
||||||
'libgl' 'libpulse' 'libx11' 'libxcursor' 'libxext' 'libxxf86vm')
|
'libgl' 'libpulse' 'libx11' 'libxcursor' 'libxext' 'libxxf86vm')
|
||||||
optdepends=('xorg-xrandr: for older Minecraft versions')
|
optdepends=('xorg-xrandr: for older Minecraft versions')
|
||||||
@@ -21,12 +21,30 @@ options=('!strip' '!debug')
|
|||||||
# v0.21.2-2, which pkgver spells 0.21.2.r2; see pkg.sh.
|
# v0.21.2-2, which pkgver spells 0.21.2.r2; see pkg.sh.
|
||||||
_tag="v0.21.2"
|
_tag="v0.21.2"
|
||||||
_asset="Modrinth.Enhanced_0.21.2_amd64.deb"
|
_asset="Modrinth.Enhanced_0.21.2_amd64.deb"
|
||||||
source=("${pkgname}-${pkgver}.deb::https://github.com/Felitendo/Modrinth-Enhanced/releases/download/${_tag}/${_asset}")
|
# With the NVIDIA driver WebKitGTK paces the app with a 60 fps timer whatever
|
||||||
|
# the monitor's refresh rate. vblank-shim.c, preloaded by modrinth-enhanced.sh,
|
||||||
|
# paces it at the monitor's rate instead and keeps the app on X11, the only
|
||||||
|
# place that works; it is not part of upstream's release.
|
||||||
|
source=("${pkgname}-${pkgver}.deb::https://github.com/Felitendo/Modrinth-Enhanced/releases/download/${_tag}/${_asset}"
|
||||||
|
"vblank-shim.c"
|
||||||
|
"modrinth-enhanced.sh")
|
||||||
noextract=("${pkgname}-${pkgver}.deb")
|
noextract=("${pkgname}-${pkgver}.deb")
|
||||||
sha256sums=('32ed32575050b4ac1a990b54a894e82c17860a48d5a228ce0d1ce7fc2c9d5d6f')
|
sha256sums=('32ed32575050b4ac1a990b54a894e82c17860a48d5a228ce0d1ce7fc2c9d5d6f' '0190921b8ff2fb1deec3209cba71c01541ca1f013e3ba41680f1636e185fd455' 'b24872f82645c52ee4804599cd678d138876fb193c754403fa9c5cf92bd745b9')
|
||||||
|
|
||||||
|
build() {
|
||||||
|
# GLib for its headers only: the shim looks GTK and GLib up at run time
|
||||||
|
gcc $CPPFLAGS $CFLAGS $LDFLAGS -shared -fPIC -o libwebkit-vblank-shim.so vblank-shim.c \
|
||||||
|
$(pkg-config --cflags glib-2.0) $(pkg-config --cflags --libs libdrm)
|
||||||
|
}
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
bsdtar -xOf "$srcdir/${pkgname}-${pkgver}.deb" 'data.tar.*' \
|
bsdtar -xOf "$srcdir/${pkgname}-${pkgver}.deb" 'data.tar.*' \
|
||||||
| bsdtar -xpf - -C "$pkgdir" usr
|
| bsdtar -xpf - -C "$pkgdir" usr
|
||||||
|
|
||||||
|
# the binary moves behind the script that preloads the shim
|
||||||
|
install -d "$pkgdir/usr/lib/modrinth-enhanced"
|
||||||
|
mv "$pkgdir/usr/bin/ModrinthEnhanced" "$pkgdir/usr/lib/modrinth-enhanced/"
|
||||||
|
install -Dm755 libwebkit-vblank-shim.so -t "$pkgdir/usr/lib/modrinth-enhanced/"
|
||||||
|
install -Dm755 modrinth-enhanced.sh "$pkgdir/usr/bin/ModrinthEnhanced"
|
||||||
ln -s ModrinthEnhanced "$pkgdir/usr/bin/modrinth-enhanced"
|
ln -s ModrinthEnhanced "$pkgdir/usr/bin/modrinth-enhanced"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Starts Modrinth Enhanced with the vblank shim preloaded (see vblank-shim.c).
|
||||||
|
# With the NVIDIA driver the shim only lifts the frame rate under X11, so it is
|
||||||
|
# asked to keep GTK on X11 there. MODRINTH_VBLANK_SHIM=0 starts the app without.
|
||||||
|
if [ "${MODRINTH_VBLANK_SHIM:-1}" != 0 ]; then
|
||||||
|
[ -d /sys/module/nvidia_drm ] && export VBLANK_SHIM_GDK_BACKEND=x11
|
||||||
|
export LD_PRELOAD="/usr/lib/modrinth-enhanced/libwebkit-vblank-shim.so${LD_PRELOAD:+:$LD_PRELOAD}"
|
||||||
|
fi
|
||||||
|
exec /usr/lib/modrinth-enhanced/ModrinthEnhanced "$@"
|
||||||
@@ -2,9 +2,10 @@
|
|||||||
# the Modrinth App (Tauri) with a series of patches applied: no ads, no
|
# the Modrinth App (Tauri) with a series of patches applied: no ads, no
|
||||||
# telemetry, offline and Ely.by accounts, Linux fixes.
|
# telemetry, offline and Ely.by accounts, Linux fixes.
|
||||||
#
|
#
|
||||||
# Upstream publishes a bundled .deb per release, so there is no build step
|
# Upstream publishes a bundled .deb per release, so the app is not built here:
|
||||||
# here: on a new version only pkgver, the tag, the asset name and the checksum
|
# on a new version only pkgver, the tag, the asset name and the checksums are
|
||||||
# are refreshed and the PKGBUILD repackages the deb directly.
|
# refreshed and the PKGBUILD repackages the deb directly. The only thing built
|
||||||
|
# is vblank-shim.c, which ships with this package (see the PKGBUILD).
|
||||||
#
|
#
|
||||||
# Releases are tagged after the Modrinth App release they are built on
|
# Releases are tagged after the Modrinth App release they are built on
|
||||||
# (v0.21.2). When the patches change without a new Modrinth App release, the
|
# (v0.21.2). When the patches change without a new Modrinth App release, the
|
||||||
@@ -18,6 +19,9 @@
|
|||||||
|
|
||||||
UPSTREAM_REPO="Felitendo/Modrinth-Enhanced"
|
UPSTREAM_REPO="Felitendo/Modrinth-Enhanced"
|
||||||
|
|
||||||
|
# Installed in CI before the makepkg test build, for the shim's headers.
|
||||||
|
BUILD_DEPS=(glib2 libdrm)
|
||||||
|
|
||||||
latest_version() {
|
latest_version() {
|
||||||
gh api "repos/$UPSTREAM_REPO/releases/latest" --jq '.tag_name' | sed 's/^v//; s/-/.r/'
|
gh api "repos/$UPSTREAM_REPO/releases/latest" --jq '.tag_name' | sed 's/^v//; s/-/.r/'
|
||||||
}
|
}
|
||||||
@@ -25,7 +29,11 @@ latest_version() {
|
|||||||
# refresh_checksums <version> <pkgbuild-path>
|
# refresh_checksums <version> <pkgbuild-path>
|
||||||
refresh_checksums() {
|
refresh_checksums() {
|
||||||
local ver="$1" pkgbuild="$2"
|
local ver="$1" pkgbuild="$2"
|
||||||
local tag="v${ver/.r/-}" asset sha
|
local tag="v${ver/.r/-}" dir asset sha sha_shim sha_script
|
||||||
|
|
||||||
|
dir="$(dirname "$pkgbuild")"
|
||||||
|
sha_shim="$(sha256sum "$dir/vblank-shim.c" | cut -d' ' -f1)"
|
||||||
|
sha_script="$(sha256sum "$dir/modrinth-enhanced.sh" | cut -d' ' -f1)"
|
||||||
|
|
||||||
asset="$(gh api "repos/$UPSTREAM_REPO/releases/tags/$tag" \
|
asset="$(gh api "repos/$UPSTREAM_REPO/releases/tags/$tag" \
|
||||||
--jq '.assets[].name | select(endswith("_amd64.deb"))')"
|
--jq '.assets[].name | select(endswith("_amd64.deb"))')"
|
||||||
@@ -40,6 +48,6 @@ refresh_checksums() {
|
|||||||
sed -i \
|
sed -i \
|
||||||
-e "s|^_tag=.*|_tag=\"$tag\"|" \
|
-e "s|^_tag=.*|_tag=\"$tag\"|" \
|
||||||
-e "s|^_asset=.*|_asset=\"$asset\"|" \
|
-e "s|^_asset=.*|_asset=\"$asset\"|" \
|
||||||
-e "s|^sha256sums=.*|sha256sums=('$sha')|" \
|
-e "s|^sha256sums=.*|sha256sums=('$sha' '$sha_shim' '$sha_script')|" \
|
||||||
"$pkgbuild"
|
"$pkgbuild"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,437 @@
|
|||||||
|
// LD_PRELOAD shim that lets Modrinth Enhanced (WebKitGTK 4.1 on GTK3) draw at
|
||||||
|
// the monitor's refresh rate with the NVIDIA driver instead of 60 Hz.
|
||||||
|
//
|
||||||
|
// Three things hold it at 60 Hz there:
|
||||||
|
// 1. WebKitGTK looks for the DRM CRTC of the monitor a window is on by
|
||||||
|
// physical size, and the NVIDIA DRM connector reports slightly different
|
||||||
|
// millimetres than GDK does, so no CRTC is found.
|
||||||
|
// 2. The NVIDIA DRM driver does not implement DRM_IOCTL_WAIT_VBLANK, so even a
|
||||||
|
// found CRTC cannot be waited on. WebKit then paces with a 60 fps timer.
|
||||||
|
// 3. GTK3 paces its own paints from the refresh interval the display server
|
||||||
|
// reports, and assumes 60 Hz without one. KWin reports none to it, on X11
|
||||||
|
// (no _NET_WM_FRAME_TIMINGS for XWayland clients) and on Wayland alike.
|
||||||
|
//
|
||||||
|
// This shim:
|
||||||
|
// 1. corrects the connector size to what GDK reports for the same monitor,
|
||||||
|
// found by output name on X11 ("DP-1") or EDID model name on Wayland;
|
||||||
|
// 2. emulates blocking vblank waits at the CRTC's refresh rate when the
|
||||||
|
// driver refuses them;
|
||||||
|
// 3. fills in the monitor refresh interval on GTK3 frame timings that were
|
||||||
|
// left without one.
|
||||||
|
//
|
||||||
|
// Each step only stands in for what is missing, so with drivers that report
|
||||||
|
// all of it the shim changes nothing.
|
||||||
|
//
|
||||||
|
// The frame rate only comes through on X11: on Wayland something in GTK3 or
|
||||||
|
// WebKit still asks for 60 frames a second. VBLANK_SHIM_GDK_BACKEND=x11 keeps
|
||||||
|
// GTK on X11 without setting GDK_BACKEND, which every program the app starts
|
||||||
|
// would inherit. A GDK_BACKEND the user set still wins.
|
||||||
|
//
|
||||||
|
// Build: gcc -shared -fPIC -O2 -o libwebkit-vblank-shim.so vblank-shim.c $(pkg-config --cflags glib-2.0) $(pkg-config --cflags --libs libdrm)
|
||||||
|
// Debug: VBLANK_SHIM_DEBUG=1
|
||||||
|
// Knobs: VBLANK_SHIM_RATE_MULTIPLIER (vblank emulation), VBLANK_SHIM_REFRESH_HZ
|
||||||
|
// (GTK frame timings, default: fastest monitor), VBLANK_SHIM_FRAME_CLOCK=0
|
||||||
|
// (leave GTK frame timings alone)
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <xf86drm.h>
|
||||||
|
#include <xf86drmMode.h>
|
||||||
|
|
||||||
|
typedef struct _GdkDisplay GdkDisplay;
|
||||||
|
typedef struct _GdkMonitor GdkMonitor;
|
||||||
|
typedef struct _GdkWindow GdkWindow;
|
||||||
|
typedef struct _GdkFrameClock GdkFrameClock;
|
||||||
|
typedef struct _GdkFrameTimings GdkFrameTimings;
|
||||||
|
|
||||||
|
static int debug_enabled(void) {
|
||||||
|
static int value = -1;
|
||||||
|
if (value < 0) value = getenv("VBLANK_SHIM_DEBUG") != NULL;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define debug(...) do { if (debug_enabled()) fprintf(stderr, "vblank-shim: " __VA_ARGS__); } while (0)
|
||||||
|
|
||||||
|
// --- 0. Window system -------------------------------------------------------
|
||||||
|
|
||||||
|
static char gdk_backend[16];
|
||||||
|
|
||||||
|
// Read on load, while nothing else runs, and taken out of the environment.
|
||||||
|
__attribute__((constructor))
|
||||||
|
static void take_gdk_backend(void) {
|
||||||
|
const char *backend = getenv("VBLANK_SHIM_GDK_BACKEND");
|
||||||
|
if (!backend) return;
|
||||||
|
snprintf(gdk_backend, sizeof gdk_backend, "%s", backend);
|
||||||
|
unsetenv("VBLANK_SHIM_GDK_BACKEND");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void select_gdk_backend(void) {
|
||||||
|
if (!gdk_backend[0] || getenv("GDK_BACKEND")) return;
|
||||||
|
void (*set_allowed_backends)(const char *) = dlsym(RTLD_DEFAULT, "gdk_set_allowed_backends");
|
||||||
|
if (set_allowed_backends) {
|
||||||
|
set_allowed_backends(gdk_backend);
|
||||||
|
debug("GDK limited to %s\n", gdk_backend);
|
||||||
|
}
|
||||||
|
gdk_backend[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
int gtk_init_check(int *argc, char ***argv) {
|
||||||
|
static int (*real)(int *, char ***);
|
||||||
|
if (!real) real = dlsym(RTLD_NEXT, "gtk_init_check");
|
||||||
|
select_gdk_backend();
|
||||||
|
return real(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gtk_init(int *argc, char ***argv) {
|
||||||
|
static void (*real)(int *, char ***);
|
||||||
|
if (!real) real = dlsym(RTLD_NEXT, "gtk_init");
|
||||||
|
select_gdk_backend();
|
||||||
|
real(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebKit waits for vblank and GTK paints in the process the shim is preloaded
|
||||||
|
// into. Its children - WebKit's helper processes, and Minecraft started from
|
||||||
|
// the launcher - have no use for it, so it leaves LD_PRELOAD on load and keeps
|
||||||
|
// whatever else is in there.
|
||||||
|
__attribute__((constructor))
|
||||||
|
static void leave_ld_preload(void) {
|
||||||
|
const char *preload = getenv("LD_PRELOAD");
|
||||||
|
Dl_info info;
|
||||||
|
if (!preload || !dladdr((void *)leave_ld_preload, &info) || !info.dli_fname) return;
|
||||||
|
const char *self = strrchr(info.dli_fname, '/');
|
||||||
|
self = self ? self + 1 : info.dli_fname;
|
||||||
|
|
||||||
|
char *entries = strdup(preload), *kept = calloc(1, strlen(preload) + 1);
|
||||||
|
if (entries && kept) {
|
||||||
|
char *save = NULL;
|
||||||
|
for (char *entry = strtok_r(entries, ": ", &save); entry; entry = strtok_r(NULL, ": ", &save)) {
|
||||||
|
const char *name = strrchr(entry, '/');
|
||||||
|
if (strcmp(name ? name + 1 : entry, self) == 0) continue;
|
||||||
|
if (*kept) strcat(kept, ":");
|
||||||
|
strcat(kept, entry);
|
||||||
|
}
|
||||||
|
if (*kept) setenv("LD_PRELOAD", kept, 1);
|
||||||
|
else unsetenv("LD_PRELOAD");
|
||||||
|
}
|
||||||
|
free(entries);
|
||||||
|
free(kept);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GTK and GLib are looked up at run time rather than linked, so the shim loads
|
||||||
|
// into processes without them (such as the shell script that starts the
|
||||||
|
// AppImage) and still finds them when they are loaded later with dlopen.
|
||||||
|
static struct {
|
||||||
|
GdkDisplay *(*display_get_default)(void);
|
||||||
|
int (*display_get_n_monitors)(GdkDisplay *);
|
||||||
|
GdkMonitor *(*display_get_monitor)(GdkDisplay *, int);
|
||||||
|
const char *(*monitor_get_model)(GdkMonitor *);
|
||||||
|
int (*monitor_get_width_mm)(GdkMonitor *);
|
||||||
|
int (*monitor_get_height_mm)(GdkMonitor *);
|
||||||
|
int (*monitor_get_refresh_rate)(GdkMonitor *);
|
||||||
|
GType (*frame_clock_get_type)(void);
|
||||||
|
GdkFrameTimings *(*frame_clock_get_current_timings)(GdkFrameClock *);
|
||||||
|
gint64 (*frame_timings_get_refresh_interval)(GdkFrameTimings *);
|
||||||
|
gpointer (*type_class_ref)(GType);
|
||||||
|
guint (*signal_lookup)(const gchar *, GType);
|
||||||
|
gulong (*signal_add_emission_hook)(guint, GQuark, GSignalEmissionHook, gpointer, GDestroyNotify);
|
||||||
|
gpointer (*value_get_object)(const GValue *);
|
||||||
|
} gtk;
|
||||||
|
|
||||||
|
static int gtk_resolved(void) {
|
||||||
|
if (gtk.value_get_object) return 1;
|
||||||
|
#define RESOLVE(field, name) if (!(gtk.field = dlsym(RTLD_DEFAULT, name))) return 0
|
||||||
|
RESOLVE(display_get_default, "gdk_display_get_default");
|
||||||
|
RESOLVE(display_get_n_monitors, "gdk_display_get_n_monitors");
|
||||||
|
RESOLVE(display_get_monitor, "gdk_display_get_monitor");
|
||||||
|
RESOLVE(monitor_get_model, "gdk_monitor_get_model");
|
||||||
|
RESOLVE(monitor_get_width_mm, "gdk_monitor_get_width_mm");
|
||||||
|
RESOLVE(monitor_get_height_mm, "gdk_monitor_get_height_mm");
|
||||||
|
RESOLVE(monitor_get_refresh_rate, "gdk_monitor_get_refresh_rate");
|
||||||
|
RESOLVE(frame_clock_get_type, "gdk_frame_clock_get_type");
|
||||||
|
RESOLVE(frame_clock_get_current_timings, "gdk_frame_clock_get_current_timings");
|
||||||
|
RESOLVE(frame_timings_get_refresh_interval, "gdk_frame_timings_get_refresh_interval");
|
||||||
|
RESOLVE(type_class_ref, "g_type_class_ref");
|
||||||
|
RESOLVE(signal_lookup, "g_signal_lookup");
|
||||||
|
RESOLVE(signal_add_emission_hook, "g_signal_add_emission_hook");
|
||||||
|
RESOLVE(value_get_object, "g_value_get_object");
|
||||||
|
#undef RESOLVE
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 1. Connector size ------------------------------------------------------
|
||||||
|
|
||||||
|
static const char *connector_prefix(uint32_t type) {
|
||||||
|
switch (type) {
|
||||||
|
case DRM_MODE_CONNECTOR_DisplayPort: return "DP";
|
||||||
|
case DRM_MODE_CONNECTOR_HDMIA: return "HDMI-A";
|
||||||
|
case DRM_MODE_CONNECTOR_HDMIB: return "HDMI-B";
|
||||||
|
case DRM_MODE_CONNECTOR_DVID: return "DVI-D";
|
||||||
|
case DRM_MODE_CONNECTOR_DVII: return "DVI-I";
|
||||||
|
case DRM_MODE_CONNECTOR_eDP: return "eDP";
|
||||||
|
case DRM_MODE_CONNECTOR_VGA: return "VGA";
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The monitor name descriptor (0xFC) of the connector's EDID, which is what
|
||||||
|
// GDK's Wayland backend reports as the monitor model.
|
||||||
|
static void edid_model_name(int fd, uint32_t connector_id, char *out, size_t size) {
|
||||||
|
out[0] = '\0';
|
||||||
|
drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(fd, connector_id, DRM_MODE_OBJECT_CONNECTOR);
|
||||||
|
if (!props) return;
|
||||||
|
for (uint32_t i = 0; i < props->count_props && !out[0]; i++) {
|
||||||
|
drmModePropertyPtr prop = drmModeGetProperty(fd, props->props[i]);
|
||||||
|
if (prop && strcmp(prop->name, "EDID") == 0 && props->prop_values[i]) {
|
||||||
|
drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(fd, props->prop_values[i]);
|
||||||
|
if (blob && blob->length >= 128) {
|
||||||
|
const unsigned char *edid = blob->data;
|
||||||
|
for (int d = 54; d <= 108; d += 18) {
|
||||||
|
if (edid[d] || edid[d + 1] || edid[d + 2] || edid[d + 3] != 0xFC) continue;
|
||||||
|
size_t n = 0;
|
||||||
|
for (int k = 5; k < 18 && n + 1 < size && edid[d + k] != '\n'; k++) out[n++] = edid[d + k];
|
||||||
|
while (n && isspace((unsigned char)out[n - 1])) n--;
|
||||||
|
out[n] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drmModeFreePropertyBlob(blob);
|
||||||
|
}
|
||||||
|
drmModeFreeProperty(prop);
|
||||||
|
}
|
||||||
|
drmModeFreeObjectProperties(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id) {
|
||||||
|
static drmModeConnectorPtr (*real)(int, uint32_t);
|
||||||
|
if (!real) real = dlsym(RTLD_NEXT, "drmModeGetConnector");
|
||||||
|
drmModeConnectorPtr connector = real(fd, connector_id);
|
||||||
|
if (!connector || connector->connection != DRM_MODE_CONNECTED || !gtk_resolved()) return connector;
|
||||||
|
|
||||||
|
GdkDisplay *display = gtk.display_get_default();
|
||||||
|
if (!display) return connector;
|
||||||
|
|
||||||
|
char output_name[32] = "";
|
||||||
|
const char *prefix = connector_prefix(connector->connector_type);
|
||||||
|
if (prefix) snprintf(output_name, sizeof output_name, "%s-%u", prefix, connector->connector_type_id);
|
||||||
|
char edid_name[32];
|
||||||
|
edid_model_name(fd, connector_id, edid_name, sizeof edid_name);
|
||||||
|
|
||||||
|
for (int i = 0; i < gtk.display_get_n_monitors(display); i++) {
|
||||||
|
GdkMonitor *monitor = gtk.display_get_monitor(display, i);
|
||||||
|
const char *model = gtk.monitor_get_model(monitor);
|
||||||
|
if (!model) continue;
|
||||||
|
if (!(output_name[0] && strcmp(model, output_name) == 0) && !(edid_name[0] && strcmp(model, edid_name) == 0))
|
||||||
|
continue;
|
||||||
|
int w = gtk.monitor_get_width_mm(monitor), h = gtk.monitor_get_height_mm(monitor);
|
||||||
|
if (w > 0 && h > 0 && ((uint32_t)w != connector->mmWidth || (uint32_t)h != connector->mmHeight)) {
|
||||||
|
debug("%s (%s): connector size %ux%u mm -> %dx%d mm (as GDK reports)\n", output_name, edid_name,
|
||||||
|
connector->mmWidth, connector->mmHeight, w, h);
|
||||||
|
connector->mmWidth = w;
|
||||||
|
connector->mmHeight = h;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 2. Vblank emulation ----------------------------------------------------
|
||||||
|
|
||||||
|
struct emulated_crtc {
|
||||||
|
int fd;
|
||||||
|
unsigned index;
|
||||||
|
long long period_ns;
|
||||||
|
struct timespec base;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct emulated_crtc crtcs[16];
|
||||||
|
static int crtc_count;
|
||||||
|
static pthread_mutex_t crtcs_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
static long long to_ns(const struct timespec *t) {
|
||||||
|
return (long long)t->tv_sec * 1000000000LL + t->tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double rate_multiplier(void) {
|
||||||
|
const char *value = getenv("VBLANK_SHIM_RATE_MULTIPLIER");
|
||||||
|
double multiplier = value ? atof(value) : 1.0;
|
||||||
|
return multiplier >= 1.0 ? multiplier : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long long refresh_period_ns(int fd, unsigned index) {
|
||||||
|
long long period = (long long)(1e9 / (60 * rate_multiplier()));
|
||||||
|
drmModeResPtr resources = drmModeGetResources(fd);
|
||||||
|
if (!resources) return period;
|
||||||
|
if ((int)index < resources->count_crtcs) {
|
||||||
|
drmModeCrtcPtr crtc = drmModeGetCrtc(fd, resources->crtcs[index]);
|
||||||
|
if (crtc && crtc->mode_valid && crtc->mode.htotal && crtc->mode.vtotal) {
|
||||||
|
const drmModeModeInfo *mode = &crtc->mode;
|
||||||
|
double hz = mode->clock * 1000.0 / ((double)mode->htotal * mode->vtotal);
|
||||||
|
if (mode->flags & DRM_MODE_FLAG_INTERLACE) hz *= 2;
|
||||||
|
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) hz /= 2;
|
||||||
|
if (mode->vscan > 1) hz /= mode->vscan;
|
||||||
|
if (hz > 1) period = (long long)(1e9 / (hz * rate_multiplier()));
|
||||||
|
debug("emulating vblank for crtc index %u at %.3f Hz x %.1f\n", index, hz, rate_multiplier());
|
||||||
|
}
|
||||||
|
drmModeFreeCrtc(crtc);
|
||||||
|
}
|
||||||
|
drmModeFreeResources(resources);
|
||||||
|
return period;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct emulated_crtc *emulated_crtc_for(int fd, unsigned index) {
|
||||||
|
pthread_mutex_lock(&crtcs_lock);
|
||||||
|
struct emulated_crtc *found = NULL;
|
||||||
|
for (int i = 0; i < crtc_count; i++) {
|
||||||
|
if (crtcs[i].fd == fd && crtcs[i].index == index) {
|
||||||
|
found = &crtcs[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found && crtc_count < (int)(sizeof crtcs / sizeof crtcs[0])) {
|
||||||
|
found = &crtcs[crtc_count++];
|
||||||
|
found->fd = fd;
|
||||||
|
found->index = index;
|
||||||
|
found->period_ns = refresh_period_ns(fd, index);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &found->base);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&crtcs_lock);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
int drmWaitVBlank(int fd, drmVBlankPtr vbl) {
|
||||||
|
static int (*real)(int, drmVBlankPtr);
|
||||||
|
if (!real) real = dlsym(RTLD_NEXT, "drmWaitVBlank");
|
||||||
|
|
||||||
|
drmVBlankReq request = vbl->request;
|
||||||
|
int ret = real(fd, vbl);
|
||||||
|
if (ret == 0) return 0;
|
||||||
|
|
||||||
|
int error = errno;
|
||||||
|
// Only stand in for a driver that does not do vblank waits at all, and only
|
||||||
|
// for plain blocking waits.
|
||||||
|
if ((error != EOPNOTSUPP && error != EPERM) || (request.type & (DRM_VBLANK_EVENT | DRM_VBLANK_SIGNAL))) {
|
||||||
|
errno = error;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned index = (request.type & DRM_VBLANK_SECONDARY)
|
||||||
|
? 1
|
||||||
|
: (request.type & DRM_VBLANK_HIGH_CRTC_MASK) >> DRM_VBLANK_HIGH_CRTC_SHIFT;
|
||||||
|
struct emulated_crtc *crtc = emulated_crtc_for(fd, index);
|
||||||
|
if (!crtc) {
|
||||||
|
errno = error;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
long long base = to_ns(&crtc->base);
|
||||||
|
long long current = (to_ns(&now) - base) / crtc->period_ns;
|
||||||
|
long long target;
|
||||||
|
if (request.type & DRM_VBLANK_RELATIVE) {
|
||||||
|
target = current + request.sequence;
|
||||||
|
} else {
|
||||||
|
target = request.sequence;
|
||||||
|
if (target <= current && (request.type & DRM_VBLANK_NEXTONMISS)) target = current + 1;
|
||||||
|
}
|
||||||
|
if (target < current) target = current;
|
||||||
|
|
||||||
|
long long when = base + target * crtc->period_ns;
|
||||||
|
if (target > current) {
|
||||||
|
struct timespec until = { when / 1000000000LL, when % 1000000000LL };
|
||||||
|
while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &until, NULL) == EINTR) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vbl->reply.type = request.type;
|
||||||
|
vbl->reply.sequence = (unsigned)target;
|
||||||
|
vbl->reply.tval_sec = when / 1000000000LL;
|
||||||
|
vbl->reply.tval_usec = (when % 1000000000LL) / 1000;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 3. GTK3 frame timings --------------------------------------------------
|
||||||
|
|
||||||
|
static gint64 frame_refresh_interval_us;
|
||||||
|
// Offset of the refresh_interval field inside GdkFrameTimings, found through
|
||||||
|
// the public getter rather than assumed. -1: not found yet, -2: give up.
|
||||||
|
static long refresh_interval_offset = -1;
|
||||||
|
|
||||||
|
static gint64 monitor_refresh_interval_us(void) {
|
||||||
|
const char *forced = getenv("VBLANK_SHIM_REFRESH_HZ");
|
||||||
|
if (forced && atof(forced) > 1) return (gint64)(1e6 / atof(forced));
|
||||||
|
GdkDisplay *display = gtk.display_get_default();
|
||||||
|
if (!display) return 0;
|
||||||
|
int fastest = 0;
|
||||||
|
for (int i = 0; i < gtk.display_get_n_monitors(display); i++) {
|
||||||
|
int rate = gtk.monitor_get_refresh_rate(gtk.display_get_monitor(display, i));
|
||||||
|
if (rate > fastest) fastest = rate;
|
||||||
|
}
|
||||||
|
// GDK reports milli-hertz.
|
||||||
|
return fastest > 0 ? (gint64)(1000000000LL / fastest) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long find_refresh_interval_offset(GdkFrameTimings *timings) {
|
||||||
|
gint64 *slots = (gint64 *)timings;
|
||||||
|
// The struct starts with a guint ref_count; the gint64 fields follow it.
|
||||||
|
for (long offset = 8; offset <= 96; offset += 8) {
|
||||||
|
gint64 saved = slots[offset / 8];
|
||||||
|
slots[offset / 8] = 0x5eed5eed5eedLL;
|
||||||
|
gboolean match = gtk.frame_timings_get_refresh_interval(timings) == 0x5eed5eed5eedLL;
|
||||||
|
slots[offset / 8] = saved;
|
||||||
|
if (match) return offset;
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean after_paint_hook(GSignalInvocationHint *hint, guint n_params, const GValue *params, gpointer data) {
|
||||||
|
(void)hint;
|
||||||
|
(void)data;
|
||||||
|
if (n_params < 1 || refresh_interval_offset == -2) return TRUE;
|
||||||
|
GdkFrameTimings *timings = gtk.frame_clock_get_current_timings(gtk.value_get_object(¶ms[0]));
|
||||||
|
// Only frames the backend left without a refresh interval.
|
||||||
|
if (!timings || gtk.frame_timings_get_refresh_interval(timings) != 0) return TRUE;
|
||||||
|
|
||||||
|
if (!frame_refresh_interval_us) frame_refresh_interval_us = monitor_refresh_interval_us();
|
||||||
|
if (frame_refresh_interval_us <= 0) return TRUE;
|
||||||
|
if (refresh_interval_offset == -1) {
|
||||||
|
refresh_interval_offset = find_refresh_interval_offset(timings);
|
||||||
|
if (refresh_interval_offset < 0) {
|
||||||
|
debug("could not locate refresh_interval in GdkFrameTimings, leaving GTK alone\n");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
debug("GTK frame timings: refresh interval %" G_GINT64_FORMAT " us (offset %ld)\n",
|
||||||
|
frame_refresh_interval_us, refresh_interval_offset);
|
||||||
|
}
|
||||||
|
((gint64 *)timings)[refresh_interval_offset / 8] = frame_refresh_interval_us;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void install_frame_clock_hook(void) {
|
||||||
|
const char *enabled = getenv("VBLANK_SHIM_FRAME_CLOCK");
|
||||||
|
if (enabled && strcmp(enabled, "0") == 0) return;
|
||||||
|
if (!gtk_resolved()) return;
|
||||||
|
GType type = gtk.frame_clock_get_type();
|
||||||
|
gtk.type_class_ref(type); // signals exist once the class does; keep it alive
|
||||||
|
guint signal = gtk.signal_lookup("after-paint", type);
|
||||||
|
if (!signal) return;
|
||||||
|
gtk.signal_add_emission_hook(signal, 0, after_paint_hook, NULL, NULL);
|
||||||
|
debug("installed GTK after-paint hook\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
GdkFrameClock *gdk_window_get_frame_clock(GdkWindow *window) {
|
||||||
|
static GdkFrameClock *(*real)(GdkWindow *);
|
||||||
|
static pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||||
|
if (!real) real = dlsym(RTLD_NEXT, "gdk_window_get_frame_clock");
|
||||||
|
GdkFrameClock *clock = real(window);
|
||||||
|
if (clock) pthread_once(&once, install_frame_clock_hook);
|
||||||
|
return clock;
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
pkgbase = modrinth-enhanced
|
pkgbase = modrinth-enhanced
|
||||||
pkgdesc = Modrinth App without ads or telemetry, with offline and Ely.by accounts and Linux fixes
|
pkgdesc = Modrinth App without ads or telemetry, with offline and Ely.by accounts and Linux fixes
|
||||||
pkgver = 0.21.2
|
pkgver = 0.21.2
|
||||||
pkgrel = 1
|
pkgrel = 2
|
||||||
url = https://github.com/Felitendo/Modrinth-Enhanced
|
url = https://github.com/Felitendo/Modrinth-Enhanced
|
||||||
arch = x86_64
|
arch = x86_64
|
||||||
license = GPL-3.0-only
|
license = GPL-3.0-only
|
||||||
@@ -19,6 +19,7 @@ pkgbase = modrinth-enhanced
|
|||||||
depends = glibc
|
depends = glibc
|
||||||
depends = gtk3
|
depends = gtk3
|
||||||
depends = hicolor-icon-theme
|
depends = hicolor-icon-theme
|
||||||
|
depends = libdrm
|
||||||
depends = libgcc
|
depends = libgcc
|
||||||
depends = libsoup3
|
depends = libsoup3
|
||||||
depends = webkit2gtk-4.1
|
depends = webkit2gtk-4.1
|
||||||
@@ -34,7 +35,11 @@ pkgbase = modrinth-enhanced
|
|||||||
options = !debug
|
options = !debug
|
||||||
source = modrinth-enhanced-v0.21.2.tar.gz::https://github.com/Felitendo/Modrinth-Enhanced/archive/refs/tags/v0.21.2.tar.gz
|
source = modrinth-enhanced-v0.21.2.tar.gz::https://github.com/Felitendo/Modrinth-Enhanced/archive/refs/tags/v0.21.2.tar.gz
|
||||||
source = modrinth-code-v0.21.2.tar.gz::https://github.com/modrinth/code/archive/refs/tags/v0.21.2.tar.gz
|
source = modrinth-code-v0.21.2.tar.gz::https://github.com/modrinth/code/archive/refs/tags/v0.21.2.tar.gz
|
||||||
|
source = vblank-shim.c
|
||||||
|
source = modrinth-enhanced.sh
|
||||||
sha256sums = a87ddcef0a39ab4a2c56ece806e381c6b398c755da00a9734b0162abc377e5a6
|
sha256sums = a87ddcef0a39ab4a2c56ece806e381c6b398c755da00a9734b0162abc377e5a6
|
||||||
sha256sums = 583e085cd7ae64a7020656af4ecc64ecfcc82fd97519f74cc3ab114d49574a5e
|
sha256sums = 583e085cd7ae64a7020656af4ecc64ecfcc82fd97519f74cc3ab114d49574a5e
|
||||||
|
sha256sums = 0190921b8ff2fb1deec3209cba71c01541ca1f013e3ba41680f1636e185fd455
|
||||||
|
sha256sums = b24872f82645c52ee4804599cd678d138876fb193c754403fa9c5cf92bd745b9
|
||||||
|
|
||||||
pkgname = modrinth-enhanced
|
pkgname = modrinth-enhanced
|
||||||
@@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
pkgname=modrinth-enhanced
|
pkgname=modrinth-enhanced
|
||||||
pkgver=0.21.2
|
pkgver=0.21.2
|
||||||
pkgrel=1
|
pkgrel=2
|
||||||
pkgdesc="Modrinth App without ads or telemetry, with offline and Ely.by accounts and Linux fixes"
|
pkgdesc="Modrinth App without ads or telemetry, with offline and Ely.by accounts and Linux fixes"
|
||||||
arch=('x86_64')
|
arch=('x86_64')
|
||||||
url="https://github.com/Felitendo/Modrinth-Enhanced"
|
url="https://github.com/Felitendo/Modrinth-Enhanced"
|
||||||
license=('GPL-3.0-only')
|
license=('GPL-3.0-only')
|
||||||
depends=('cairo' 'dbus' 'gdk-pixbuf2' 'glib2' 'glibc' 'gtk3' 'hicolor-icon-theme'
|
depends=('cairo' 'dbus' 'gdk-pixbuf2' 'glib2' 'glibc' 'gtk3' 'hicolor-icon-theme'
|
||||||
'libgcc' 'libsoup3' 'webkit2gtk-4.1'
|
'libdrm' 'libgcc' 'libsoup3' 'webkit2gtk-4.1'
|
||||||
# loaded by Minecraft, not by the launcher
|
# loaded by Minecraft, not by the launcher
|
||||||
'libgl' 'libpulse' 'libx11' 'libxcursor' 'libxext' 'libxxf86vm')
|
'libgl' 'libpulse' 'libx11' 'libxcursor' 'libxext' 'libxxf86vm')
|
||||||
# git replays the patches the way upstream's scripts/prepare.sh does; the JDK
|
# git replays the patches the way upstream's scripts/prepare.sh does; the JDK
|
||||||
@@ -27,14 +27,20 @@ options=('!lto' '!debug')
|
|||||||
_tag="v0.21.2"
|
_tag="v0.21.2"
|
||||||
_upstream="v0.21.2"
|
_upstream="v0.21.2"
|
||||||
_base="v0.21.2"
|
_base="v0.21.2"
|
||||||
|
# With the NVIDIA driver WebKitGTK paces the app with a 60 fps timer whatever
|
||||||
|
# the monitor's refresh rate. vblank-shim.c, preloaded by modrinth-enhanced.sh,
|
||||||
|
# paces it at the monitor's rate instead and keeps the app on X11, the only
|
||||||
|
# place that works; it is not part of upstream's release.
|
||||||
source=("${pkgname}-${_tag}.tar.gz::https://github.com/Felitendo/Modrinth-Enhanced/archive/refs/tags/${_tag}.tar.gz"
|
source=("${pkgname}-${_tag}.tar.gz::https://github.com/Felitendo/Modrinth-Enhanced/archive/refs/tags/${_tag}.tar.gz"
|
||||||
"modrinth-code-${_upstream}.tar.gz::https://github.com/modrinth/code/archive/refs/tags/${_upstream}.tar.gz")
|
"modrinth-code-${_upstream}.tar.gz::https://github.com/modrinth/code/archive/refs/tags/${_upstream}.tar.gz"
|
||||||
|
"vblank-shim.c"
|
||||||
|
"modrinth-enhanced.sh")
|
||||||
noextract=("modrinth-code-${_upstream}.tar.gz")
|
noextract=("modrinth-code-${_upstream}.tar.gz")
|
||||||
if [[ "$_base" != "$_upstream" ]]; then
|
if [[ "$_base" != "$_upstream" ]]; then
|
||||||
source+=("modrinth-code-${_base}.tar.gz::https://github.com/modrinth/code/archive/refs/tags/${_base}.tar.gz")
|
source+=("modrinth-code-${_base}.tar.gz::https://github.com/modrinth/code/archive/refs/tags/${_base}.tar.gz")
|
||||||
noextract+=("modrinth-code-${_base}.tar.gz")
|
noextract+=("modrinth-code-${_base}.tar.gz")
|
||||||
fi
|
fi
|
||||||
sha256sums=('a87ddcef0a39ab4a2c56ece806e381c6b398c755da00a9734b0162abc377e5a6' '583e085cd7ae64a7020656af4ecc64ecfcc82fd97519f74cc3ab114d49574a5e')
|
sha256sums=('a87ddcef0a39ab4a2c56ece806e381c6b398c755da00a9734b0162abc377e5a6' '583e085cd7ae64a7020656af4ecc64ecfcc82fd97519f74cc3ab114d49574a5e' '0190921b8ff2fb1deec3209cba71c01541ca1f013e3ba41680f1636e185fd455' 'b24872f82645c52ee4804599cd678d138876fb193c754403fa9c5cf92bd745b9')
|
||||||
|
|
||||||
prepare() {
|
prepare() {
|
||||||
# What upstream's scripts/prepare.sh does with two shallow tags: apply the
|
# What upstream's scripts/prepare.sh does with two shallow tags: apply the
|
||||||
@@ -88,6 +94,10 @@ prepare() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
|
# GLib for its headers only: the shim looks GTK and GLib up at run time
|
||||||
|
gcc $CPPFLAGS $CFLAGS $LDFLAGS -shared -fPIC -o libwebkit-vblank-shim.so vblank-shim.c \
|
||||||
|
$(pkg-config --cflags glib-2.0) $(pkg-config --cflags --libs libdrm)
|
||||||
|
|
||||||
cd app
|
cd app
|
||||||
|
|
||||||
export RUSTUP_TOOLCHAIN=stable
|
export RUSTUP_TOOLCHAIN=stable
|
||||||
@@ -106,8 +116,11 @@ build() {
|
|||||||
package() {
|
package() {
|
||||||
cd app
|
cd app
|
||||||
|
|
||||||
# the same files, under the same names, as upstream's .deb
|
# the same files, under the same names, as modrinth-enhanced-bin: the binary
|
||||||
install -Dm755 target/release/ModrinthEnhanced -t "$pkgdir/usr/bin/"
|
# sits behind the script that preloads the shim
|
||||||
|
install -Dm755 target/release/ModrinthEnhanced -t "$pkgdir/usr/lib/modrinth-enhanced/"
|
||||||
|
install -Dm755 "$srcdir/libwebkit-vblank-shim.so" -t "$pkgdir/usr/lib/modrinth-enhanced/"
|
||||||
|
install -Dm755 "$srcdir/modrinth-enhanced.sh" "$pkgdir/usr/bin/ModrinthEnhanced"
|
||||||
ln -s ModrinthEnhanced "$pkgdir/usr/bin/modrinth-enhanced"
|
ln -s ModrinthEnhanced "$pkgdir/usr/bin/modrinth-enhanced"
|
||||||
|
|
||||||
install -Dm644 apps/app/icons/128x128.png \
|
install -Dm644 apps/app/icons/128x128.png \
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../modrinth-enhanced-bin/modrinth-enhanced.sh
|
||||||
@@ -23,7 +23,7 @@ UPSTREAM_REPO="Felitendo/Modrinth-Enhanced"
|
|||||||
|
|
||||||
# Installed in CI (pacman) before the makepkg test build. makepkg runs with
|
# Installed in CI (pacman) before the makepkg test build. makepkg runs with
|
||||||
# -d there, so the libraries the binary links against are listed too.
|
# -d there, so the libraries the binary links against are listed too.
|
||||||
BUILD_DEPS=(rust git jdk17-openjdk node-gyp nodejs npm pnpm webkit2gtk-4.1 gtk3 libsoup3)
|
BUILD_DEPS=(rust git jdk17-openjdk node-gyp nodejs npm pnpm webkit2gtk-4.1 gtk3 libsoup3 libdrm)
|
||||||
|
|
||||||
latest_version() {
|
latest_version() {
|
||||||
gh api "repos/$UPSTREAM_REPO/releases/latest" --jq '.tag_name' | sed 's/^v//; s/-/.r/'
|
gh api "repos/$UPSTREAM_REPO/releases/latest" --jq '.tag_name' | sed 's/^v//; s/-/.r/'
|
||||||
@@ -52,7 +52,11 @@ refresh_checksums() {
|
|||||||
| sha256sum | cut -d' ' -f1)"
|
| sha256sum | cut -d' ' -f1)"
|
||||||
sha_upstream="$(curl -sfL "https://github.com/modrinth/code/archive/refs/tags/$upstream.tar.gz" \
|
sha_upstream="$(curl -sfL "https://github.com/modrinth/code/archive/refs/tags/$upstream.tar.gz" \
|
||||||
| sha256sum | cut -d' ' -f1)"
|
| sha256sum | cut -d' ' -f1)"
|
||||||
|
# vblank-shim.c and modrinth-enhanced.sh ship with the package, as symlinks
|
||||||
|
# to modrinth-enhanced-bin's copies; they come before the optional base tag
|
||||||
sums="'$sha_patches' '$sha_upstream'"
|
sums="'$sha_patches' '$sha_upstream'"
|
||||||
|
sums+=" '$(sha256sum "$(dirname "$pkgbuild")/vblank-shim.c" | cut -d' ' -f1)'"
|
||||||
|
sums+=" '$(sha256sum "$(dirname "$pkgbuild")/modrinth-enhanced.sh" | cut -d' ' -f1)'"
|
||||||
if [[ "$base" != "$upstream" ]]; then
|
if [[ "$base" != "$upstream" ]]; then
|
||||||
sums+=" '$(curl -sfL "https://github.com/modrinth/code/archive/refs/tags/$base.tar.gz" \
|
sums+=" '$(curl -sfL "https://github.com/modrinth/code/archive/refs/tags/$base.tar.gz" \
|
||||||
| sha256sum | cut -d' ' -f1)'"
|
| sha256sum | cut -d' ' -f1)'"
|
||||||
|
|||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../modrinth-enhanced-bin/vblank-shim.c
|
||||||
Reference in new issue
Block a user