Skip to content

Commit e0c3946

Browse files
committed
Add display-format preference and RGB10A2 support
Introduce a launch-time display-format preference (auto/rgba8/rgb10a2/hdr) with precedence: --display-format, IMIV_DISPLAY_FORMAT, saved imiv.inf preference, then auto. Add --display-format CLI parsing and IMIV_DISPLAY_FORMAT environment support; preference is persisted in imiv.inf and changes are next-launch only. HDR is reserved and currently falls back to auto. UI: expose display-format selector in Preferences and save/load display_format state. Validate/sanitize values and surface helpful UI messages when rgb10a2 or hdr are requested. Renderer/platform: thread requested display format through app/renderer state. GLFW: add framebuffer bit hints for OpenGL when requesting RGB10A2. OpenGL: probe window with requested format and log actual framebuffer bits. Vulkan: request 10-bit surface formats when requested, select surface format and present mode, record whether swapchain supports transfer-src (screenshots), and expose verbose logging and fallback reporting. Metal: choose display and preview pixel formats per preference, create pipelines/textures accordingly, and fall back to BGRA8 when 10-bit formats are unavailable; verbose logging reports selection and fallbacks. Capture: implement conversion utilities for Vulkan and Metal to convert various framebuffer formats (including A2R10/A2B10 packed formats) into RGBA8 for screenshots/previews; fail gracefully when format unsupported. Misc: update persistence read/write, types/headers, and several renderer/backends to carry the new DisplayFormatPreference. Add helper functions for parsing/printing display-format names and some Vulkan/Metal format name helpers for logging.
1 parent e9a1095 commit e0c3946

20 files changed

Lines changed: 699 additions & 77 deletions

src/doc/imiv_dev.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,18 @@ Backend preference changes made in the Preferences window are persistent but
10821082
take effect on the next launch. This is intentional and should remain true for
10831083
all backends.
10841084

1085+
The launch-time display-format request resolves in this order:
1086+
1087+
1. the `--display-format` command-line option, if supplied;
1088+
2. the `IMIV_DISPLAY_FORMAT` environment variable, if set;
1089+
3. the saved `display_format` preference from `imiv.inf`;
1090+
4. `auto`, which keeps the backend default presentation format.
1091+
1092+
Display-format preference changes are also persistent and next-launch only.
1093+
The current implemented non-default request is `rgb10a2` for 10-bit SDR
1094+
presentation. `hdr` is parsed as a reserved value but falls back to `auto`
1095+
until the backends have an explicit HDR/EDR color-space path.
1096+
10851097
For isolated local repros and tests, set `IMIV_CONFIG_HOME` so preference
10861098
changes do not bleed into your normal user config.
10871099

src/doc/imiv_user.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ image list. For example::
4949

5050
imiv --backend vulkan frame.exr
5151

52+
imiv --display-format rgb10a2 frame.exr
53+
5254
imiv --display "sRGB - Display" \
5355
--view "ACES 2.0 - SDR 100 nits (Rec.709)" \
5456
--image-color-space ACEScg image.exr
@@ -85,6 +87,20 @@ Use :program:`imiv --help` to print the option summary for the current build.
8587
:program:`imiv` falls back to the resolved default backend and prints a
8688
message.
8789

90+
.. option:: --display-format FORMAT
91+
92+
Request a display presentation format at launch time. Valid values are
93+
`auto`, `rgba8`, `rgb10a2`, and `hdr`.
94+
95+
`rgba8` keeps the default 8-bit SDR path. `rgb10a2` requests 10-bit SDR
96+
presentation from the renderer backend and falls back to the backend's
97+
default format if unsupported. `hdr` is accepted for forward compatibility
98+
but currently falls back to `auto`; HDR/EDR output still needs a dedicated
99+
color-space and presentation path.
100+
101+
The command-line request takes precedence over the saved display-format
102+
preference and the ``IMIV_DISPLAY_FORMAT`` environment variable.
103+
88104
.. option:: --list-backends
89105

90106
Print the backend support compiled into the current :program:`imiv`
@@ -370,6 +386,7 @@ Saved state currently includes:
370386
* Dear ImGui docking/window layout;
371387
* viewer and preview defaults for the primary view;
372388
* backend preference (`renderer_backend`);
389+
* display format preference (`display_format`);
373390
* whether the main window is `Always on Top`;
374391
* OCIO settings;
375392
* recent images and sort mode.
@@ -378,6 +395,7 @@ Example::
378395

379396
[ImivApp][State]
380397
renderer_backend=vulkan
398+
display_format=rgb10a2
381399
fit_image_to_window=1
382400
window_always_on_top=0
383401
use_ocio=1
@@ -390,6 +408,9 @@ the compiled backends, plus ``Auto``. Changing the backend preference updates
390408
the next-launch backend and shows a restart-required note. The active backend
391409
for the current process does not change until the next launch.
392410

