Merge pull request #2989 from webghost009/bicubic_opengl

GLSL Bilinear Filter Fixes and Add Bicubic Filter
This commit is contained in:
R. Belmont 2018-01-02 08:08:06 -05:00 committed by GitHub
commit 2a49d6dd44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 217 additions and 45 deletions

View File

@ -100,7 +100,7 @@ const options_entry osd_options::s_option_entries[] =
{ OSDOPTION_GL_VBO, "1", OPTION_BOOLEAN, "enable OpenGL VBO, if available (default on)" },
{ OSDOPTION_GL_PBO, "1", OPTION_BOOLEAN, "enable OpenGL PBO, if available (default on)" },
{ OSDOPTION_GL_GLSL, "0", OPTION_BOOLEAN, "enable OpenGL GLSL, if available (default off)" },
{ OSDOPTION_GLSL_FILTER, "1", OPTION_STRING, "enable OpenGL GLSL filtering instead of FF filtering 0-plain, 1-bilinear (default)" },
{ OSDOPTION_GLSL_FILTER, "1", OPTION_STRING, "enable OpenGL GLSL filtering instead of FF filtering 0-plain, 1-bilinear (default), 2-bicubic" },
{ OSDOPTION_SHADER_MAME "0", OSDOPTVAL_NONE, OPTION_STRING, "custom OpenGL GLSL shader set mame bitmap 0" },
{ OSDOPTION_SHADER_MAME "1", OSDOPTVAL_NONE, OPTION_STRING, "custom OpenGL GLSL shader set mame bitmap 1" },
{ OSDOPTION_SHADER_MAME "2", OSDOPTVAL_NONE, OPTION_STRING, "custom OpenGL GLSL shader set mame bitmap 2" },

View File

@ -144,7 +144,7 @@ public:
bool gl_vbo() const { return bool_value(OSDOPTION_GL_VBO); }
bool gl_pbo() const { return bool_value(OSDOPTION_GL_PBO); }
bool gl_glsl() const { return bool_value(OSDOPTION_GL_GLSL); }
bool glsl_filter() const { return bool_value(OSDOPTION_GLSL_FILTER); }
int glsl_filter() const { return int_value(OSDOPTION_GLSL_FILTER); }
const char *shader_mame(int index) const { return value(string_format("%s%d", OSDOPTION_SHADER_MAME, index).c_str()); }
const char *shader_screen(int index) const { return value(string_format("%s%d", OSDOPTION_SHADER_SCREEN, index).c_str()); }

View File

@ -23,7 +23,8 @@ static const char * glsl_mamebm_vsh_files [GLSL_VERTEX_SHADER_INT_NUMBER] =
static const char * glsl_mamebm_fsh_files [GLSL_SHADER_FEAT_INT_NUMBER] =
{
"/tmp/glsl_plain_rgb32_dir.fsh", // rgb32 dir plain
"/tmp/glsl_bilinear_rgb32_dir.fsh" // rgb32 dir bilinear
"/tmp/glsl_bilinear_rgb32_dir.fsh", // rgb32 dir bilinear
"/tmp/glsl_bicubic_rgb32_dir.fsh", // rgb32 dir bicubic
};
#else // GLSL_SOURCE_ON_DISK
@ -32,6 +33,7 @@ static const char * glsl_mamebm_fsh_files [GLSL_SHADER_FEAT_INT_NUMBER] =
#include "shader/glsl_plain_rgb32_dir.fsh.c"
#include "shader/glsl_bilinear_rgb32_dir.fsh.c"
#include "shader/glsl_bicubic_rgb32_dir.fsh.c"
static const char * glsl_mamebm_vsh_sources [GLSL_VERTEX_SHADER_INT_NUMBER] =
{
@ -40,8 +42,9 @@ static const char * glsl_mamebm_vsh_sources [GLSL_VERTEX_SHADER_INT_NUMBER] =
static const char * glsl_mamebm_fsh_sources [GLSL_SHADER_FEAT_INT_NUMBER] =
{
glsl_plain_rgb32_dir_fsh_src, // rgb32 dir plain
glsl_bilinear_rgb32_dir_fsh_src // rgb32 dir bilinear
glsl_plain_rgb32_dir_fsh_src, // rgb32 dir plain
glsl_bilinear_rgb32_dir_fsh_src, // rgb32 dir bilinear
glsl_bicubic_rgb32_dir_fsh_src, // rgb32 dir bicubic
};
#endif // GLSL_SOURCE_ON_DISK
@ -50,12 +53,13 @@ static const char * glsl_mamebm_filter_names [GLSL_SHADER_FEAT_MAX_NUMBER] =
{
"plain",
"bilinear",
"bicubic",
"custom"
};
static GLhandleARB glsl_mamebm_programs [GLSL_SHADER_FEAT_MAX_NUMBER+9] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, custom0-9, .. */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, bicubic, custom0-9, .. */
};
/**
@ -65,6 +69,7 @@ static int glsl_mamebm_fsh2vsh[GLSL_SHADER_FEAT_MAX_NUMBER] =
{
0, // plain -> general
0, // bilinear -> general
0, // bicubic -> general
1, // custom -> custom
};
@ -75,7 +80,7 @@ static GLhandleARB glsl_mamebm_vsh_shader[GLSL_VERTEX_SHADER_MAX_NUMBER+9] =
static GLhandleARB glsl_mamebm_fsh_shader [GLSL_SHADER_FEAT_MAX_NUMBER+9] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, custom0-9 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* rgb32 dir: plain, bilinear, bicubic, custom0-9 */
};
static GLhandleARB glsl_scrn_programs [10] =
@ -145,7 +150,7 @@ glsl_shader_info *glsl_shader_init(osd_gl_context *gl_ctx)
if(glsl_mamebm_fsh_files[j])
err = gl_compile_shader_files (&glsl_mamebm_programs[j],
&glsl_mamebm_vsh_shader[glsl_mamebm_fsh2vsh[j]],
&glsl_mamebmfsh_shader[j],
&glsl_mamebm_fsh_shader[j],
nullptr /*precompiled*/, glsl_mamebm_fsh_files[j], 0);
#else
if(glsl_mamebm_fsh_sources[j])

