Merge pull request #4950 from jpark37/manual-srgb-filtering

Manual SRGB filtering
This commit is contained in:
Jim 2021-07-11 09:34:45 -07:00 committed by GitHub
commit 4fad39cdc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 367 additions and 133 deletions

View file

@ -847,6 +847,14 @@ General Source Functions
---------------------
.. function:: bool obs_source_get_texcoords_centered(obs_source_t *source)
Hints whether or not the source will blend texels.
:return: Whether or not the source will blend texels
---------------------
.. function:: obs_data_t *obs_source_get_settings(const obs_source_t *source)
:return: The settings string for a source. The reference counter of the

View file

@ -218,9 +218,12 @@ static inline void copy_texture(gs_duplicator_t *d, ID3D11Texture2D *tex)
d->texture->height != desc.Height) {
delete d->texture;
const gs_color_format format =
ConvertDXGITextureFormat(desc.Format);
const gs_color_format srgb_format =
gs_generalize_format(format);
d->texture = (gs_texture_2d *)gs_texture_create(
desc.Width, desc.Height,
ConvertDXGITextureFormat(desc.Format), 1, nullptr, 0);
desc.Width, desc.Height, srgb_format, 1, nullptr, 0);
}
if (!!d->texture)

View file

@ -1768,6 +1768,20 @@ inline void gs_device::CopyTex(ID3D11Texture2D *dst, uint32_t dst_x,
}
}
static DXGI_FORMAT get_copy_compare_format(gs_color_format format)
{
switch (format) {
case GS_RGBA_UNORM:
return DXGI_FORMAT_R8G8B8A8_TYPELESS;
case GS_BGRX_UNORM:
return DXGI_FORMAT_B8G8R8X8_TYPELESS;
case GS_BGRA_UNORM:
return DXGI_FORMAT_B8G8R8A8_TYPELESS;
default:
return ConvertGSTextureFormatResource(format);
}
}
void device_copy_texture_region(gs_device_t *device, gs_texture_t *dst,
uint32_t dst_x, uint32_t dst_y,
gs_texture_t *src, uint32_t src_x,
@ -1784,7 +1798,8 @@ void device_copy_texture_region(gs_device_t *device, gs_texture_t *dst,
if (src->type != GS_TEXTURE_2D || dst->type != GS_TEXTURE_2D)
throw "Source and destination textures must be a 2D "
"textures";
if (dst->format != src->format)
if (get_copy_compare_format(dst->format) !=
get_copy_compare_format(src->format))
throw "Source and destination formats do not match";
/* apparently casting to the same type that the variable

View file

@ -150,7 +150,7 @@ static inline GLenum get_gl_format_type(enum gs_color_format format)
case GS_BGRA:
return GL_UNSIGNED_BYTE;
case GS_R10G10B10A2:
return GL_UNSIGNED_INT_10_10_10_2;
return GL_UNSIGNED_INT_2_10_10_10_REV;
case GS_RGBA16:
return GL_UNSIGNED_SHORT;
case GS_R16:

View file

@ -564,24 +564,20 @@ extern "C" EXPORT void winrt_capture_free(struct winrt_capture *capture)
}
}
static void draw_texture(struct winrt_capture *capture, gs_effect_t *effect)
static void draw_texture(struct winrt_capture *capture)
{
gs_texture_t *const texture = capture->texture;
gs_effect_t *const 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();
const bool previous = gs_framebuffer_srgb_enabled();
gs_enable_framebuffer_srgb(linear_srgb);
gs_enable_framebuffer_srgb(true);
gs_enable_blending(false);
if (linear_srgb)
gs_effect_set_texture_srgb(image, texture);
else
gs_effect_set_texture(image, texture);
gs_texture_t *const texture = capture->texture;
gs_effect_set_texture_srgb(image, texture);
passes = gs_technique_begin(tech);
const size_t passes = gs_technique_begin(tech);
for (size_t i = 0; i < passes; i++) {
if (gs_technique_begin_pass(tech, i)) {
gs_draw_sprite(texture, 0, 0, 0);
@ -591,6 +587,7 @@ static void draw_texture(struct winrt_capture *capture, gs_effect_t *effect)
}
gs_technique_end(tech);
gs_enable_blending(true);
gs_enable_framebuffer_srgb(previous);
}
@ -627,11 +624,10 @@ extern "C" EXPORT BOOL winrt_capture_show_cursor(struct winrt_capture *capture,
return success;
}
extern "C" EXPORT void winrt_capture_render(struct winrt_capture *capture,
gs_effect_t *effect)
extern "C" EXPORT void winrt_capture_render(struct winrt_capture *capture)
{
if (capture->texture_written)
draw_texture(capture, effect);
draw_texture(capture);
}
extern "C" EXPORT uint32_t

View file

@ -20,8 +20,7 @@ EXPORT void winrt_capture_free(struct winrt_capture *capture);
EXPORT BOOL winrt_capture_active(const struct winrt_capture *capture);
EXPORT BOOL winrt_capture_show_cursor(struct winrt_capture *capture,
BOOL visible);
EXPORT void winrt_capture_render(struct winrt_capture *capture,
gs_effect_t *effect);
EXPORT void winrt_capture_render(struct winrt_capture *capture);
EXPORT uint32_t winrt_capture_width(const struct winrt_capture *capture);
EXPORT uint32_t winrt_capture_height(const struct winrt_capture *capture);

View file

@ -62,6 +62,13 @@ float4 PSDrawNonlinearAlpha(VertInOut vert_in) : TARGET
return rgba;
}
float4 PSDrawSrgbDecompress(VertInOut vert_in) : TARGET
{
float4 rgba = image.Sample(def_sampler, vert_in.uv);
rgba.rgb = srgb_nonlinear_to_linear(rgba.rgb);
return rgba;
}
float4 PSDrawSrgbDecompressPremultiplied(VertInOut vert_in) : TARGET
{
float4 rgba = image.Sample(def_sampler, vert_in.uv);
@ -97,6 +104,15 @@ technique DrawNonlinearAlpha
}
}
technique DrawSrgbDecompress
{
pass
{
vertex_shader = VSDefault(vert_in);
pixel_shader = PSDrawSrgbDecompress(vert_in);
}
}
technique DrawSrgbDecompressPremultiplied
{
pass

View file

@ -1005,6 +1005,24 @@ static inline bool gs_is_srgb_format(enum gs_color_format format)
}
}
static inline enum gs_color_format
gs_generalize_format(enum gs_color_format format)
{
switch (format) {
case GS_RGBA_UNORM:
format = GS_RGBA;
break;
case GS_BGRX_UNORM:
format = GS_BGRX;
break;
case GS_BGRA_UNORM:
format = GS_BGRA;
default:;
}
return format;
}
static inline uint32_t gs_get_total_levels(uint32_t width, uint32_t height,
uint32_t depth)
{

View file

@ -630,6 +630,9 @@ struct obs_source {
/* used to temporarily disable sources if needed */
bool enabled;
/* hint to allow sources to render more quickly */
bool texcoords_centered;
/* timing (if video is present, is based upon video) */
volatile bool timing_set;
volatile uint64_t timing_adjust;
@ -847,6 +850,8 @@ convert_video_format(enum video_format format)
}
}
extern void obs_source_set_texcoords_centered(obs_source_t *source,
bool centered);
extern void obs_source_activate(obs_source_t *source, enum view_type type);
extern void obs_source_deactivate(obs_source_t *source, enum view_type type);
extern void obs_source_video_tick(obs_source_t *source, float seconds);

