Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,7 @@ menu "Utils"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/utils/box64/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/utils/sdl2-touch-test/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/utils/batocera-torrent/Config.in"
source "$BR2_EXTERNAL_BATOCERA_PATH/package/batocera/utils/gamescope/Config.in"
endmenu

menu "Utils Host"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from .gun import Gun
from .utils import bezels as bezelsUtil, metadata, videoMode, wheelsUtils
from .utils.evmapy import evmapy
from .utils.gamescope import add_gamescope_arguments
from .utils.hotkeygen import set_hotkeygen_context
from .utils.logger import setup_logging
from .utils.overlayfs import mount_overlayfs
Expand Down Expand Up @@ -278,6 +279,8 @@ def start_rom(args: argparse.Namespace, maxnbplayers: int, rom: Path, original_r
_logger.error("Failed to draw_gun_borders for gun_borders")
_logger.error(e)

add_gamescope_arguments(cmd, system, gameResolution)

with profiler.pause():
monitor_thread.start()
exitCode = runCommand(cmd)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
from __future__ import annotations

import logging
import os
import subprocess
from pathlib import Path
from typing import TYPE_CHECKING

from ..exceptions import BatoceraException

if TYPE_CHECKING:
from ..Command import Command
from ..Emulator import Emulator
from ..types import Resolution

_logger = logging.getLogger(__name__)

def is_GBM_Supported() -> bool:
try:
eglinfo_bin = Path("/usr/bin/eglinfo")
if not eglinfo_bin.exists():
return False

eglCmd = '/usr/bin/eglinfo | grep EGL_KHR_platform_gbm'
eglCmdResult = subprocess.run(eglCmd, shell=True, capture_output=True, text=True)
grep_return_code = eglCmdResult.returncode

return grep_return_code == 0

except Exception:
return False

def add_gamescope_arguments(command: Command, system: Emulator, CurrentResolution: Resolution, /) -> None:

if not system.config.get_bool("gamescope"):
return

if not is_GBM_Supported():
raise BatoceraException("GPU driver don't support gamescope")

gamescope_arguments = ["/usr/bin/gamescope"]

# Retrieve output resolution from system options.
# if not defined, inherit from the current screen resolution
output_resolution = system.config.get_str("gamescope_output_resolution")
if output_resolution:
output_width, _, output_height = output_resolution.partition("x")
else:
output_width = f'{CurrentResolution["width"]}'
output_height = f'{CurrentResolution["height"]}'

gamescope_arguments.extend([
"-W", output_width.strip(),
"-H", output_height.strip()
])

# Retrieve nested resolution from system options.
# default undefined inherit from gamescopt_output_resoluton
# the nested_resolution is upscaled|downscaled to output_resolution

nested_resolution = system.config.get_str("gamescope_nested_resolution")
if nested_resolution:
nested_width, _, nested_height = nested_resolution.partition("x")
gamescope_arguments.extend([
"-w", nested_width.strip(),
"-h", nested_height.strip()
])

# Retrieve nested refresh rate.
# Default is undefined with output refresh forced to 60hz
# if nested refresh is defined, output refresh is equal to nested refresh
nested_refresh = system.config.get_str("gamescope_nested_refresh")
if nested_refresh:
gamescope_arguments.extend(["-r", str(nested_refresh)])

# Framerate limit, used by gamescope as a divisor of the refresh rate.
framerate_limit = system.config.get_str("gamescope_framerate_limit")
if framerate_limit:
gamescope_arguments.extend(["--framerate-limit", framerate_limit])

# Upscaler type.
# default is stretched if undefined
scaler = system.config.get_str("gamescope_scaler")
if scaler:
gamescope_arguments.extend(["-S", scaler])

# Upscaler filter.
# default is linear if undefined
upscale_filter = system.config.get_str("gamescope_filter")
if upscale_filter:
gamescope_arguments.extend(["-F", upscale_filter])

# Upscaler sharpness
sharpness = system.config.get_str("gamescope_sharpness")
if sharpness:
gamescope_arguments.extend(["--sharpness", sharpness])

if system.config.get_bool("gamescope_hdr"):
sdr_gamut = system.config.get_str("gamescope_sdr_gamut_wideness")
if sdr_gamut:
gamescope_arguments.extend(["--sdr-gamut-wideness", sdr_gamut])

hdr_sdr_nits = system.config.get_str("gamescope_hdr_sdr_content_nits")
if hdr_sdr_nits:
gamescope_arguments.extend(["--hdr-sdr-content-nits", hdr_sdr_nits])

if system.config.get_bool("gamescope_hdr_itm_enabled"):
gamescope_arguments.append("--hdr-itm-enabled")

hdr_itm_sdr_nits = system.config.get_str("gamescope_hdr_itm_sdr_nits")
if hdr_itm_sdr_nits:
gamescope_arguments.extend(["--hdr-itm-sdr-nits", hdr_itm_sdr_nits])

hdr_itm_target = system.config.get_str("gamescope_hdr_itm_target_nits")
if hdr_itm_target:
gamescope_arguments.extend(["--hdr-itm-target-nits", hdr_itm_target])

#expose native nested wayland to bypass Xwayland when possible
if os.environ.get("WAYLAND_DISPLAY"):
gamescope_arguments.append("--expose-wayland")

#always fullscreen
gamescope_arguments.append("-f")

# Reshade effect.
reshade_effect = system.config.get_str("gamescope_reshade_effect")
if reshade_effect:
gamescope_arguments.extend(["--reshade-effect", reshade_effect])

gamescope_arguments.append("--")

command.array = gamescope_arguments + command.array
2 changes: 2 additions & 0 deletions package/batocera/core/batocera-system/Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,8 @@ config BR2_PACKAGE_BATOCERA_SYSTEM
BR2_PACKAGE_BATOCERA_TARGET_RK3588 || \
BR2_PACKAGE_BATOCERA_TARGET_RK3588_SDIO || \
BR2_PACKAGE_BATOCERA_TARGET_RK3588_MAINLINE
# gamescope
select BR2_PACKAGE_GAMESCOPE if BR2_PACKAGE_BATOCERA_TARGET_X86_64_ANY

help
Install the batocera.linux system files
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ shared_features:
- bezel.tattoo_corner
- bezel.tattoo_file
- bezel.resize_tattoo
- gamescope
- gamescope_nested_resolution
- gamescope_output_resolution
- gamescope_nested_refresh
- gamescope_framerate_limit
- gamescope_scaler
- gamescope_filter
- gamescope_sharpness
- gamescope_reshade_effect
- gamescope_hdr
- gamescope_sdr_gamut_wideness
- gamescope_hdr_sdr_content_nits
- gamescope_hdr_itm_enabled
- gamescope_hdr_itm_sdr_nits
- gamescope_hdr_itm_target_nits
- ai_service_enabled
- ai_target_lang
- ai_service_url
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ HOST_BATOCERA_ES_SYSTEM_DEPENDENCIES = host-python-batocera-common

$(eval $(call register,_shared.emulator.yml _global.emulator.yml lexaloffle.emulator.yml sh.emulator.yml))
$(eval $(call register-if-kconfig,BR2_PACKAGE_BATOCERA_TARGET_X86_64_ANY,tdp._shared.emulator.yml))
$(eval $(call register-if-kconfig,BR2_PACKAGE_GAMESCOPE,gamescope._shared.emulator.yml))
$(eval $(call register-if-none-of,$(BATOCERA_SYSTEM_ARCH),s905 bcm2835 bcm2836,hud._shared.emulator.yml))
$(eval $(call register-if-kconfig,BR2_PACKAGE_STELLA,stella.emulator.yml))

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# gamescope options. Registered only when gamescope is actually built,
# which replaces the archs_include the old es_features.yml used.
# See batocera-es-system.mk.
custom_features:
gamescope:
submenu: GAMESCOPE
prompt: GAMESCOPE ENABLE
description: Enable GameScope compositor for enhanced game display. Default Off.
choices:
'Off': 0
'On': 1
before: ai_service_enabled
gamescope_output_resolution:
submenu: GAMESCOPE
prompt: OUTPUT RESOLUTION
description: Select the output resolution for GameScope. Default is current monitor resolution.
choices:
640x480: 640x480
576x768: 576x768
800x600: 800x600
960x720: 960x720
1024x768: 1024x768
1280x720: 1280x720
1440x1080: 1440x1080
1920x1080: 1920x1080
2048x1080: 2048x1080
2560x1444: 2560x1444
3840x2160: 3840x2160
4096x2160: 4096x2160
before: ai_service_enabled
gamescope_nested_resolution:
submenu: GAMESCOPE
prompt: GAME NESTED RESOLUTION
description: Select the game (nested) resolution for GameScope. Default is output resolution.
choices:
640x480: 640x480
576x768: 576x768
800x600: 800x600
960x720: 960x720
1024x768: 1024x768
1280x720: 1280x720
1440x1080: 1440x1080
1920x1080: 1920x1080
2048x1080: 2048x1080
2560x1444: 2560x1444
3840x2160: 3840x2160
4096x2160: 4096x2160
before: ai_service_enabled
gamescope_nested_refresh:
submenu: GAMESCOPE
prompt: GAME REFRESH RATE
description: Set the refresh rate (fps) for the game when using GameScope. Default 60Hz.
choices:
60Hz: 60
75Hz: 75
120Hz: 120
138Hz: 138
144Hz: 144
150Hz: 150
165Hz: 165
170Hz: 170
175Hz: 175
180Hz: 180
200Hz: 200
240Hz: 240
270Hz: 270
275Hz: 275
280Hz: 280
360Hz: 360
390Hz: 390
480Hz: 480
540Hz: 540
before: ai_service_enabled
gamescope_framerate_limit:
submenu: GAMESCOPE
prompt: FRAMERATE LIMIT
description: Set a simple framerate limit. Used as a divisor of the refresh rate, rounds down (e.g., 60 / 59 -> 60fps, 60 / 25 -> 30fps).
choices:
'1': 1
'2': 2
'3': 3
'4': 4
'6': 6
'10': 10
'15': 15
'30': 30
'60': 60
before: ai_service_enabled
gamescope_scaler:
submenu: GAMESCOPE
prompt: GAMESCOPE SCALER
description: Choose the upscaler type for GameScope. Default stretch.
choices:
integer: integer
fit: fit
fill: fill
stretch: stretch
before: ai_service_enabled
gamescope_filter:
submenu: GAMESCOPE
prompt: GAMESCOPE FILTER
description: Choose the upscaler filter for GameScope. Default linear.
choices:
linear: linear
nearest: nearest
fsr: fsr
nis: nis
pixel: pixel
before: ai_service_enabled
gamescope_sharpness:
submenu: GAMESCOPE
prompt: GAMESCOPE SHARPNESS
description: Set the upscaler sharpness (0 for maximum sharpness, 20 for minimum).
choices:
'0': 0
'5': 5
'10': 10
'15': 15
'20': 20
before: ai_service_enabled
gamescope_reshade_effect:
submenu: GAMESCOPE
prompt: GAMESCOPE RESHADE EFFECT
description: Specify a ReShade shader effect to use with GameScope.
# free text, as it was in the old choice-less es_features.yml entry
preset: input
before: ai_service_enabled
gamescope_hdr:
submenu: GAMESCOPE
prompt: GAMESCOPE HDR
description: Enable HDR mode in GameScope if supported.
choices:
'Off': 0
'On': 1
before: ai_service_enabled
gamescope_sdr_gamut_wideness:
submenu: GAMESCOPE
prompt: SDR GAMUT WIDENESS
description: Set the 'wideness' of the gamut for SDR content.
choices:
'0': 0
'0.25': 0.25
'0.5': 0.5
'0.75': 0.75
'1': 1
before: ai_service_enabled
gamescope_hdr_sdr_content_nits:
submenu: GAMESCOPE
prompt: HDR SDR CONTENT NITS
description: 'Set the luminance of SDR content in nits. Default: 400 nits.'
choices:
'100': 100
'200': 200
'300': 300
'400': 400
'500': 500
'600': 600
'700': 700
'800': 800
'900': 900
'1000': 1000
before: ai_service_enabled
gamescope_hdr_itm_enabled:
submenu: GAMESCOPE
prompt: HDR ITM ENABLED
description: Enable SDR->HDR inverse tone mapping.
choices:
'Off': 0
'On': 1
before: ai_service_enabled
gamescope_hdr_itm_sdr_nits:
submenu: GAMESCOPE
prompt: HDR ITM SDR NITS
description: 'Set the luminance (in nits) of SDR content used as input for inverse tone mapping. Default: 100 nits, Max: 1000 nits.'
choices:
'100': 100
'200': 200
'300': 300
'400': 400
'500': 500
'600': 600
'700': 700
'800': 800
'900': 900
'1000': 1000
before: ai_service_enabled
gamescope_hdr_itm_target_nits:
submenu: GAMESCOPE
prompt: HDR ITM TARGET NITS
description: 'Set the target luminance (in nits) of the inverse tone mapping process. Default: 1000 nits, Max: 10000 nits.'
choices:
'1000': 1000
'2000': 2000
'3000': 3000
'4000': 4000
'5000': 5000
'6000': 6000
'7000': 7000
'8000': 8000
'9000': 9000
'10000': 10000
before: ai_service_enabled
Loading
Loading