View File

@ -11,6 +11,7 @@
enum GLSL_SHADER_FEATURE {
GLSL_SHADER_FEAT_PLAIN,
GLSL_SHADER_FEAT_BILINEAR,
GLSL_SHADER_FEAT_BICUBIC,
GLSL_SHADER_FEAT_INT_NUMBER,
GLSL_SHADER_FEAT_CUSTOM = GLSL_SHADER_FEAT_INT_NUMBER,
GLSL_SHADER_FEAT_MAX_NUMBER

4
src/osd/modules/opengl/shader/genc.sh Normal file → Executable file
View File

@ -44,3 +44,7 @@ echo "const char glsl_bilinear_rgb32_dir_fsh_src[] =" > glsl_bilinear_rgb32_dir.
sed -e 's/^/"/g' -e 's/$/\\n"/g' glsl_bilinear_rgb32_dir.fsh >> glsl_bilinear_rgb32_dir.fsh.c
echo ";" >> glsl_bilinear_rgb32_dir.fsh.c
echo "const char glsl_bicubic_rgb32_dir_fsh_src[] =" > glsl_bicubic_rgb32_dir.fsh.c
sed -e 's/^/"/g' -e 's/$/\\n"/g' glsl_bicubic_rgb32_dir.fsh >> glsl_bicubic_rgb32_dir.fsh.c
echo ";" >> glsl_bicubic_rgb32_dir.fsh.c

View File

@ -0,0 +1,81 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Stover
#pragma optimize (on)
#pragma debug (off)
uniform sampler2D color_texture;
uniform vec2 color_texture_pow2_sz; // pow2 tex size
uniform vec4 vid_attributes; // gamma, contrast, brightness
#define TEX2D(v) texture2D(color_texture,(v))
void main()
{
vec2 pixel = gl_TexCoord[0].st * color_texture_pow2_sz - 0.5;
vec2 uv_ratio = fract(pixel);
vec2 one = 1.0 / color_texture_pow2_sz;
vec2 xy = (floor(pixel) + 0.5) * one;
//
// Robert G. Keys'
//
// 'Cubic Convolution Interpolation for Digital Image Processing'
// IEEE TRANSACTIONS ON ACOUSTICS, SPEECH, AND SIGNAL PROCESSING,
// VOL. ASSP-29, NO. 6, DECEMBER 1981
//
// gives the following equation:
//
// g(x) = c_k-1(-s^3 + 2s^2 - s)/2
// + c_k(3s^3 - 5s^2 + 2)/2
// + c_k+1(-3s^3 + 4s^2 + s)/2
// + c_k+2(s^3 - s^2)/2
//
// c_* are the sample values, s is our uv_ratio.
//
// Weight equations are taken from above.
//
vec2 s = uv_ratio;
vec2 s2 = uv_ratio*uv_ratio;
vec2 s3 = uv_ratio*uv_ratio*uv_ratio;
vec2 w0 = 0.5 * (-s3 + 2.0*s2 - s);
vec2 w1 = 0.5 * (3.0*s3 - 5.0*s2 + 2.0);
vec2 w2 = 0.5 * (-3.0*s3 + 4.0*s2 + s);
vec2 w3 = 0.5 * (s3 - s2);
// Compute the coordinates to sample from
vec2 pos0 = xy - 1.0*one.xy;
vec2 pos1 = xy;
vec2 pos2 = xy + 1.0*one.xy;
vec2 pos3 = xy + 2.0*one.xy;
// Finally - take the samples, multiply by weight, and sum
vec4 col = vec4(0.0);
col += TEX2D(vec2(pos0.x, pos0.y)) * w0.x * w0.y;
col += TEX2D(vec2(pos1.x, pos0.y)) * w1.x * w0.y;
col += TEX2D(vec2(pos2.x, pos0.y)) * w2.x * w0.y;
col += TEX2D(vec2(pos3.x, pos0.y)) * w3.x * w0.y;
col += TEX2D(vec2(pos0.x, pos1.y)) * w0.x * w1.y;
col += TEX2D(vec2(pos1.x, pos1.y)) * w1.x * w1.y;
col += TEX2D(vec2(pos2.x, pos1.y)) * w2.x * w1.y;
col += TEX2D(vec2(pos3.x, pos1.y)) * w3.x * w1.y;
col += TEX2D(vec2(pos0.x, pos2.y)) * w0.x * w2.y;
col += TEX2D(vec2(pos1.x, pos2.y)) * w1.x * w2.y;
col += TEX2D(vec2(pos2.x, pos2.y)) * w2.x * w2.y;
col += TEX2D(vec2(pos3.x, pos2.y)) * w3.x * w2.y;
col += TEX2D(vec2(pos0.x, pos3.y)) * w0.x * w3.y;
col += TEX2D(vec2(pos1.x, pos3.y)) * w1.x * w3.y;
col += TEX2D(vec2(pos2.x, pos3.y)) * w2.x * w3.y;
col += TEX2D(vec2(pos3.x, pos3.y)) * w3.x * w3.y;
#ifdef DO_GAMMA
// gamma/contrast/brightness
vec4 gamma = vec4(1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 0.0);
gl_FragColor = ( pow ( col, gamma ) * vid_attributes.g) + vid_attributes.b - 1.0;
#else
// contrast/brightness
gl_FragColor = ( col * vid_attributes.g) + vid_attributes.b - 1.0;
#endif
}

View File

@ -0,0 +1,82 @@
const char glsl_bicubic_rgb32_dir_fsh_src[] =
"// license:BSD-3-Clause\n"
"// copyright-holders:Aaron Stover\n"
"#pragma optimize (on)\n"
"#pragma debug (off)\n"
"\n"
"uniform sampler2D color_texture;\n"
"uniform vec2 color_texture_pow2_sz; // pow2 tex size\n"
"uniform vec4 vid_attributes; // gamma, contrast, brightness\n"
"\n"
"#define TEX2D(v) texture2D(color_texture,(v))\n"
"\n"
"void main()\n"
"{\n"
" vec2 pixel = gl_TexCoord[0].st * color_texture_pow2_sz - 0.5;\n"
" vec2 uv_ratio = fract(pixel);\n"
" vec2 one = 1.0 / color_texture_pow2_sz;\n"
" vec2 xy = (floor(pixel) + 0.5) * one;\n"
"\n"
" //\n"
" // Robert G. Keys'\n"
" //\n"
" // 'Cubic Convolution Interpolation for Digital Image Processing'\n"
" // IEEE TRANSACTIONS ON ACOUSTICS, SPEECH, AND SIGNAL PROCESSING, \n"
" // VOL. ASSP-29, NO. 6, DECEMBER 1981 \n"
" //\n"
" // gives the following equation:\n"
" //\n"
" // g(x) = c_k-1(-s^3 + 2s^2 - s)/2 \n"
" // + c_k(3s^3 - 5s^2 + 2)/2\n"
" // + c_k+1(-3s^3 + 4s^2 + s)/2 \n"
" // + c_k+2(s^3 - s^2)/2\n"
" //\n"
" // c_* are the sample values, s is our uv_ratio. \n"
" //\n"
" // Weight equations are taken from above.\n"
" //\n"
" vec2 s = uv_ratio;\n"
" vec2 s2 = uv_ratio*uv_ratio;\n"
" vec2 s3 = uv_ratio*uv_ratio*uv_ratio;\n"
" vec2 w0 = 0.5 * (-s3 + 2.0*s2 - s);\n"
" vec2 w1 = 0.5 * (3.0*s3 - 5.0*s2 + 2.0);\n"
" vec2 w2 = 0.5 * (-3.0*s3 + 4.0*s2 + s);\n"
" vec2 w3 = 0.5 * (s3 - s2);\n"
"\n"
" // Compute the coordinates to sample from\n"
" vec2 pos0 = xy - 1.0*one.xy;\n"
" vec2 pos1 = xy;\n"
" vec2 pos2 = xy + 1.0*one.xy;\n"
" vec2 pos3 = xy + 2.0*one.xy;\n"
"\n"
" // Finally - take the samples, multiply by weight, and sum\n"
" vec4 col = vec4(0.0);\n"
" col += TEX2D(vec2(pos0.x, pos0.y)) * w0.x * w0.y;\n"
" col += TEX2D(vec2(pos1.x, pos0.y)) * w1.x * w0.y;\n"
" col += TEX2D(vec2(pos2.x, pos0.y)) * w2.x * w0.y;\n"
" col += TEX2D(vec2(pos3.x, pos0.y)) * w3.x * w0.y;\n"
"\n"
" col += TEX2D(vec2(pos0.x, pos1.y)) * w0.x * w1.y;\n"
" col += TEX2D(vec2(pos1.x, pos1.y)) * w1.x * w1.y;\n"
" col += TEX2D(vec2(pos2.x, pos1.y)) * w2.x * w1.y;\n"
" col += TEX2D(vec2(pos3.x, pos1.y)) * w3.x * w1.y;\n"
" \n"
" col += TEX2D(vec2(pos0.x, pos2.y)) * w0.x * w2.y;\n"
" col += TEX2D(vec2(pos1.x, pos2.y)) * w1.x * w2.y;\n"
" col += TEX2D(vec2(pos2.x, pos2.y)) * w2.x * w2.y;\n"
" col += TEX2D(vec2(pos3.x, pos2.y)) * w3.x * w2.y;\n"
"\n"
" col += TEX2D(vec2(pos0.x, pos3.y)) * w0.x * w3.y;\n"
" col += TEX2D(vec2(pos1.x, pos3.y)) * w1.x * w3.y;\n"
" col += TEX2D(vec2(pos2.x, pos3.y)) * w2.x * w3.y;\n"
" col += TEX2D(vec2(pos3.x, pos3.y)) * w3.x * w3.y;\n"
"\n"
"#ifdef DO_GAMMA\n"
" // gamma/contrast/brightness\n"
" vec4 gamma = vec4(1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 0.0);\n"
" gl_FragColor = ( pow ( col, gamma ) * vid_attributes.g) + vid_attributes.b - 1.0;\n"
"#else\n"
" // contrast/brightness\n"
" gl_FragColor = ( col * vid_attributes.g) + vid_attributes.b - 1.0;\n"
"#endif\n"
"}\n";

View File

@ -13,8 +13,6 @@ uniform vec4 vid_attributes; // gamma, contrast, brightness
void main()
{
vec2 xy = gl_TexCoord[0].st;
// mix(x,y,a): x*(1-a) + y*a
//
// bilinear filtering includes 2 mix:
@ -25,9 +23,11 @@ void main()
//
// so we can use the build in mix function for these 2 computations ;-)
//
vec2 uv_ratio = fract(xy*color_texture_pow2_sz); // xy*color_texture_pow2_sz - floor(xy*color_texture_pow2_sz);
vec2 one = 1.0/color_texture_pow2_sz;
vec2 pixel = gl_TexCoord[0].st * color_texture_pow2_sz - 0.5;
vec2 uv_ratio = fract(pixel);
vec2 one = 1.0 / color_texture_pow2_sz;
vec2 xy = (floor(pixel) + 0.5) * one;
#if 1
vec4 col, col2;

View File

@ -1,7 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sven Gothel
const char glsl_bilinear_rgb32_dir_fsh_src[] =
"\n"
"// license:BSD-3-Clause\n"
"// copyright-holders:Sven Gothel\n"
"#pragma optimize (on)\n"
"#pragma debug (off)\n"
"\n"
@ -15,43 +14,43 @@ const char glsl_bilinear_rgb32_dir_fsh_src[] =
"\n"
"void main()\n"
"{\n"
" vec2 xy = gl_TexCoord[0].st;\n"
"\n"
" // mix(x,y,a): x*(1-a) + y*a\n"
" //\n"
" // bilinear filtering includes 2 mix:\n"
" //\n"
" // pix1 = tex[x0][y0] * ( 1 - u_ratio ) + tex[x1][y0] * u_ratio\n"
" // pix2 = tex[x0][y1] * ( 1 - u_ratio ) + tex[x1][y1] * u_ratio\n"
" // fin = pix1 * ( 1 - v_ratio ) + pix2 * v_ratio\n"
" //\n"
" // so we can use the build in mix function for these 2 computations ;-)\n"
" //\n"
" vec2 uv_ratio = fract(xy*color_texture_pow2_sz); // xy*color_texture_pow2_sz - floor(xy*color_texture_pow2_sz);\n"
" vec2 one = 1.0/color_texture_pow2_sz;\n"
"\n"
" // mix(x,y,a): x*(1-a) + y*a\n"
" //\n"
" // bilinear filtering includes 2 mix:\n"
" //\n"
" // pix1 = tex[x0][y0] * ( 1 - u_ratio ) + tex[x1][y0] * u_ratio\n"
" // pix2 = tex[x0][y1] * ( 1 - u_ratio ) + tex[x1][y1] * u_ratio\n"
" // fin = pix1 * ( 1 - v_ratio ) + pix2 * v_ratio\n"
" //\n"
" // so we can use the build in mix function for these 2 computations ;-)\n"
" //\n"
" vec2 pixel = gl_TexCoord[0].st * color_texture_pow2_sz - 0.5;\n"
" vec2 uv_ratio = fract(pixel);\n"
" vec2 one = 1.0 / color_texture_pow2_sz;\n"
" vec2 xy = (floor(pixel) + 0.5) * one;\n"
" \n"
"#if 1\n"
" vec4 col, col2;\n"
" vec4 col, col2;\n"
"\n"
" col = mix( TEX2D(xy ), TEX2D(xy + vec2(one.x, 0.0)), uv_ratio.x);\n"
" col2 = mix( TEX2D(xy + vec2(0.0, one.y)), TEX2D(xy + one ), uv_ratio.x);\n"
" col = mix ( col, col2, uv_ratio.y );\n"
" col = mix( TEX2D(xy ), TEX2D(xy + vec2(one.x, 0.0)), uv_ratio.x);\n"
" col2 = mix( TEX2D(xy + vec2(0.0, one.y)), TEX2D(xy + one ), uv_ratio.x);\n"
" col = mix ( col, col2, uv_ratio.y );\n"
"#else\n"
" // doesn't work on MacOSX GLSL engine ..\n"
" //\n"
" vec4 col = mix ( mix( TEX2D(xy ), TEX2D(xy + vec2(one.x, 0.0)), uv_ratio.x),\n"
" mix( TEX2D(xy + vec2(0.0, one.y)), TEX2D(xy + one ), uv_ratio.x), uv_ratio.y );\n"
" // doesn't work on MacOSX GLSL engine ..\n"
" //\n"
" vec4 col = mix ( mix( TEX2D(xy ), TEX2D(xy + vec2(one.x, 0.0)), uv_ratio.x),\n"
" mix( TEX2D(xy + vec2(0.0, one.y)), TEX2D(xy + one ), uv_ratio.x), uv_ratio.y );\n"
"#endif\n"
"\n"
" // gamma, contrast, brightness equation from: rendutil.h / apply_brightness_contrast_gamma_fp\n"
" // gamma, contrast, brightness equation from: rendutil.h / apply_brightness_contrast_gamma_fp\n"
"\n"
"#ifdef DO_GAMMA\n"
" // gamma/contrast/brightness\n"
" vec4 gamma = vec4(1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 0.0);\n"
" gl_FragColor = ( pow ( col, gamma ) * vid_attributes.g) + vid_attributes.b - 1.0;\n"
" // gamma/contrast/brightness\n"
" vec4 gamma = vec4(1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 1.0 / vid_attributes.r, 0.0);\n"
" gl_FragColor = ( pow ( col, gamma ) * vid_attributes.g) + vid_attributes.b - 1.0;\n"
"#else\n"
" // contrast/brightness\n"
" gl_FragColor = ( col * vid_attributes.g) + vid_attributes.b - 1.0;\n"
" // contrast/brightness\n"
" gl_FragColor = ( col * vid_attributes.g) + vid_attributes.b - 1.0;\n"
"#endif\n"
"}\n"
"\n"