View file

@ -561,6 +561,20 @@ static void render_item_texture(struct obs_scene_item *item)
GS_DEBUG_MARKER_END();
}
static bool are_texcoords_centered(struct matrix4 *m)
{
static const struct matrix4 identity = {
{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, 0.0f, 1.0f},
};
struct matrix4 copy = identity;
copy.t.x = floorf(m->t.x);
copy.t.y = floorf(m->t.y);
return memcmp(m, &copy, sizeof(*m)) == 0;
}
static inline void render_item(struct obs_scene_item *item)
{
GS_DEBUG_MARKER_BEGIN_FORMAT(GS_DEBUG_COLOR_ITEM, "Item: %s",
@ -610,7 +624,11 @@ static inline void render_item(struct obs_scene_item *item)
cx, cy);
obs_source_video_render(item->hide_transition);
} else {
obs_source_set_texcoords_centered(item->source,
true);
obs_source_video_render(item->source);
obs_source_set_texcoords_centered(item->source,
false);
}
gs_texrender_end(item->item_render);
@ -635,7 +653,11 @@ static inline void render_item(struct obs_scene_item *item)
obs_transition_set_size(item->hide_transition, cx, cy);
obs_source_video_render(item->hide_transition);
} else {
const bool centered =
are_texcoords_centered(&item->draw_transform);
obs_source_set_texcoords_centered(item->source, centered);
obs_source_video_render(item->source);
obs_source_set_texcoords_centered(item->source, false);
}
gs_matrix_pop();
gs_set_linear_srgb(previous);

