libobs: Add dormant SRGB format support
GS_RGBA, GS_BGRX, and GS_BGRA now use TYPELESS DXGI formats, so we can alias them between UNORM and UNORM_SRGB as necessary. GS_RGBA_UNORM, GS_BGRX_UNORM, and GS_BGRA_UNORM have been added to support straight UNORM types, which Windows requires for sharing textures from D3D9 and OpenGL. The D3D path aliases via views, and GL aliases via GL_EXT_texture_sRGB_decode/GL_FRAMEBUFFER_SRGB. A significant amount of code has changed in the D3D/GL backends, but the concepts are simple. On the D3D side, we need separate SRVs and RTVs to support nonlinear/linear reads and writes. On the GL side, we need to set the proper GL parameters to emulate the same. Add gs_enable_framebuffer_srgb/gs_framebuffer_srgb_enabled to set/get the framebuffer as SRGB or not. Add gs_linear_srgb_active/gs_set_linear_srgb to instruct sources that they should render as SRGB. Legacy sources can ignore this setting without regression. Update obs_source_draw to use linear SRGB as needed. Update render_filter_tex to use linear SRGB as needed. Add gs_effect_set_texture_srgb next to gs_effect_set_texture to set texture with SRGB view instead. Add SRGB helpers for vec4 struct. Create GDI-compatible textures without SRGB support. Doesn't seem to work with SRGB formats.
This commit is contained in:
@@ -525,8 +525,13 @@ static void program_set_param_data(struct gs_program *program,
|
||||
}
|
||||
|
||||
glUniform1i(pp->obj, pp->param->texture_id);
|
||||
device_load_texture(program->device, pp->param->texture,
|
||||
pp->param->texture_id);
|
||||
if (pp->param->srgb)
|
||||
device_load_texture_srgb(program->device,
|
||||
pp->param->texture,
|
||||
pp->param->texture_id);
|
||||
else
|
||||
device_load_texture(program->device, pp->param->texture,
|
||||
pp->param->texture_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,7 +762,7 @@ void gs_shader_set_val(gs_sparam_t *param, const void *val, size_t size)
|
||||
expected_size = sizeof(float) * 4 * 4;
|
||||
break;
|
||||
case GS_SHADER_PARAM_TEXTURE:
|
||||
expected_size = sizeof(void *);
|
||||
expected_size = sizeof(struct gs_shader_texture);
|
||||
break;
|
||||
default:
|
||||
expected_size = 0;
|
||||
@@ -773,10 +778,14 @@ void gs_shader_set_val(gs_sparam_t *param, const void *val, size_t size)
|
||||
return;
|
||||
}
|
||||
|
||||
if (param->type == GS_SHADER_PARAM_TEXTURE)
|
||||
gs_shader_set_texture(param, *(gs_texture_t **)val);
|
||||
else
|
||||
if (param->type == GS_SHADER_PARAM_TEXTURE) {
|
||||
struct gs_shader_texture shader_tex;
|
||||
memcpy(&shader_tex, val, sizeof(shader_tex));
|
||||
gs_shader_set_texture(param, shader_tex.tex);
|
||||
param->srgb = shader_tex.srgb;
|
||||
} else {
|
||||
da_copy_array(param->cur_value, val, size);
|
||||
}
|
||||
}
|
||||
|
||||
void gs_shader_set_default(gs_sparam_t *param)
|
||||
|
@@ -138,6 +138,12 @@ static bool gl_init_extensions(struct gs_device *device)
|
||||
|
||||
gl_enable_debug();
|
||||
|
||||
if (!GLAD_GL_EXT_texture_sRGB_decode) {
|
||||
blog(LOG_ERROR, "OpenGL extension EXT_texture_sRGB_decode "
|
||||
"is required.");
|
||||
return false;
|
||||
}
|
||||
|
||||
gl_enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
|
||||
if (GLAD_GL_VERSION_4_3 || GLAD_GL_ARB_copy_image)
|
||||
@@ -492,7 +498,8 @@ static inline struct gs_shader_param *get_texture_param(gs_device_t *device,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void device_load_texture(gs_device_t *device, gs_texture_t *tex, int unit)
|
||||
static void device_load_texture_internal(gs_device_t *device, gs_texture_t *tex,
|
||||
int unit, GLint decode)
|
||||
{
|
||||
struct gs_shader_param *param;
|
||||
struct gs_sampler_state *sampler;
|
||||
@@ -530,6 +537,10 @@ void device_load_texture(gs_device_t *device, gs_texture_t *tex, int unit)
|
||||
|
||||
if (!gl_bind_texture(tex->gl_target, tex->texture))
|
||||
goto fail;
|
||||
|
||||
if (!gl_tex_param_i(tex->gl_target, GL_TEXTURE_SRGB_DECODE_EXT, decode))
|
||||
goto fail;
|
||||
|
||||
if (sampler && !load_texture_sampler(tex, sampler))
|
||||
goto fail;
|
||||
|
||||
@@ -539,6 +550,16 @@ fail:
|
||||
blog(LOG_ERROR, "device_load_texture (GL) failed");
|
||||
}
|
||||
|
||||
void device_load_texture(gs_device_t *device, gs_texture_t *tex, int unit)
|
||||
{
|
||||
device_load_texture_internal(device, tex, unit, GL_SKIP_DECODE_EXT);
|
||||
}
|
||||
|
||||
void device_load_texture_srgb(gs_device_t *device, gs_texture_t *tex, int unit)
|
||||
{
|
||||
device_load_texture_internal(device, tex, unit, GL_DECODE_EXT);
|
||||
}
|
||||
|
||||
static bool load_sampler_on_textures(gs_device_t *device, gs_samplerstate_t *ss,
|
||||
int sampler_unit)
|
||||
{
|
||||
@@ -863,6 +884,21 @@ fail:
|
||||
blog(LOG_ERROR, "device_set_cube_render_target (GL) failed");
|
||||
}
|
||||
|
||||
void device_enable_framebuffer_srgb(gs_device_t *device, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
gl_enable(GL_FRAMEBUFFER_SRGB);
|
||||
else
|
||||
gl_disable(GL_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
|
||||
bool device_framebuffer_srgb_enabled(gs_device_t *device)
|
||||
{
|
||||
const GLboolean enabled = glIsEnabled(GL_FRAMEBUFFER_SRGB);
|
||||
gl_success("glIsEnabled");
|
||||
return enabled == GL_TRUE;
|
||||
}
|
||||
|
||||
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,
|
||||
|
@@ -71,6 +71,12 @@ static inline GLenum convert_gs_format(enum gs_color_format format)
|
||||
return GL_RGBA;
|
||||
case GS_DXT5:
|
||||
return GL_RGBA;
|
||||
case GS_RGBA_UNORM:
|
||||
return GL_RGBA;
|
||||
case GS_BGRX_UNORM:
|
||||
return GL_BGRA;
|
||||
case GS_BGRA_UNORM:
|
||||
return GL_BGRA;
|
||||
case GS_UNKNOWN:
|
||||
return 0;
|
||||
}
|
||||
@@ -86,11 +92,11 @@ static inline GLenum convert_gs_internal_format(enum gs_color_format format)
|
||||
case GS_R8:
|
||||
return GL_R8;
|
||||
case GS_RGBA:
|
||||
return GL_RGBA;
|
||||
return GL_SRGB8_ALPHA8;
|
||||
case GS_BGRX:
|
||||
return GL_RGB;
|
||||
return GL_SRGB8;
|
||||
case GS_BGRA:
|
||||
return GL_RGBA;
|
||||
return GL_SRGB8_ALPHA8;
|
||||
case GS_R10G10B10A2:
|
||||
return GL_RGB10_A2;
|
||||
case GS_RGBA16:
|
||||
@@ -117,6 +123,12 @@ static inline GLenum convert_gs_internal_format(enum gs_color_format format)
|
||||
return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
case GS_DXT5:
|
||||
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
case GS_RGBA_UNORM:
|
||||
return GL_RGBA;
|
||||
case GS_BGRX_UNORM:
|
||||
return GL_RGB;
|
||||
case GS_BGRA_UNORM:
|
||||
return GL_RGBA;
|
||||
case GS_UNKNOWN:
|
||||
return 0;
|
||||
}
|
||||
@@ -163,6 +175,12 @@ static inline GLenum get_gl_format_type(enum gs_color_format format)
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case GS_DXT5:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case GS_RGBA_UNORM:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case GS_BGRX_UNORM:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case GS_BGRA_UNORM:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case GS_UNKNOWN:
|
||||
return 0;
|
||||
}
|
||||
@@ -411,6 +429,7 @@ struct gs_shader_param {
|
||||
int array_count;
|
||||
|
||||
struct gs_texture *texture;
|
||||
bool srgb;
|
||||
|
||||
DARRAY(uint8_t) cur_value;
|
||||
DARRAY(uint8_t) def_value;
|
||||
|
Reference in New Issue
Block a user