mirror of https://github.com/xemu-project/xemu.git
nv2a: Add Gaussian convolution filter for AA
This commit is contained in:
parent
a34cab69dd
commit
0bec22318a
|
@ -517,6 +517,9 @@
|
|||
#define NV_PGRAPH_TEXCTL2_1 0x000019F0
|
||||
#define NV_PGRAPH_TEXFILTER0 0x000019F4
|
||||
# define NV_PGRAPH_TEXFILTER0_MIPMAP_LOD_BIAS 0x00001FFF
|
||||
# define NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL 0x0000E000
|
||||
# define NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_QUINCUNX 1
|
||||
# define NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_GAUSSIAN_3 2
|
||||
# define NV_PGRAPH_TEXFILTER0_MIN 0x003F0000
|
||||
# define NV_PGRAPH_TEXFILTER0_MIN_BOX_LOD0 1
|
||||
# define NV_PGRAPH_TEXFILTER0_MIN_TENT_LOD0 2
|
||||
|
|
|
@ -63,7 +63,7 @@ static const GLenum pgraph_texture_min_filter_map[] = {
|
|||
GL_LINEAR_MIPMAP_NEAREST,
|
||||
GL_NEAREST_MIPMAP_LINEAR,
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_LINEAR, /* TODO: Convolution filter... */
|
||||
GL_LINEAR,
|
||||
};
|
||||
|
||||
static const GLenum pgraph_texture_mag_filter_map[] = {
|
||||
|
@ -3358,6 +3358,21 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
|
|||
state.psh.snorm_tex[i] = (f.gl_internal_format == GL_RGB8_SNORM)
|
||||
|| (f.gl_internal_format == GL_RG8_SNORM);
|
||||
|
||||
uint32_t filter = pg->regs[NV_PGRAPH_TEXFILTER0 + i*4];
|
||||
unsigned int min_filter = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_MIN);
|
||||
enum ConvolutionFilter kernel = CONVOLUTION_FILTER_DISABLED;
|
||||
/* FIXME: We do not distinguish between min and mag when
|
||||
* performing convolution. Just use it if specified for min (common AA
|
||||
* case).
|
||||
*/
|
||||
if (min_filter == NV_PGRAPH_TEXFILTER0_MIN_CONVOLUTION_2D_LOD0) {
|
||||
int k = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL);
|
||||
assert(k == NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_QUINCUNX ||
|
||||
k == NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_GAUSSIAN_3);
|
||||
kernel = (enum ConvolutionFilter)k;
|
||||
}
|
||||
|
||||
state.psh.conv_tex[i] = kernel;
|
||||
}
|
||||
|
||||
ShaderBinding* cached_shader = (ShaderBinding*)g_hash_table_lookup(pg->shader_cache, &state);
|
||||
|
|
|
@ -588,6 +588,22 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
"vec3 dotmap_hilo_hemisphere(vec3 col) {\n"
|
||||
" return col;\n" // FIXME
|
||||
"}\n"
|
||||
"const float[9] gaussian3x3 = float[9](\n"
|
||||
" 1.0/16.0, 2.0/16.0, 1.0/16.0,\n"
|
||||
" 2.0/16.0, 4.0/16.0, 2.0/16.0,\n"
|
||||
" 1.0/16.0, 2.0/16.0, 1.0/16.0);\n"
|
||||
"const vec2[9] convolution3x3 = vec2[9](\n"
|
||||
" vec2(-1.0,-1.0),vec2(0.0,-1.0),vec2(1.0,-1.0),\n"
|
||||
" vec2(-1.0, 0.0),vec2(0.0, 0.0),vec2(1.0, 0.0),\n"
|
||||
" vec2(-1.0, 1.0),vec2(0.0, 1.0),vec2(1.0, 1.0));\n"
|
||||
"vec4 gaussianFilter2DRectProj(sampler2DRect sampler, vec3 texCoord) {\n"
|
||||
" vec4 sum = vec4(0.0);\n"
|
||||
" for (int i = 0; i < 9; i++) {\n"
|
||||
" sum += gaussian3x3[i]*textureProj(sampler,\n"
|
||||
" texCoord + vec3(convolution3x3[i], 0.0));\n"
|
||||
" }\n"
|
||||
" return sum;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
/* Window Clipping */
|
||||
|
@ -658,11 +674,25 @@ static QString* psh_convert(struct PixelShader *ps)
|
|||
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_NONE */\n",
|
||||
i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_PROJECT2D:
|
||||
case PS_TEXTUREMODES_PROJECT2D: {
|
||||
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
|
||||
qstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyw);\n",
|
||||
i, i, i);
|
||||
const char *lookup = "textureProj";
|
||||
if ((ps->state.conv_tex[i] == CONVOLUTION_FILTER_GAUSSIAN)
|
||||
|| (ps->state.conv_tex[i] == CONVOLUTION_FILTER_QUINCUNX)) {
|
||||
/* FIXME: Quincunx looks better than Linear and costs less than
|
||||
* Gaussian, but Gaussian should be plenty fast so use it for
|
||||
* now.
|
||||
*/
|
||||
if (ps->state.rect_tex[i]) {
|
||||
lookup = "gaussianFilter2DRectProj";
|
||||
} else {
|
||||
NV2A_UNIMPLEMENTED("Convolution for 2D textures");
|
||||
}
|
||||
}
|
||||
qstring_append_fmt(vars, "vec4 t%d = %s(texSamp%d, pT%d.xyw);\n",
|
||||
i, lookup, i, i);
|
||||
break;
|
||||
}
|
||||
case PS_TEXTUREMODES_PROJECT3D:
|
||||
sampler_type = "sampler3D";
|
||||
qstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",
|
||||
|
|
|
@ -33,6 +33,12 @@ enum PshAlphaFunc {
|
|||
ALPHA_FUNC_ALWAYS,
|
||||
};
|
||||
|
||||
enum ConvolutionFilter {
|
||||
CONVOLUTION_FILTER_DISABLED,
|
||||
CONVOLUTION_FILTER_QUINCUNX,
|
||||
CONVOLUTION_FILTER_GAUSSIAN,
|
||||
};
|
||||
|
||||
typedef struct PshState {
|
||||
/* fragment shader - register combiner stuff */
|
||||
uint32_t combiner_control;
|
||||
|
@ -48,6 +54,7 @@ typedef struct PshState {
|
|||
bool snorm_tex[4];
|
||||
bool compare_mode[4][4];
|
||||
bool alphakill[4];
|
||||
enum ConvolutionFilter conv_tex[4];
|
||||
|
||||
bool alpha_test;
|
||||
enum PshAlphaFunc alpha_func;
|
||||
|
|
Loading…
Reference in New Issue