View file

@ -1030,6 +1030,16 @@ void obs_source_send_key_click(obs_source_t *source,
}
}
bool obs_source_get_texcoords_centered(obs_source_t *source)
{
return source->texcoords_centered;
}
void obs_source_set_texcoords_centered(obs_source_t *source, bool centered)
{
source->texcoords_centered = centered;
}
static void activate_source(obs_source_t *source)
{
if (source->context.data && source->info.activate)

View file

@ -962,6 +962,9 @@ EXPORT uint32_t obs_source_get_width(obs_source_t *source);
/** Gets the height of a source (if it has video) */
EXPORT uint32_t obs_source_get_height(obs_source_t *source);
/** Hints whether or not the source will blend texels */
EXPORT bool obs_source_get_texcoords_centered(obs_source_t *source);
/**
* If the source is a filter, returns the parent source of the filter. Only
* guaranteed to be valid inside of the video_render, filter_audio,

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);
}

View file

@ -7,6 +7,7 @@
struct dc_capture {
gs_texture_t *texture;
gs_texture_t *extra_texture;
bool texture_written;
int x, y;
uint32_t width;
@ -31,4 +32,5 @@ extern void dc_capture_init(struct dc_capture *capture, int x, int y,
extern void dc_capture_free(struct dc_capture *capture);
extern void dc_capture_capture(struct dc_capture *capture, HWND window);
extern void dc_capture_render(struct dc_capture *capture, gs_effect_t *effect);
extern void dc_capture_render(struct dc_capture *capture,
bool texcoords_centered);

View file

@ -39,8 +39,7 @@ typedef struct winrt_capture *(*PFN_winrt_capture_init_monitor)(
typedef void (*PFN_winrt_capture_free)(struct winrt_capture *capture);
typedef BOOL (*PFN_winrt_capture_active)(const struct winrt_capture *capture);
typedef void (*PFN_winrt_capture_render)(struct winrt_capture *capture,
gs_effect_t *effect);
typedef void (*PFN_winrt_capture_render)(struct winrt_capture *capture);
typedef uint32_t (*PFN_winrt_capture_width)(const struct winrt_capture *capture);
typedef uint32_t (*PFN_winrt_capture_height)(
const struct winrt_capture *capture);
@ -488,18 +487,18 @@ static void draw_cursor(struct duplicator_capture *capture)
capture->rot % 180 == 0 ? capture->height : capture->width);
}
static void duplicator_capture_render(void *data, gs_effect_t *effect)
static void duplicator_capture_render(void *data, gs_effect_t *unused)
{
UNUSED_PARAMETER(unused);
struct duplicator_capture *capture = data;
if (capture->method == METHOD_WGC) {
gs_effect_t *const opaque =
obs_get_base_effect(OBS_EFFECT_OPAQUE);
if (capture->capture_winrt) {
if (capture->exports.winrt_capture_active(
capture->capture_winrt)) {
capture->exports.winrt_capture_render(
capture->capture_winrt, opaque);
capture->capture_winrt);
} else {
capture->exports.winrt_capture_free(
capture->capture_winrt);
@ -507,54 +506,62 @@ static void duplicator_capture_render(void *data, gs_effect_t *effect)
}
}
} else {
gs_texture_t *texture;
int rot;
if (!capture->duplicator)
return;
texture = gs_duplicator_get_texture(capture->duplicator);
gs_texture_t *const texture =
gs_duplicator_get_texture(capture->duplicator);
if (!texture)
return;
effect = obs_get_base_effect(OBS_EFFECT_OPAQUE);
const bool previous = gs_framebuffer_srgb_enabled();
gs_enable_framebuffer_srgb(true);
gs_enable_blending(false);
rot = capture->rot;
const int rot = capture->rot;
if (rot != 0) {
float x = 0.0f;
float y = 0.0f;
while (gs_effect_loop(effect, "Draw")) {
if (rot != 0) {
float x = 0.0f;
float y = 0.0f;
switch (rot) {
case 90:
x = (float)capture->height;
break;
case 180:
x = (float)capture->width;
y = (float)capture->height;
break;
case 270:
y = (float)capture->width;
break;
}
gs_matrix_push();
gs_matrix_translate3f(x, y, 0.0f);
gs_matrix_rotaa4f(0.0f, 0.0f, 1.0f,
RAD((float)rot));
switch (rot) {
case 90:
x = (float)capture->height;
break;
case 180:
x = (float)capture->width;
y = (float)capture->height;
break;
case 270:
y = (float)capture->width;
break;
}
obs_source_draw(texture, 0, 0, 0, 0, false);
if (rot != 0)
gs_matrix_pop();
gs_matrix_push();
gs_matrix_translate3f(x, y, 0.0f);
gs_matrix_rotaa4f(0.0f, 0.0f, 1.0f, RAD((float)rot));
}
if (capture->capture_cursor) {
effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
gs_effect_t *const opaque_effect =
obs_get_base_effect(OBS_EFFECT_OPAQUE);
while (gs_effect_loop(opaque_effect, "Draw")) {
gs_eparam_t *image = gs_effect_get_param_by_name(
opaque_effect, "image");
gs_effect_set_texture_srgb(image, texture);
while (gs_effect_loop(effect, "Draw")) {
gs_draw_sprite(texture, 0, 0, 0);
}
if (rot != 0)
gs_matrix_pop();
gs_enable_blending(true);
gs_enable_framebuffer_srgb(previous);
if (capture->capture_cursor) {
gs_effect_t *const default_effect =
obs_get_base_effect(OBS_EFFECT_DEFAULT);
while (gs_effect_loop(default_effect, "Draw")) {
draw_cursor(capture);
}
}
@ -670,7 +677,7 @@ struct obs_source_info duplicator_capture_info = {
.id = "monitor_capture",
.type = OBS_SOURCE_TYPE_INPUT,
.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW |
OBS_SOURCE_DO_NOT_DUPLICATE,
OBS_SOURCE_DO_NOT_DUPLICATE | OBS_SOURCE_SRGB,
.get_name = duplicator_capture_getname,
.create = duplicator_capture_create,
.destroy = duplicator_capture_destroy,

View file

@ -149,7 +149,9 @@ struct game_capture {
ipc_pipe_server_t pipe;
gs_texture_t *texture;
bool supports_srgb;
gs_texture_t *extra_texture;
gs_texrender_t *extra_texrender;
bool linear_sample;
struct hook_info *global_hook_info;
HANDLE keepalive_mutex;
HANDLE hook_init;
@ -332,12 +334,14 @@ static void stop_capture(struct game_capture *gc)
close_handle(&gc->texture_mutexes[0]);
close_handle(&gc->texture_mutexes[1]);
if (gc->texture) {
obs_enter_graphics();
gs_texture_destroy(gc->texture);
obs_leave_graphics();
gc->texture = NULL;
}
obs_enter_graphics();
gs_texrender_destroy(gc->extra_texrender);
gs_texture_destroy(gc->extra_texture);
gs_texture_destroy(gc->texture);
obs_leave_graphics();
gc->extra_texrender = NULL;
gc->extra_texture = NULL;
gc->texture = NULL;
if (gc->active)
info("capture stopped");
@ -1552,49 +1556,104 @@ static inline bool is_16bit_format(uint32_t format)
static inline bool init_shmem_capture(struct game_capture *gc)
{
enum gs_color_format format;
gc->texture_buffers[0] =
(uint8_t *)gc->data + gc->shmem_data->tex1_offset;
gc->texture_buffers[1] =
(uint8_t *)gc->data + gc->shmem_data->tex2_offset;
gc->convert_16bit = is_16bit_format(gc->global_hook_info->format);
format = gc->convert_16bit
? GS_BGRA
: convert_format(gc->global_hook_info->format);
const uint32_t dxgi_format = gc->global_hook_info->format;
const bool convert_16bit = is_16bit_format(dxgi_format);
const enum gs_color_format format =
convert_16bit ? GS_BGRA : convert_format(dxgi_format);
obs_enter_graphics();
gs_texrender_destroy(gc->extra_texrender);
gs_texture_destroy(gc->extra_texture);
gs_texture_destroy(gc->texture);
gc->texture =
gs_texture_t *const texture =
gs_texture_create(gc->cx, gc->cy, format, 1, NULL, GS_DYNAMIC);
obs_leave_graphics();
if (!gc->texture) {
bool success = texture != NULL;
if (success) {
const bool linear_sample = format != GS_R10G10B10A2;
gs_texrender_t *extra_texrender = NULL;
if (!linear_sample) {
extra_texrender =
gs_texrender_create(GS_BGRA, GS_ZS_NONE);
success = extra_texrender != NULL;
if (!success)
warn("init_shmem_capture: failed to create extra texrender");
}
if (success) {
gc->texture_buffers[0] = (uint8_t *)gc->data +
gc->shmem_data->tex1_offset;
gc->texture_buffers[1] = (uint8_t *)gc->data +
gc->shmem_data->tex2_offset;
gc->convert_16bit = convert_16bit;
gc->texture = texture;
gc->extra_texture = NULL;
gc->extra_texrender = extra_texrender;
gc->linear_sample = linear_sample;
gc->copy_texture = copy_shmem_tex;
} else {
gs_texture_destroy(texture);
}
} else {
warn("init_shmem_capture: failed to create texture");
return false;
}
gc->supports_srgb = true;
gc->copy_texture = copy_shmem_tex;
return true;
return success;
}
static inline bool init_shtex_capture(struct game_capture *gc)
{
obs_enter_graphics();
gs_texrender_destroy(gc->extra_texrender);
gs_texture_destroy(gc->extra_texture);
gs_texture_destroy(gc->texture);
gc->texture = gs_texture_open_shared(gc->shtex_data->tex_handle);
enum gs_color_format format = gs_texture_get_color_format(gc->texture);
gc->supports_srgb = gs_is_srgb_format(format);
gs_texture_t *const texture =
gs_texture_open_shared(gc->shtex_data->tex_handle);
bool success = texture != NULL;
if (success) {
enum gs_color_format format =
gs_texture_get_color_format(texture);
const bool ten_bit_srgb = (format == GS_R10G10B10A2);
enum gs_color_format linear_format =
ten_bit_srgb ? GS_BGRA : gs_generalize_format(format);
const bool linear_sample = (linear_format == format);
gs_texture_t *extra_texture = NULL;
gs_texrender_t *extra_texrender = NULL;
if (!linear_sample) {
if (ten_bit_srgb) {
extra_texrender = gs_texrender_create(
linear_format, GS_ZS_NONE);
success = extra_texrender != NULL;
if (!success)
warn("init_shtex_capture: failed to create extra texrender");
} else {
extra_texture = gs_texture_create(
gs_texture_get_width(texture),
gs_texture_get_height(texture),
linear_format, 1, NULL, 0);
success = extra_texture != NULL;
if (!success)
warn("init_shtex_capture: failed to create extra texture");
}
}
if (success) {
gc->texture = texture;
gc->linear_sample = linear_sample;
gc->extra_texture = extra_texture;
gc->extra_texrender = extra_texrender;
} else {
gs_texture_destroy(texture);
}
} else {
warn("init_shtex_capture: failed to open shared handle");
}
obs_leave_graphics();
if (!gc->texture) {
warn("init_shtex_capture: failed to open shared handle");
return false;
}
return true;
return success;
}
static bool start_capture(struct game_capture *gc)
@ -1802,36 +1861,86 @@ static inline void game_capture_render_cursor(struct game_capture *gc)
gc->global_hook_info->cy);
}
static void game_capture_render(void *data, gs_effect_t *effect)
static void game_capture_render(void *data, gs_effect_t *unused)
{
UNUSED_PARAMETER(unused);
struct game_capture *gc = data;
if (!gc->texture || !gc->active)
return;
effect = obs_get_base_effect(gc->config.allow_transparency
? OBS_EFFECT_DEFAULT
: OBS_EFFECT_OPAQUE);
const bool allow_transparency = gc->config.allow_transparency;
gs_effect_t *const effect = obs_get_base_effect(
allow_transparency ? OBS_EFFECT_DEFAULT : OBS_EFFECT_OPAQUE);
const bool linear_srgb = gs_get_linear_srgb() && gc->supports_srgb;
const bool previous = gs_set_linear_srgb(linear_srgb);
bool linear_sample = gc->linear_sample;
gs_texture_t *texture = gc->texture;
if (!linear_sample && !obs_source_get_texcoords_centered(gc->source)) {
gs_texture_t *const extra_texture = gc->extra_texture;
if (extra_texture) {
gs_copy_texture(extra_texture, texture);
texture = extra_texture;
} else {
gs_texrender_t *const texrender = gc->extra_texrender;
gs_texrender_reset(texrender);
const uint32_t cx = gs_texture_get_width(texture);
const uint32_t cy = gs_texture_get_height(texture);
if (gs_texrender_begin(texrender, cx, cy)) {
gs_effect_t *const default_effect =
obs_get_base_effect(OBS_EFFECT_DEFAULT);
const bool previous =
gs_framebuffer_srgb_enabled();
gs_enable_framebuffer_srgb(false);
gs_enable_blending(false);
gs_ortho(0.0f, (float)cx, 0.0f, (float)cy,
-100.0f, 100.0f);
gs_eparam_t *const image =
gs_effect_get_param_by_name(
default_effect, "image");
gs_effect_set_texture(image, texture);
while (gs_effect_loop(default_effect, "Draw")) {
gs_draw_sprite(texture, 0, 0, 0);
}
gs_enable_blending(true);
gs_enable_framebuffer_srgb(previous);
while (gs_effect_loop(effect, "Draw")) {
obs_source_draw(gc->texture, 0, 0, 0, 0,
gc->global_hook_info->flip);
gs_texrender_end(texrender);
if (gc->config.allow_transparency && gc->config.cursor &&
texture = gs_texrender_get_texture(texrender);
}
}
linear_sample = true;
}
gs_eparam_t *const image = gs_effect_get_param_by_name(effect, "image");
const uint32_t flip = gc->global_hook_info->flip ? GS_FLIP_V : 0;
const char *tech_name = allow_transparency && !linear_sample
? "DrawSrgbDecompress"
: "Draw";
while (gs_effect_loop(effect, tech_name)) {
const bool previous = gs_framebuffer_srgb_enabled();
gs_enable_framebuffer_srgb(allow_transparency || linear_sample);
gs_enable_blending(allow_transparency);
if (linear_sample)
gs_effect_set_texture_srgb(image, texture);
else
gs_effect_set_texture(image, texture);
gs_draw_sprite(texture, flip, 0, 0);
gs_enable_blending(true);
gs_enable_framebuffer_srgb(previous);
if (allow_transparency && gc->config.cursor &&
!gc->cursor_hidden) {
game_capture_render_cursor(gc);
}
}
gs_set_linear_srgb(previous);
if (!allow_transparency && gc->config.cursor && !gc->cursor_hidden) {
gs_effect_t *const default_effect =
obs_get_base_effect(OBS_EFFECT_DEFAULT);
if (!gc->config.allow_transparency && gc->config.cursor &&
!gc->cursor_hidden) {
effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
while (gs_effect_loop(effect, "Draw")) {
while (gs_effect_loop(default_effect, "Draw")) {
game_capture_render_cursor(gc);
}
}

View file

@ -152,7 +152,7 @@ static void monitor_capture_render(void *data, gs_effect_t *effect)
{
struct monitor_capture *capture = data;
dc_capture_render(&capture->data,
obs_get_base_effect(OBS_EFFECT_OPAQUE));
obs_source_get_texcoords_centered(capture->source));
UNUSED_PARAMETER(effect);
}

View file

@ -37,8 +37,7 @@ typedef void (*PFN_winrt_capture_free)(struct winrt_capture *capture);
typedef BOOL (*PFN_winrt_capture_active)(const struct winrt_capture *capture);
typedef BOOL (*PFN_winrt_capture_show_cursor)(struct winrt_capture *capture,
BOOL visible);
typedef void (*PFN_winrt_capture_render)(struct winrt_capture *capture,
gs_effect_t *effect);
typedef void (*PFN_winrt_capture_render)(struct winrt_capture *capture);
typedef uint32_t (*PFN_winrt_capture_width)(const struct winrt_capture *capture);
typedef uint32_t (*PFN_winrt_capture_height)(
const struct winrt_capture *capture);
@ -574,13 +573,12 @@ static void wc_tick(void *data, float seconds)
static void wc_render(void *data, gs_effect_t *effect)
{
struct window_capture *wc = data;
gs_effect_t *const opaque = obs_get_base_effect(OBS_EFFECT_OPAQUE);
if (wc->method == METHOD_WGC) {
if (wc->capture_winrt) {
if (wc->exports.winrt_capture_active(
wc->capture_winrt)) {
wc->exports.winrt_capture_render(
wc->capture_winrt, opaque);
wc->capture_winrt);
} else {
wc->exports.winrt_capture_free(
wc->capture_winrt);
@ -588,7 +586,9 @@ static void wc_render(void *data, gs_effect_t *effect)
}
}
} else {
dc_capture_render(&wc->capture, opaque);
dc_capture_render(
&wc->capture,
obs_source_get_texcoords_centered(wc->source));
}
UNUSED_PARAMETER(effect);