Commit Graph
67840 Commits
Author SHA1 Message Date
sonninnos 65fe838e00 Add Load State to Run menu (#18997) 2026-05-02 04:59:06 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 8f6d51bc80 Qt: return const char* from enum-name lookup methods
Three MainWindow methods exist solely to map an enum value to a
fixed string literal: getThemeString, getCurrentViewTypeString,
and getCurrentThumbnailTypeString. They returned QString built
from a string literal at every call. Returning the literal
directly as const char* is one less heap allocation per call and
the caller (QSettings::setValue, which takes QVariant) accepts
it via the implicit QString conversion either way.

* getThemeString: 4 lines -> 1 line per branch.
* getCurrentViewTypeString: switch over a 2-value enum collapses
  to an if.
* getCurrentThumbnailTypeString: dropped a dead trailing
  'return QString("list")' that the compiler couldn't reach -
  the THUMBNAIL_TYPE_BOXART branch already returned via the
  default label.

No behaviour change. All four object files build with zero
warnings.
2026-05-01 23:00:30 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 56e0592626 Qt: drop more dead overrides, slots, and connections
Four small dead-code removals turned up in another sweep over
the audit areas. No behaviour change.

* TreeView::columnCountChanged: pure passthrough to
  QTreeView::columnCountChanged. Without this override, Qt's
  default does exactly the same thing. Drop the slot decl + impl.

* ListWidget::isEditorOpen: declared and defined, never called.
  TableView has the same method and one caller; ListWidget had
  none.

* AppHandler::onLastWindowClosed + the QApplication::lastWindowClosed
  -> onLastWindowClosed connect: the slot body was empty and the
  connection was therefore a no-op. Drop the slot, the connect()
  call, and the now-empty 'private slots:' section in the header.

* ThumbnailLabel::resizeEvent: pure passthrough to
  QWidget::resizeEvent, same situation as columnCountChanged.

All four object files (ui_qt, ui_qt_widgets, moc_ui_qt,
moc_ui_qt_widgets) build with zero warnings.
2026-05-01 22:51:38 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 0cc7a59da0 Qt: convert PlaylistModel content rows from QHash to a typed struct
The Qt UI's playlist rows used to round-trip through
QHash<QString,QString> with magic string keys ('path', 'label',
'core_path', etc.). This commit replaces that with a typed
PlaylistEntry struct. The keys actually used at the call sites
collapsed cleanly into 9 fields plus a row index. Other
QHash<QString,QString> uses in the file (core-info display rows,
core-selection-dialog rows) follow a different schema and are
intentionally left alone.

* ui_qt_widgets.h: define PlaylistEntry. The struct lives in this
  header rather than ui_qt.h because PlaylistEntryDialog has it
  in a default argument and ui_qt_widgets.h is included by
  ui_qt.h, not the other way round. Q_DECLARE_METATYPE and
  qRegisterMetaType<PlaylistEntry>() enable QVariant transport.

* PlaylistModel: m_contents is now QVector<PlaylistEntry>.
  getThumbnailPath(), data() (HASH role), and setData() all
  consume the struct directly. The custom user role enum is
  renamed HASH -> ENTRY to match.

* MainWindow:
  - getCurrentContentHash() -> getCurrentContentEntry()
  - getFileContentHash()    -> getFileContentEntry()
  - loadContent(QHash)      -> loadContent(PlaylistEntry)
  - onCurrentItemChanged(QHash) -> onCurrentItemChanged(PlaylistEntry)
  - updateCurrentPlaylistEntry(QHash) -> (PlaylistEntry)
  All call sites (setCoreActions, getSelectedCorePath, onRunClicked,
  onCurrentTableItemDataChanged, onCurrentFileChanged,
  onFileDoubleClicked, changeThumbnail, deleteCurrentPlaylistItem,
  the playlist-context-menu handler, and the addFilesToPlaylist
  flow) updated to read entry.field instead of hash["field"].

* PlaylistEntryDialog::showDialog and setEntryValues now take
  const PlaylistEntry &. The 'multiple entries' detection that
  used QHash::isEmpty() now uses entry.path.isEmpty(); previously
  the addFilesToPlaylist() flow had to write two empty-string keys
  just to make the QHash non-empty as a signal, which is gone.

* Drop the dead 'index' field round-trip.
  updateCurrentPlaylistEntry() and deleteCurrentPlaylistItem() used
  to read 'index' from the hash via QString::toUInt, which meant
  PlaylistModel::addPlaylistItems() had to format every row's index
  as a decimal string into the hash. PlaylistEntry::index is just
  an unsigned now.

* Drop dead m_currentGridHash member from MainWindow. It was only
  ever cleared, never written or read, so it always held an empty
  QHash. Removed along with the related conversions.

No behaviour change. All four object files (ui_qt, ui_qt_widgets,
moc_ui_qt, moc_ui_qt_widgets) build with zero warnings.
2026-05-01 22:32:15 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 1816b93862 Qt: prune dead getters, signals, forward decls, and locals
Pure dead-code removal in three files. No behaviour change.

* ui_qt.h: drop 8 redundant forward declarations.

  GridView, ShaderParamsDialog, CoreOptionsDialog, CoreInfoDialog,
  PlaylistEntryDialog and ViewOptionsDialog all have full
  definitions in ui_qt_widgets.h, which ui_qt.h includes at line
  46 - the forward decls below the include were noise.

  MainWindow and ThumbnailWidget were forward-declared at the top
  of ui_qt.h but never referenced before their own definitions
  later in the same file. Only the ThumbnailLabel forward decl is
  load-bearing - ThumbnailWidget references ThumbnailLabel* as a
  member before ThumbnailLabel is defined.

* MainWindow: drop 5 dead signals and 4 dead connect() calls.

  - gotReloadCoreOptions, gotThumbnailDownload, updateThumbnails
    and extractArchiveDeferred each had a connect() in the
    constructor but were never emitted anywhere - the signal
    connections were inert. The slots they pointed to
    (onDownloadThumbnail, onGotReloadCoreOptions, onExtractArchive,
    updateVisibleItems) all stay - they have other callers, either
    via direct calls or via QMetaObject::invokeMethod.

  - gridItemChanged was declared but neither emitted nor connected.

* MainWindow: drop 3 dead public getters.

  contentTableView(), contentGridView() and searchWidget() were
  declared and defined but had zero callers across ui/, libretro-
  common/, frontend/, menu/, and retroarch.c.

* MainWindow::MainWindow: drop dead 'QDir playlistDir' and the
  path_dir_playlist local that only existed to construct it.
  Both unused since the constructor split.
  -Wunused-variable did not flag the QDir because of its
  non-trivial constructor.

* MainWindow::changeThumbnail: replace QDir.exists() / QDir.mkpath
  pair with path_is_directory() / path_mkdir() from libretro-
  common, dropping one more QDir local. mkpath(".") and
  path_mkdir() both create parent directories recursively.

* MainWindow::setCoreActions: drop dead 'QFileInfo info' block
  ('info' was assigned via setFile() but never read) and a dead
  'coreName = "<n/a>"' assignment in a then-branch that did
  nothing else with coreName.

* qt_companion_select_initial_playlist: drop redundant
  'listWidget->count() &&' guard from two for-loop conditions
  ('i < count' is already false when count is 0).

* ui_qt_widgets.cpp: drop pre-existing dead 'uint32_t flags =
  runloop_st->flags' local in CoreOptionsDialog (-Wunused-variable
  was suppressed in the build and so this slipped in years ago).
