libobs-winrt, win-capture: Linear SRGB support

Update window, display, and game capture to always bilinear filter in
linear space, even if the source texture is not SRGB typed. This helps
resolve confusion in situations where we were filtering in nonlinear
space vs. linear space, like when toggling an empty crop filter.
This commit is contained in:
jpark37
2021-07-06 22:10:57 -07:00
parent ebfbe1a78e
commit bf27941f5f
8 changed files with 263 additions and 129 deletions

View File

@@ -5,14 +5,27 @@
static inline void init_textures(struct dc_capture *capture)
{
if (capture->compatibility)
if (capture->compatibility) {
capture->texture = gs_texture_create(capture->width,
capture->height, GS_BGRA,
1, NULL, GS_DYNAMIC);
else
} else {
capture->texture =
gs_texture_create_gdi(capture->width, capture->height);
if (capture->texture) {
capture->extra_texture = gs_texture_create(
capture->width, capture->height, GS_BGRA, 1,
NULL, 0);
if (!capture->extra_texture) {
blog(LOG_WARNING, "[dc_capture_init] Failed to "
"create textures");
gs_texture_destroy(capture->texture);
capture->texture = NULL;
}
}
}
if (!capture->texture) {
blog(LOG_WARNING, "[dc_capture_init] Failed to "
"create textures");
@@ -73,6 +86,7 @@ void dc_capture_free(struct dc_capture *capture)
}
obs_enter_graphics();
gs_texture_destroy(capture->extra_texture);
gs_texture_destroy(capture->texture);
obs_leave_graphics();
@@ -165,41 +179,48 @@ void dc_capture_capture(struct dc_capture *capture, HWND window)
capture->texture_written = true;
}
static void draw_texture(struct dc_capture *capture, gs_effect_t *effect)
static void draw_texture(struct dc_capture *capture, bool texcoords_centered)
{
gs_texture_t *texture = capture->texture;
gs_effect_t *effect = obs_get_base_effect(OBS_EFFECT_OPAQUE);
gs_technique_t *tech = gs_effect_get_technique(effect, "Draw");
gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
size_t passes;
const bool linear_srgb = gs_get_linear_srgb() && capture->compatibility;
gs_texture_t *texture = capture->texture;
const bool compatibility = capture->compatibility;
bool linear_sample = compatibility;
if (!linear_sample && !texcoords_centered) {
gs_texture_t *const extra_texture = capture->extra_texture;
gs_copy_texture(extra_texture, texture);
texture = extra_texture;
linear_sample = true;
}
const bool previous = gs_framebuffer_srgb_enabled();
gs_enable_framebuffer_srgb(linear_srgb);
gs_enable_framebuffer_srgb(linear_sample);
gs_enable_blending(false);
if (linear_srgb)
if (linear_sample)
gs_effect_set_texture_srgb(image, texture);
else
gs_effect_set_texture(image, texture);
passes = gs_technique_begin(tech);
const uint32_t flip = compatibility ? GS_FLIP_V : 0;
const size_t passes = gs_technique_begin(tech);
for (size_t i = 0; i < passes; i++) {
if (gs_technique_begin_pass(tech, i)) {
if (capture->compatibility)
gs_draw_sprite(texture, GS_FLIP_V, 0, 0);
else
gs_draw_sprite(texture, 0, 0, 0);
gs_draw_sprite(texture, flip, 0, 0);
gs_technique_end_pass(tech);
}
}
gs_technique_end(tech);
gs_enable_blending(true);
gs_enable_framebuffer_srgb(previous);
}
void dc_capture_render(struct dc_capture *capture, gs_effect_t *effect)
void dc_capture_render(struct dc_capture *capture, bool texcoords_centered)
{
if (capture->valid && capture->texture_written)
draw_texture(capture, effect);
draw_texture(capture, texcoords_centered);
}