411+
The same Preferences section exposes the display-format request. Changing it is
412+
persistent and also applies on the next launch.
413+
393414
Developer mode may also be controlled by the ``OIIO_DEVMODE`` environment
394415
variable. Acceptable values include ``1``, ``0``, ``true``, ``false``, ``on``,
395416
``off``, ``yes``, and ``no``. The command-line ``--devmode`` flag takes

src/imiv/imiv_app.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,30 @@ namespace {
193193
return sanitize_backend_kind(ui_state.renderer_backend);
194194
}
195195

196+
DisplayFormatPreference
197+
requested_display_format_for_launch(const AppConfig& config,
198+
const PlaceholderUiState& ui_state,
199+
bool verbose_logging)
200+
{
201+
DisplayFormatPreference requested = sanitize_display_format_preference(
202+
ui_state.display_format);
203+
std::string env_value;
204+
if (read_env_value("IMIV_DISPLAY_FORMAT", env_value)) {
205+
DisplayFormatPreference env_format = DisplayFormatPreference::Auto;
206+
if (parse_display_format_preference(env_value, env_format)) {
207+
requested = env_format;
208+
} else if (verbose_logging) {
209+
print(stderr,
210+
"imiv: ignoring invalid IMIV_DISPLAY_FORMAT value '{}'; "
211+
"expected auto/rgba8/rgb10a2/hdr\n",
212+
env_value);
213+
}
214+
}
215+
if (config.display_format_explicit)
216+
requested = config.requested_display_format;
217+
return sanitize_display_format_preference(static_cast<int>(requested));
218+
}
219+
196220
void apply_glfw_topmost_state_to_platform_windows(GLFWwindow* main_window,
197221
bool always_on_top)
198222
{
@@ -325,6 +349,14 @@ run(const AppConfig& config)
325349
library.sort_mode, library.sort_reverse);
326350
const BackendKind requested_backend
327351
= requested_backend_for_launch(run_config, ui_state);
352+
DisplayFormatPreference requested_display_format
353+
= requested_display_format_for_launch(run_config, ui_state,
354+
run_config.verbose);
355+
if (requested_display_format == DisplayFormatPreference::Hdr) {
356+
print(
357+
"imiv: display format 'hdr' is not implemented yet; using auto\n");
358+
requested_display_format = DisplayFormatPreference::Auto;
359+
}
328360

329361
const bool verbose_logging = run_config.verbose;
330362
const bool verbose_validation_output
@@ -400,7 +432,8 @@ run(const AppConfig& config)
400432
= Strutil::fmt::format("ImIv v.{} [{}]", OIIO_VERSION_STRING,
401433
backend_cli_name(active_backend));
402434
GLFWwindow* window
403-
= platform_glfw_create_main_window(active_backend, 1600, 900,
435+
= platform_glfw_create_main_window(active_backend,
436+
requested_display_format, 1600, 900,
404437
window_title.c_str(), startup_error);
405438
if (window == nullptr) {
406439
print(stderr, "imiv: {}\n", startup_error);
@@ -426,6 +459,7 @@ run(const AppConfig& config)
426459

427460
RendererState renderer_state;
428461
renderer_select_backend(renderer_state, active_backend);
462+
renderer_state.requested_display_format = requested_display_format;
429463
renderer_state.verbose_logging = verbose_logging;
430464
renderer_state.verbose_validation_output = verbose_validation_output;
431465
renderer_state.log_imgui_texture_updates = log_imgui_texture_updates;
@@ -532,6 +566,8 @@ run(const AppConfig& config)
532566
run_config.input_paths.size());
533567
print("imiv: native file dialogs: {}\n",
534568
FileDialog::available() ? "enabled" : "disabled");
569+
print("imiv: requested display format: {}\n",
570+
display_format_cli_name(requested_display_format));
535571
}
536572

537573
#if !defined(IMGUI_ENABLE_TEST_ENGINE)

src/imiv/imiv_app.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ struct AppConfig {
2323
bool developer_mode_explicit = false;
2424

2525
BackendKind requested_backend = BackendKind::Auto;
26+
DisplayFormatPreference requested_display_format
27+
= DisplayFormatPreference::Auto;
28+
bool display_format_explicit = false;
2629

2730
std::string ocio_display;
2831
std::string ocio_image_color_space;

src/imiv/imiv_aux_windows.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,51 @@ namespace {
600600
}
601601
}
602602