2026-05-01 22:08:40 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre a9878b1c35 Qt: prefer libretro-common file APIs and drop Qt5/Qt6 ladders
Reduces Qt-specific surface and silences three pre-existing
-Wdeprecated-declarations warnings. All changes preserve behaviour
on Qt 5.2 and up (RetroArch's minimum, per qb/config.libs.sh).

* MainWindow::MainWindow:

  Drop dead 'QDir playlistDir(path_dir_playlist)' and the
  path_dir_playlist local that only existed to construct it. Both
  unused since the constructor split. -Wunused-variable did not
  flag the QDir because of its non-trivial constructor.

* MainWindow::setCustomThemeFile:

  Replace QFile open / readAll / close with filestream_read_file
  plus filestream_exists. Same five error paths preserved
  (blank path, missing file, open failure, empty file, success).

* MainWindow::onFileBrowserTreeContextMenuRequested:

  Replace the QDir / dir.exists() existence check with
  path_is_directory(). Removes a Qt5/Qt6 ifdef ladder ('dir =
  string' on Qt5 vs 'dir.setPath(string)' on Qt6) and silences
  the QDir::operator=(QString) deprecation warning. The
  QDir::toNativeSeparators(...) display path stays - that side is
  fine on both Qt 5 and Qt 6.

* LoadCoreWindow::onCoreEnterPressed:

  Replace 'QByteArray::append(QString)' (Qt 5) /
  'QByteArray::append(QString::toStdString())' (Qt 6) ladder with
  'path.toUtf8().constData()' inline. The temporary QByteArray's
  lifetime extends through the loadCore() call so this is safe.
  Silences the QByteArray::append(QString) deprecation warning.

* MainWindow::onPlaylistWidgetContextMenuRequested:

  Replace 'm_listWidget->isItemHidden(item)' (deprecated since
  Qt 4.8) with 'item->isHidden()' (available since Qt 4.x).
  Removes a Qt5/Qt6 ifdef ladder. Silences the
  QListWidget::isItemHidden() deprecation warning.

Tested under Qt 5.15 with -Wdeprecated-declarations enabled; all
four object files (ui_qt, ui_qt_widgets, moc_ui_qt,
moc_ui_qt_widgets) now build with zero warnings.

No behaviour change.
2026-05-01 21:36:51 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 334f787c2e Qt: drop unused includes and split MainWindow constructor
* Drop three unused Qt includes:

  - ui_qt.h: QDialog, QStyledItemDelegate. Both are still needed in
    ui_qt_widgets.h (PlaylistEntryDialog inherits QDialog,
    ThumbnailDelegate inherits QStyledItemDelegate), and ui_qt.h
    pulls in ui_qt_widgets.h, so consumers continue to get them
    transitively for free.
  - ui_qt_widgets.h: QTabWidget. Not used in this header at all.

* Split MainWindow::MainWindow body into helpers. The constructor
  was 446 body lines of mixed widget creation, layout assembly,
  model setup, file-system configuration, dock setup, and signal
  wiring, with locals declared at the top and used hundreds of
  lines later. Five private methods now own the chunks that don't
  cross-depend:

  - setupPlaylistFooter() builds the zoom slider, view-type and
    thumbnail-type push buttons, items count label, and grid
    progress widget, attaching them under the playlist views.
  - setupModels() configures the playlist + filesystem proxy
    models and the table / file-table / grid views.
  - setupFileSystemBrowser() configures the QFileSystemModels
    (filters, root paths) and the directory tree view.
  - setupDockWidgets() owns the search / core-info / log dock
    widgets, including the searchResetButton that previously lived
    as a constructor local.
  - setupSignalConnections() owns the bulk of the QObject::connect
    block plus the m_dirTree initial-selection and m_thumbnailTimer
    setup that was interleaved with it.

  Constructor body: 446 -> 101 lines.

* Three small file-static helpers collapse repeated boilerplate:

  - qt_button_set_action_label() replaces the
    setDefaultAction(new QAction(msg_hash_to_str(label), btn)) +
    setFixedSize(sizeHint()) pair (5 sites).
  - qt_dock_add_to() replaces the
    addDockWidget(static_cast<Qt::DockWidgetArea>(
       dock->property("default_area").toInt()), dock)
    idiom (7 sites).
  - qt_dock_configure() replaces a setObjectName / setProperty(
    "default_area") / setProperty("menu_text") / setWidget
    four-line block (6 sites).

No behaviour change.
2026-05-01 21:24:07 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre d49ccc1478 Qt: cache root index in FileSystemProxyModel::filterAcceptsRow
The proxy model's filterAcceptsRow is called once per (row, parent)
pair the source QFileSystemModel surfaces, which can run into the
tens of thousands during a directory load, sort, or filter pass on
a populous tree. The original implementation resolved the source
model's root path to a QModelIndex via sm->index(sm->rootPath()) on
every single call - cheap individually, but it adds up.

The root path itself only changes when the user navigates, so cache
both the path and its resolved index on the proxy. On each call,
compare the cached path against the current one (a QString equality
check, much cheaper than re-walking the model); refresh on mismatch.

No behaviour change.
2026-05-01 20:34:47 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 146ac2efbc Qt: decode file-browser preview images on a worker thread
Selecting an image file in the file browser ran the PNG/JPEG decode
synchronously on the UI thread via image_texture_load. For ordinary
scraper-sized boxart this is fine, but for the multi-GiB ARGB32
bitmaps that come out of decoding a high-resolution upscayl-style
PNG the UI froze for hundreds of milliseconds to several seconds.
The same stall fired on every selection change, including the
implicit ones triggered by collapsing a tree node when the current
selection became invisible.

Add a ThumbnailLoader owned by MainWindow (parallel to the one
PlaylistModel owns for the grid view) and route the preview-pane
decode through it. The panes are cleared immediately on selection
change; the loaded pixmap is installed when the worker's
imageLoaded signal fires. A pending-path token guards against rapid
selection changes flickering stale images in.

Playlist-thumbnail (scraper boxart) decoding stays synchronous
because those images are bounded in size; the only change there is
that m_pendingPreviewPath is cleared on entry so a previously-issued
preview request can't land in the panes after the playlist code
already painted boxart there.
2026-05-01 20:27:44 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 52a92f848a Qt: companion driver cleanup pass
Refactor pass on ui/drivers/ui_qt.{cpp,h} and ui_qt_widgets.{cpp,h}
to reduce Qt-specific surface, lift pure-C work out of C++ syntax,
and use libretro-common idioms in place of locally-rolled equivalents.

  ui/drivers/ui_qt.cpp           5620 -> 5462    (-158)
  ui/drivers/ui_qt_widgets.cpp   8888 -> 8783    (-105)
  ui/drivers/ui_qt.h              761 ->  747    ( -14)
  ui/drivers/ui_qt_widgets.h     1442 -> 1381    ( -61)
                                                 -----
  TOTAL                         16711 -> 16373   (-338)

No functional change. Build verified for ui_qt.o, ui_qt_widgets.o,
moc_ui_qt.o and moc_ui_qt_widgets.o; the only warnings emitted are
the same three pre-existing -Wdeprecated-declarations warnings the
original tree emits (QDir::operator=(const QString&),
QByteArray::append(const QString&), QListWidget::isItemHidden).

Iterative-build wall clock on the four targets drops ~9%
(28.1s -> 25.6s, hyperfine n=5), MOC-generated .cpp drops ~9%
(8666 -> 7874 lines), and total object size drops ~4%
(2.05 MiB -> 1.97 MiB).

Changes:

* Drop string_split_to_qt and use QString::split. The function was
  declared inside RETRO_BEGIN_DECLS - i.e. with C linkage - but
  returned QStringList, which is not a C-compatible type. The four
  call sites become QString::split('|') / .split(' ').

* Replace MainWindow::getScrubbedString with a static scrub_qstring()
  helper using string_replace_all_chars from libretro-common. Moves
  the function out of MOC (one fewer slot to generate).

* Collapse 11 trivial OptionsPage subclasses (MenuSoundsPage,
  UpdaterPage, QuickMenuPage, DriversPage, DirectoryPage,
  ConfigurationPage, CorePage, LoggingPage, AIServicePage,
  FrameThrottlePage, RewindPage) into one runtime-parameterised
  SimplePage class. Each was a do-nothing constructor plus a
  one-line widget() returning create_widget(DISPLAYLIST_X). The 12
  instantiation sites in *Category::pages() become
  new SimplePage(DISPLAYLIST_X, MENU_ENUM_LABEL_VALUE_X, this).

* Extract MainWindow::getCoreInfo() into a C helper qt_core_info_collect
  that emits two parallel struct string_list outputs (keys, values)
  with a status code (enum qt_core_info_row_status) packed into
  values->elems[i].attr.i. The walking logic is now pure C using
  libretro-common idioms (string_list_*, core_info_*,
  fill_pathname_basedir, string_count_occurrences_single_character);
  the C++ wrapper is a ~50-line loop applying status-driven HTML/CSS
  styling for firmware rows. Both consumers
  (onLaunchWithComboBoxIndexChanged, CoreInfoDialog::showCoreInfo)
  work unchanged.

* Replace four parallel thumbnail paths with arrays. The
  m_thumbnailPixmap{,2,3,4} pointers, onResizeThumbnail{One,Two,
  Three,Four} slots, and thumbnailChanged{,2,3,4} signals are
  consolidated into m_thumbnailPixmaps[4] and three static tables.
  The four thumbnailChanged* signals were never emitted and never
  connected anywhere - deleted. The four onResizeThumbnail* slots
  were one-line wrappers around setThumbnail("thumbnailN", ...) -
  deleted, callers use setThumbnail directly. Destructor,
  onCurrentItemChanged and onThumbnailDropped collapse to short
  loops; an explicit ThumbnailType -> widget-index mapping handles
  the asymmetric ordering between the enum (BOXART, SCREENSHOT,
  TITLE_SCREEN, LOGO) and the 1..4 widget naming (boxart, title,
  screenshot, logo).

* Convert MainWindow::getSelectedCore (which returned
  QHash<QString,QString> but only ever set a single field) to
  getSelectedCorePath returning QString. Sole caller updated.

* Replace QFileInfo/QDir/QFile usage with file_path.h /
  file_stream.h equivalents in three high-leverage spots:

  - renamePlaylistItem: now uses path_basename, path_basedir,
    path_get_extension, fill_pathname_slash,
    string_is_equal_case_insensitive, and filestream_rename.
  - onExtractArchive's per-entry delete-or-rename loop: now uses
    filestream_exists, filestream_delete, filestream_rename. Also
    fixes a pre-existing leak: the original code returned -1 on
    three error paths without freeing file_list.
  - loadContent's extension-filter block: collapses lastIndexOf('.')
    + .mid() onto path_get_extension, which the same block was
    already using three lines below.
  - Three QFileInfo(pathData).suffix() callers in
    add-files-to-playlist code: replaced with
    QString::fromUtf8(path_get_extension(pathData)).

* Split ui_companion_qt_init from a 516-line monolith into six
  focused static helpers (qt_companion_build_menubar,
  qt_companion_build_browser_dock, qt_companion_build_thumbnail_docks,
  qt_companion_build_core_selection_dock, qt_companion_restore_settings,
  qt_companion_select_initial_playlist) plus a ~75-line orchestrator.
  Behaviour preserved verbatim. The thumbnail-dock setup that was
  65 lines of 4-way copy-paste collapses to a 30-line loop using
  qt_thumbnail_widget_names from above.
2026-05-01 20:15:11 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre fca0e40b54 deps/switchres: fix -Wformat warnings on 32-bit builds
Three -Wformat= warnings surface on i386 Linux where size_t is unsigned
int and uint64_t is unsigned long long (both differ from x86_64, where
the existing specifiers happen to match):

  display_linux.cpp:166         %ld    on  vector::size_type (size_t)
  custom_video_xrandr.cpp:679   %lx    on  uint64_t platform_data
  custom_video_xrandr.cpp:685   %lx    on  uint64_t platform_data

The size_t case is signedness-only and benign in practice; switch to
%zu, the C99 specifier intended for size_t. The uint64_t cases are an
actual 32-bit truncation bug -- %lx reads four bytes off the stack on
i386 cdecl, dropping the high 32 bits of platform_data and misaligning
any following format arguments. Use %llx with an explicit
(unsigned long long) cast, matching the raw-printf idiom Switchres
uses everywhere else (no <inttypes.h> / PRIx64 elsewhere in the tree).

deps/switchres/ is a verbatim mirror of antonioginer/switchres; this
fix should also be sent upstream so the next sync doesn't reintroduce
the warnings.
2026-05-01 19:28:58 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 07b6551a23 Silence warning - use fill_pathname_join_special 2026-05-01 18:50:17 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre f38f216256 VULKAN/HDR: Fix crash when statistics overlay is shown over HDR + custom shader
When HDR is enabled and the active shader chain doesn't emit HDR
natively, vulkan_frame() routes overlay-style content (menu, on-screen
messages, widgets, software overlays) through an offscreen SDR
buffer, then composites it back over the HDR swapchain image. The
gating condition for that detour listed every overlay source except
the statistics overlay.

The result: with HDR on, a non-HDR-emitting shader chain loaded, and
the statistics overlay enabled (with no menu/message/widget visible),
the main render pass was ended after the HDR composite but never
re-begun. The subsequent font_driver_render_msg() call for the stat
text recorded draw commands against a command buffer with no active
render pass.

Most desktop Vulkan drivers tolerate this with a validation error;
MoltenVK on macOS dereferences a null subpass in
MVKCommandEncoder::getSubpass() during vkCmdDrawIndexed encoding and
crashes with SIGSEGV. The HDR-native shaders under slang_shaders/hdr
were unaffected because they avoid the offscreen-buffer detour
entirely (use_offscreen_buffer stays false when the chain emits HDR10
or HDR16).

Add statistics_show to both gating conditions so the begin-redirect
and the matching post-blit composite stay balanced.
2026-05-01 18:37:29 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre a38a63853e Add regression tests 2026-05-01 18:30:30 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 09b66cab9b retro_atomic: shield <atomic> include from caller's extern "C"
ui_qt.cpp wraps RetroArch headers in extern "C" { ... } when CXX_BUILD
is not defined. In non-unity builds the chain

  ui_qt.cpp (extern "C") -> menu_driver.h -> gfx_thumbnail.h
    -> retro_atomic.h -> <atomic>

ends up parsing libstdc++ <atomic> under C linkage, producing dozens of
"template with C linkage" errors on g++. The same hazard exists for any
C++ TU that wraps RetroArch headers in extern "C", and is currently
masked elsewhere only because no other such TU happens to pull in a
header that reaches retro_atomic.h.

Fix at the header level so every caller is protected, not just ui_qt.cpp:

 - Add RETRO_BEGIN_DECLS_CXX / RETRO_END_DECLS_CXX to retro_common_api.h.
   They expand to extern "C++" { ... } in C++ mode (with CXX_BUILD off)
   and to nothing otherwise, mirroring the existing RETRO_BEGIN_DECLS /
   RETRO_END_DECLS pair.

 - Use them around the <atomic> / <cstddef> include in retro_atomic.h's
   C++11 backend. The standard headers parse at C++ linkage regardless
   of any surrounding extern "C" the caller imposes; the rest of the
   file (typedefs and macros, no function declarations) is unaffected.

The previous comment claiming "no need for RETRO_BEGIN_DECLS / extern
\"C\" wrapping ... the wrapper would actively break that path" addressed
only half the problem -- the file's own wrapping -- and missed that the
caller's wrapper leaks into the <atomic> include. Updated to reflect
the real constraint.
2026-05-01 18:16:29 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre a340c70468 video_driver_apply_state_changes only gets called from command_event 2026-05-01 12:11:45 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 6224ab67b9 gl3: clarify shader-fallback comment about GLSL vs Cg
The comment added in 276e4bc said gl3 'only ever advertises slang via
spirv-cross', which overstated things.  Context drivers do only
advertise SLANG for glcore, but the gl3 fallback selector itself
accepts both GLSL and SLANG as first-class types -- and 42aa9fd just
made GLSL a valid GL3_DEFAULT_SHADER_TYPE on builds without slang.

Reword the comment to be specific about what is and isn't dead:
  - Cg is dead (no context flag, ARB asm pipeline incompatible with
    Core Profile)
  - GLSL is alive (Core-compatible API surface, kept as fallback for
    no-slang builds)
  - Slang is the practical default

No code change.
2026-05-01 12:06:14 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 42aa9fd60a move DEFAULT_SHADER_TYPE to gl2/gl3.c 2026-05-01 12:03:02 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 276e4bce82 gl3: remove dead Cg shader-backend paths from glcore driver
The gl3 (glcore video driver) shader fallback selector and dispatcher
both had RARCH_SHADER_CG arms, but those branches were unreachable
in any build configuration:

1. The Cg fallback in gl3_get_fallback_shader_type gates on
   GFX_CTX_FLAGS_SHADERS_CG.  No context driver ever sets that
   flag when the active video driver is "glcore" -- audited
   x_ctx.c:1106-1116, wgl_ctx.c:778-788, drm_ctx.c, drm_go2_ctx.c,
   orbis_ctx.c, switch_ctx.c, wayland_ctx.c, xegl_ctx.c (eight
   context drivers, all of which the glcore branch advertises only
   SHADERS_SLANG).  The Cg flag is only set by ps3_ctx (which uses
   the rsx driver, not glcore) and by the legacy / non-Core branch
   of x_ctx and wgl_ctx (gated on !core_hw_context_enable, so only
   for the gl driver, not glcore).

2. Even if the gating were bypassed, gl_cg_backend in
   shader_gl_cg.c uses cgGLEnableProfile / cgGLBindProgram /
   cgGLEnableClientState et al.  These rely on the legacy ARB
   asm program pipeline (GL_VERTEX_PROGRAM_ARB style) which is
   removed from Core Profile contexts.  NVIDIA's Cg runtime hasn't
   been updated since 2012 and has no Core Profile support.

Remove:
 - the RARCH_SHADER_CG case in gl3_get_fallback_shader_type
 - the RARCH_SHADER_CG case in gl3_shader_driver_set_backend
 - HAVE_CG from the function-level guard
 - the now-unused 3rd loop iteration (the cycle is GLSL <-> SLANG)

The fallback chain becomes a 2-element cycle: GLSL falls back to
SLANG and vice versa, matching what the gating actually allows.

Add a comment at the top of gl3_get_fallback_shader_type explaining
the gl3-vs-Cg situation so future readers don't reintroduce the dead
arm.  No behaviour change on any build: HAVE_CG was defined for some
Windows builds, but the gates above already prevented those branches
from executing.
2026-05-01 11:58:43 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre cd386a3933 [GameMode] Don't probe libgamemode on every config load, preserve user setting
Two related fixes for the GameMode startup behavior on Linux:

1. configuration.c: Only call frontend_driver_set_gamemode() during config
   load when gamemode_enable is actually true. Previously the probe ran
   unconditionally with the current setting value, meaning every user on
   every config load triggered a dlopen of libgamemode.so even when the
   feature was off - producing log spam ("[GameMode] GameMode cannot be
   enabled on this system...") for the majority of users who don't have
   libgamemode installed.

   Also stop force-disabling gamemode_enable in the config when the probe
   fails. Silently flipping the user's preference to false and persisting
   it to retroarch.cfg meant a transient failure (sandbox path issue,
   library not yet installed, multi-arch mismatch, etc.) would require
   the user to manually re-enable the option on every subsequent launch.
   The user's intent should survive across sessions; if libgamemode shows
   up later, the next launch picks it up automatically.

2. frontend/drivers/platform_unix.c: Latch the unavailable state inside
   frontend_unix_set_gamemode() once gamemode_query_status() reports
   failure. The result will not change for the lifetime of the process,
   so subsequent calls (deinit cleanup, menu toggles) short-circuit
   without re-entering the Feral client code and without re-emitting the
   warning. The warning now fires exactly once per process when the user
   has gamemode enabled but libgamemode is missing.

The redundant "[Config] GameMode unsupported - disabling..." follow-up
warning is removed - it added no information beyond what the GameMode
warning already conveys.
2026-05-01 11:35:46 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 0a7758076d Silence VS2019 warnings 2026-05-01 11:11:28 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 98f5b4a0a2 (D3D12) Remove unused variable 2026-05-01 10:26:41 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 323e8b5c5f Fix metal warnings 2026-05-01 10:24:02 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre bb5f72dce1 Silence warnings 2026-05-01 10:13:01 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 6a3bcdc083 Silence warnings 2026-05-01 10:11:01 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 2aeaa5fd25 Silence more warnings 2026-05-01 10:01:04 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre c380ff5743 Silence sdl2_gfx warning 2026-05-01 09:45:38 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre f25536c970 Fix spirv-cross warning fix 2026-05-01 09:38:46 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 75b55c2334 Silence glslang warnings 2026-05-01 09:36:42 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre f3f48bd991 Silence warnings for stb_vorbis 2026-05-01 09:33:38 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 8ec8c32803 Fix warnings for Android 2026-05-01 09:29:51 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre dcf6cc7520 Warning fixes #2 2026-05-01 09:21:31 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 7a8fd93d67 Fix various warnings 2026-05-01 08:52:15 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre e5a74e7cf3 Add missing files 2026-05-01 07:56:39 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 6f8afa7a88 Folding - we want one file per filter 2026-05-01 07:53:20 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 4375682df3 Buildfixes 2026-05-01 07:41:36 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 24135f05c4 Should never include stdbool.h for MSVC backwards compat 2026-05-01 07:35:17 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre e225095fe1 Add two new filters 2026-05-01 07:29:24 +02:00
metallic77 181b550689 Add files via upload (#18987)
* Add files via upload

* Update crop_borders.c

* Add EMMIR NTSC default "crt" variant

compiles and runs perfectly fine on linux Mint.

* Add files via upload
2026-05-01 07:25:51 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 8645f04fa4 scaler/pixconv: fix conv_rgba4444_argb8888 MMX alpha handling
The MMX fast path of conv_rgba4444_argb8888 hardcoded the alpha
channel to 0xff instead of extracting it from the source's low
nibble.  The scalar fallback (lines 488-501) correctly does
'a = (col >> 0) & 0xf; a = (a << 4) | a' to expand the 4-bit
source alpha into 8 bits.  The MMX kernel kept the
'const __m64 a = _mm_set1_pi16(0x00ff)' constant from the
sibling conv_rgb565_argb8888 / conv_0rgb1555_argb8888 functions
(whose 16-bit sources have no alpha channel), so on x86 hosts
where __MMX__ is defined (which includes all x86_64 builds, since
gcc enables MMX by default alongside SSE2) RGBA4444 input was
silently converted with full opacity regardless of source alpha.

Same shape of bug as commit 9403719 (conv_rgb565_abgr8888 SSE2):
SIMD kernel inherited from a sibling without adapting all the
needed steps to the new format.

Fix: extract alpha from the low nibble (in & 0x000f), expand to
8 bits via _mm_mullo_pi16(a, 0x0011) which computes a * 17 ==
(a << 4) | a for any 4-bit value.

Verified bit-exact against the scalar fallback for every possible
RGBA4444 input.  Brute-force test of all 65,536 16-bit values:
  before fix: 61,440 of 65,536 outputs differ from scalar (94%;
              all inputs whose low nibble != 0xf produce wrong
              alpha)
  after fix:  0 of 65,536 differ

Caller audit: hit by gfx/drivers/gl1.c:1810 (RGUI menu fallback
expansion when GL_EXT_packed_pixels is unsupported -- triggers on
ancient OpenGL implementations and the Vita gl1 build) and via
the scaler chain when SCALER_FMT_RGBA4444 is paired with
SCALER_FMT_ARGB8888 (libretro-common/gfx/scaler/scaler.c:183 and
:232).  On x86_64 the MMX path is hot in both contexts.
2026-05-01 06:41:47 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 13d279d1e6 (Metal) Cleanups 2026-05-01 06:20:49 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 8e9131b4a7 dxgi_common: use pixconv conv_rgb565_argb8888 for B5G6R5 -> B8G8R8A8
Companion to 7e44a5e (which covered B5G6R5 -> R8G8B8A8 with
conv_rgb565_abgr8888).  The B8G8R8A8_UNORM destination has byte
order [b g r a] in memory, which is exactly what pixconv's
conv_rgb565_argb8888 produces (uint32 LE
(a << 24) | (r << 16) | (g << 8) | b).  Bit-identical output to
the existing scalar loop's
(r << 16) | (g << 8) | b | (255 << 24).

Same speedup characteristics as the abgr8888 case: ~2x at sub-4K
resolutions, ~1.4x at 4K.  Sub-millisecond absolute savings at
typical emulator resolutions.

Other dxgi_copy pairs considered but skipped:
  - B5G6R5 -> B8G8R8X8: pixconv conv_rgb565_argb8888 puts 0xff
    in the X byte where the existing scalar writes 0; per-spec
    'X' means undefined, but preserving bit-for-bit existing
    behavior avoids a subtle change.
  - R8G8B8A8 <-> B8G8R8A8 byte-swap pairs: pixconv's
    conv_argb8888_abgr8888 is scalar only (3-op bit-twiddle).
    Benchmarked at parity with the dxgi loop after compiler
    auto-vectorization (~0.9x to 1.1x, within noise).  No perf
    win; code consolidation alone insufficient justification.
2026-05-01 05:56:56 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 7e44a5e98c dxgi_common: use pixconv conv_rgb565_abgr8888 for B5G6R5 -> R8G8B8A8
dxgi_copy's scalar loop for the B5G6R5_UNORM -> R8G8B8A8_UNORM
format pair is exactly conv_rgb565_abgr8888 in pixconv.c.  The
output uint32 (a << 24) | (b << 16) | (g << 8) | r matches DXGI
R8G8B8A8_UNORM byte order [r g b a] and matches pixconv's abgr8888
output verbatim.

Replace the open-coded scalar loop with a call into pixconv,
removing one of dxgi_copy's many hand-rolled per-pixel converters
in favor of the canonical SIMD-aware implementation.

Code-consolidation patch with measured speedup as a side benefit:

  Resolution    scalar (ms/frame)  pixconv SSE2 (ms/frame)  speedup
  256x224       0.03               0.02                     2.3x
  640x480       0.19               0.09                     2.1x
  1280x720      0.59               0.27                     2.2x
  1920x1080     1.37               0.69                     2.0x
  3840x2160     6.5                4.7                      1.4x

(x86_64 Linux, gcc -O3 -msse2, average of 3 runs.)  Absolute
savings sub-millisecond at typical emulator resolutions; modestly
helpful at 1080p/4K.  ARM/NEON path produces equivalent output.

Other dxgi_copy format-pair branches have less clean pixconv
matches (e.g. B5G6R5 -> B8G8R8X8 nearly matches conv_rgb565_argb8888
but pixconv writes 0xff in the X byte where the existing scalar
writes 0; preserving the existing behavior bit-for-bit would
require a new pixconv variant, so leaving those alone for now).
2026-05-01 05:50:36 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 940371933f scaler/pixconv: fix conv_rgb565_abgr8888 SSE2 byte order
The SSE2 fast path of conv_rgb565_abgr8888 produced ARGB byte order
in memory ([b g r a] per pixel), not ABGR ([r g b a]).  The scalar
fallback (lines 387-396) and the NEON fast path (lines 369-385)
both produce the correct ABGR byte order.  On x86 hosts with SSE2
the function silently returned a different byte layout than its
name promised and than its scalar fallback delivered.

Root cause: the SSE2 kernel at lines 358-365 was a literal copy of
the conv_rgb565_argb8888 SSE2 kernel at lines 247-255 (the two
were byte-for-byte identical).  Both pair (b,g) into the low half
of each pixel and (r,a) into the high half shifted up 2 bytes,
producing [b g r a] byte order which is ARGB uint32 LE.  That's
correct for argb8888 but wrong for abgr8888.

Fix: swap the unpack pairings so (r,g) goes into the low half and
(b,a) into the high half shifted up 2 bytes, producing [r g b a]
byte order == ABGR uint32 LE.  Same instruction count (4 unpacks +
1 shift + 2 ors), same vector width (8 pixels per iteration), no
perf change.

Verified bit-exact against the scalar fallback for every possible
RGB565 input.  Brute-force test of all 65,536 16-bit values:
  before fix: 63,488 of 65,536 outputs differ from scalar (97%)
  after fix:  0 of 65,536 differ
For pure red input 0xF800:
  scalar:    0xFF0000FF (ABGR uint32, R in low byte)
  SSE before: 0xFFFF0000 (ARGB uint32, R in second byte)
  SSE after:  0xFF0000FF (matches scalar)

Caller audit: of the production sites that route to pixconv via
the SCALER_FMT_ABGR8888 dispatch in scaler.c:126, none are
currently observed to hit the RGB565 -> ABGR8888 pair on an x86
host running SSE2.  vulkan.c and gl3.c readback paths use ABGR8888
-> BGR24 (different pair).  switch_nx_gfx is ARM64 (NEON, not
affected).  pipewire camera input could in principle hit it if a
camera produces RGB565 output, but modern webcams typically
produce YUYV / MJPEG.  The bug has been hidden by absence of
production callers; this fix prevents future contributors from
inheriting it.
2026-05-01 05:38:48 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre e02161e1f2 gfx/vga: rename vga_t::vga_video_{...} to frame_*, publish VGA size to set_output_size
Two related changes to the VGA framebuffer driver, applying the
same pattern as the gl1 / fpga / gdi / network / sixel / caca
sequence (d654940 / 61ce292 / e675181 / 4668a2f / ad986a6) plus
the bug fix that the caca work surfaced.

Rename
------

The four vga_video_* fields on vga_t hold the libretro core's
emulated frame size: assigned from video->width / video->height
at init (line 201-202), updated from frame_width / frame_height
per-call (line 248-258), and consumed by the per-pixel scaling
loops at line 303-304 / 327-328 which scale the core's frame
down to fit the actual VGA framebuffer (VGA_WIDTH x VGA_HEIGHT =
320x200).

Rename, dropping the redundant vga_ prefix while we're at it
(the struct is already called vga_t):

  vga_video_width  -> frame_width
  vga_video_height -> frame_height
  vga_video_pitch  -> frame_pitch
  vga_video_bits   -> frame_bits

The renamed fields parallel vga_t's existing vga_menu_* group:
both are "input frame from $source", just one is the menu
surface and the other is the running core.

Bug fix
-------

vga_gfx_alive called video_driver_set_output_size with the
renamed frame_width / frame_height -- the libretro core's frame
size, e.g. 256x224 for SNES.  Per the docstring added in cecd19f,
set_output_size publishes the area where the active video driver
presents pixels.  For this driver that area is the VGA hardware
framebuffer at VGA_WIDTH x VGA_HEIGHT (320x200, mode 13h).  Lines
303-304 and 327-328 already scale the core's frame down to fit
it; those constants are the actual output area.  Pass them to
set_output_size instead.

The bug was hidden behind the misleading old field name: when
the field was called vga_video_width and held the core's frame
size, the video_driver_set_output_size(vga->vga_video_width, ...)
call read like it made sense.  After the rename, the same call
reads as video_driver_set_output_size(vga->frame_width, ...) --
visibly wrong at the call site, exactly the class of confusion
the rename pattern was meant to surface.

The existing TODO/FIXME comment immediately above the call --
"check if this is valid" -- was correctly placed; the original
author knew something was off.  Comment dropped, it's resolved.

Same shape as the caca fix in ad986a6.

Risk: if any caller of video_driver_get_output_size on vga was
relying on seeing the core's frame size (the old buggy value),
they will now see VGA_WIDTH x VGA_HEIGHT instead.  No such
caller is plausible: the API contract is the output area, and
the menu drivers / input drivers were getting nonsense input
under the old behaviour (a 256x224 output area on a 320x200
framebuffer would draw widgets clipped or off-screen).  This is
a strict bug fix in the direction of the documented contract.

Incidentally fixes a stale comment in sdl2_gfx.c at line 258
that listed vga in "Most other drivers (vga, gx2, d3d8, d3d9
common) make this call too" -- before this commit, vga was
making the call but not correctly; after, the comment is true.

Same risk profile as the rest of the rename pattern: vga_t is
file-private (declared at the top of vga_gfx.c with no header
counterpart, verified by grep across the source tree).  No
external callers besides the comment fix in sdl2_gfx.c.
2026-05-01 05:04:17 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 3179216a85 more warning fixes 2026-05-01 04:59:11 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre 89d79d93b6 Buildfixes 2026-05-01 04:52:56 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre cecd19ff0a video_driver: rename {get,set}_size -> {get,set}_output_size
video_driver_get_size and video_driver_set_size publish the size of
the area where the active video driver presents pixels to the user.
The old name says "size" without saying "size of what," and the
ambiguity has cost: the caca driver bug fixed in ad986a6 was hidden
behind exactly this confusion -- caca was passing the libretro
core's frame size to set_size when the API contract was the canvas
(surface) size, and the call site looked plausible until the field
was renamed to expose what it actually held.

Rename the public API to make the contract explicit at the call
site, and add the documentation comment that should have been on
these declarations from the start:

  video_driver_get_size  -> video_driver_get_output_size
  video_driver_set_size  -> video_driver_set_output_size

"output_size" was chosen over the alternatives:

  - window_size is wrong on terminal drivers (caca, sixel) and
    DRM-fullscreen-no-window
  - surface_size collides with SDL_Surface and D3D surface concepts
  - display_size implies the physical monitor, not the output area
  - present_size is jargon and reads oddly as a noun
  - viewport_size collides with the existing vp.{width,height}
    aspect-corrected sub-rect

"output_size" describes purpose (size of the visible output area)
without implying mechanism, doesn't collide with existing terms,
and maps cleanly onto every driver: desktop window output, DRM
scanout output, libcaca canvas output, sixel terminal output.

The doc comment in gfx/video_driver.h spells out the per-driver
mapping (window client area for desktop GL/D3D/Vulkan/Metal,
framebuffer scanout for DRM/KMS, canvas grid for libcaca,
terminal output region for sixel), the consumer list (menu
drivers, CRT switcher, shader subsystem, input drivers, other
video drivers), threading (protected by video_st->display_lock),
and explicitly contrasts with the libretro core's frame size that
lives on each driver's local state (frame_width / frame_height
after the gl1 / fpga / gdi / network / sixel / caca renames; gl2
/ gl3 still keep their canonical video_width / video_height which
mean the backbuffer size).

74 call sites across 33 files updated by word-boundary sed; no
collisions (no other identifiers contain video_driver_get_size or
_set_size as a substring).

Validation: the file with the function definitions
(gfx/video_driver.o) and a representative sample of caller files
(menu/drivers/{xmb,ozone,materialui}.o, gfx/drivers/gl{1,2,3}.o,
gfx/video_crt_switch.o, gfx/video_shader_parse.o) all build clean
in this sandbox.  The remaining 24 files hit unrelated
dependency errors (windows.h not on Linux, libcaca / libvg
headers not installed) before reaching anything rename-related;
none produced a rename-related diagnostic.  Maintainer review on
a full build environment recommended before merge.

No behavior change.  Pure rename + documentation.
2026-05-01 04:49:33 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre ad986a63ee Same thing with caca driver 2026-05-01 04:36:05 +02:00
U-DESKTOP-SPFP6AQ\twistedtechre e675181c42 Same stuff as before in prior commits - clear deliniation between
frame_width/frame_height and backbuffer width/height
2026-05-01 04:28:05 +02:00