603+
void draw_display_format_selector_row(PlaceholderUiState& ui, float spacing)
604+
{
605+
DisplayFormatPreference requested_format
606+
= sanitize_display_format_preference(ui.display_format);
607+
const float row_width = std::max(1.0f,
608+
ImGui::GetContentRegionAvail().x);
609+
const float button_width = std::max(1.0f, (row_width - spacing * 2.0f)
610+
/ 3.0f);
611+
612+
if (draw_preferences_segment_button("pref_display_auto", "Auto",
613+
requested_format
614+
== DisplayFormatPreference::Auto,
615+
true, button_width)) {
616+
ui.display_format = static_cast<int>(DisplayFormatPreference::Auto);
617+
}
618+
register_test_engine_item_label("pref-display-format:auto");
619+
register_layout_dump_synthetic_item("button", "Display format Auto");
620+
621+
ImGui::SameLine(0.0f, spacing);
622+
requested_format = sanitize_display_format_preference(
623+
ui.display_format);
624+
if (draw_preferences_segment_button(
625+
"pref_display_rgba8", "RGBA8",
626+
requested_format == DisplayFormatPreference::Rgba8, true,
627+
button_width)) {
628+
ui.display_format = static_cast<int>(
629+
DisplayFormatPreference::Rgba8);
630+
}
631+
register_test_engine_item_label("pref-display-format:rgba8");
632+
register_layout_dump_synthetic_item("button", "Display format RGBA8");
633+
634+
ImGui::SameLine(0.0f, spacing);
635+
requested_format = sanitize_display_format_preference(
636+
ui.display_format);
637+
if (draw_preferences_segment_button(
638+
"pref_display_rgb10a2", "RGB10A2",
639+
requested_format == DisplayFormatPreference::Rgb10A2, true,
640+
button_width)) {
641+
ui.display_format = static_cast<int>(
642+
DisplayFormatPreference::Rgb10A2);
643+
}
644+
register_test_engine_item_label("pref-display-format:rgb10a2");
645+
register_layout_dump_synthetic_item("button", "Display format RGB10A2");
646+
}
647+
603648
void draw_backend_preference_info(PlaceholderUiState& ui,
604649
BackendKind active_backend)
605650
{
@@ -627,6 +672,10 @@ namespace {
627672
table_labeled_row("Next launch backend");
628673
draw_right_aligned_text(backend_display_name(next_launch_backend));
629674

675+
table_labeled_row("Display format");
676+
draw_right_aligned_text(display_format_display_name(
677+
sanitize_display_format_preference(ui.display_format)));
678+
630679
table_labeled_row("Generate mipmaps");
631680
draw_right_aligned_checkbox("##pref_auto_mipmap", ui.auto_mipmap);
632681
ImGui::EndTable();
@@ -674,6 +723,15 @@ namespace {
674723
if (requested_backend == BackendKind::Auto)
675724
draw_disabled_wrapped_text(
676725
"Auto selects the first available backend.");
726+
const DisplayFormatPreference requested_format
727+
= sanitize_display_format_preference(ui.display_format);
728+
if (requested_format == DisplayFormatPreference::Rgb10A2) {
729+
draw_disabled_wrapped_text(
730+
"RGB10A2 requests 10-bit SDR presentation and falls back when unsupported.");
731+
} else if (requested_format == DisplayFormatPreference::Hdr) {
732+
draw_disabled_wrapped_text(
733+
"HDR/EDR presentation is reserved for a future backend path.");
734+
}
677735
for (const BackendRuntimeInfo& info : runtime_backend_info()) {
678736
if (!info.build_info.compiled || info.available)
679737
continue;
@@ -709,6 +767,8 @@ namespace {
709767
backend_row_min,
710768
backend_row_max);
711769
}
770+
ImGui::Spacing();
771+
draw_display_format_selector_row(ui, spacing);
712772
draw_backend_preference_info(ui, active_backend);
713773
draw_backend_status_messages(ui, active_backend);
714774
}

src/imiv/imiv_backend.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ namespace Imiv {
1212

1313
enum class BackendKind : int { Auto = -1, Vulkan = 0, Metal = 1, OpenGL = 2 };
1414

15+
enum class DisplayFormatPreference : int {
16+
Auto = -1,
17+
Rgba8 = 0,
18+
Rgb10A2 = 1,
19+
Hdr = 2
20+
};
21+
1522
struct BackendInfo {
1623
BackendKind kind = BackendKind::Auto;
1724
const char* cli_name = "auto";
@@ -38,6 +45,15 @@ const char*
3845
backend_display_name(BackendKind kind);
3946
const char*
4047
backend_runtime_name(BackendKind kind);
48+
DisplayFormatPreference
49+
sanitize_display_format_preference(int value);
50+
bool
51+
parse_display_format_preference(std::string_view value,
52+
DisplayFormatPreference& out_format);
53+
const char*
54+
display_format_cli_name(DisplayFormatPreference format);
55+
const char*
56+
display_format_display_name(DisplayFormatPreference format);
4157
BackendKind
4258
active_build_backend_kind();
4359
BackendKind

0 commit comments

Comments
 (0)