Skip to content

Commit 348b03d

Browse files
authored
nv2a: Handle PGRAPH color keying
1 parent 14a0a5f commit 348b03d

File tree

11 files changed

+155
-10
lines changed

11 files changed

+155
-10
lines changed

hw/xbox/nv2a/nv2a_regs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,10 @@
409409
# define NV_PGRAPH_CLEARRECTY_YMIN 0x00000FFF
410410
# define NV_PGRAPH_CLEARRECTY_YMAX 0x0FFF0000
411411
#define NV_PGRAPH_COLORCLEARVALUE 0x0000186C
412+
#define NV_PGRAPH_COLORKEYCOLOR0 0x00001870
413+
#define NV_PGRAPH_COLORKEYCOLOR1 0x00001874
414+
#define NV_PGRAPH_COLORKEYCOLOR2 0x00001878
415+
#define NV_PGRAPH_COLORKEYCOLOR3 0x0000187C
412416
#define NV_PGRAPH_COMBINEFACTOR0 0x00001880
413417
#define NV_PGRAPH_COMBINEFACTOR1 0x000018A0
414418
#define NV_PGRAPH_COMBINEALPHAI0 0x000018C0
@@ -533,6 +537,7 @@
533537
#define NV_PGRAPH_TEXADDRESS2 0x000019C4
534538
#define NV_PGRAPH_TEXADDRESS3 0x000019C8
535539
#define NV_PGRAPH_TEXCTL0_0 0x000019CC
540+
# define NV_PGRAPH_TEXCTL0_0_COLORKEYMODE 0x03
536541
# define NV_PGRAPH_TEXCTL0_0_ALPHAKILLEN (1 << 2)
537542
# define NV_PGRAPH_TEXCTL0_0_MAX_LOD_CLAMP 0x0003FFC0
538543
# define NV_PGRAPH_TEXCTL0_0_MIN_LOD_CLAMP 0x3FFC0000
@@ -1065,6 +1070,7 @@
10651070
# define NV097_SET_COMBINER_FACTOR1 0x00000A80
10661071
# define NV097_SET_COMBINER_ALPHA_OCW 0x00000AA0
10671072
# define NV097_SET_COMBINER_COLOR_ICW 0x00000AC0
1073+
# define NV097_SET_COLOR_KEY_COLOR 0x00000AE0
10681074
# define NV097_SET_VIEWPORT_SCALE 0x00000AF0
10691075
# define NV097_SET_TRANSFORM_PROGRAM 0x00000B00
10701076
# define NV097_SET_TRANSFORM_CONSTANT 0x00000B80

hw/xbox/nv2a/pgraph/gl/renderer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ typedef struct ShaderBinding {
127127

128128
GLint point_params_loc[8];
129129
GLint material_alpha_loc;
130+
131+
GLint color_key_loc[4];
132+
GLint color_key_mask_loc[4];
130133
} ShaderBinding;
131134

132135
typedef struct VertexKey {

hw/xbox/nv2a/pgraph/gl/shaders.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ static void update_shader_constant_locations(ShaderBinding *binding)
133133
}
134134
}
135135
binding->alpha_ref_loc = glGetUniformLocation(binding->gl_program, "alphaRef");
136+
136137
for (int i = 1; i < NV2A_MAX_TEXTURES; i++) {
137138
snprintf(tmp, sizeof(tmp), "bumpMat%d", i);
138139
binding->bump_mat_loc[i] = glGetUniformLocation(binding->gl_program, tmp);
@@ -203,6 +204,16 @@ static void update_shader_constant_locations(ShaderBinding *binding)
203204
binding->material_alpha_loc = -1;
204205
binding->specular_power_loc = -1;
205206
}
207+
208+
for (int i = 0; i < 4; ++i) {
209+
snprintf(tmp, sizeof(tmp), "colorKey[%d]", i);
210+
binding->color_key_loc[i] =
211+
glGetUniformLocation(binding->gl_program, tmp);
212+
213+
snprintf(tmp, sizeof(tmp), "colorKeyMask[%d]", i);
214+
binding->color_key_mask_loc[i] =
215+
glGetUniformLocation(binding->gl_program, tmp);
216+
}
206217
}
207218

208219
static void generate_shaders(ShaderBinding *binding)
@@ -696,6 +707,7 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
696707
bool binding_changed)
697708
{
698709
PGRAPHGLState *r = pg->gl_renderer_state;
710+
ShaderState *state = &binding->state;
699711
int i, j;
700712

701713
/* update combiner constants */
@@ -725,7 +737,6 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
725737
glUniform1i(binding->alpha_ref_loc, alpha_ref);
726738
}
727739

728-
729740
/* For each texture stage */
730741
for (i = 0; i < NV2A_MAX_TEXTURES; i++) {
731742
GLint loc;
@@ -765,6 +776,15 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
765776
assert(r->texture_binding[i] != NULL);
766777
glUniform1f(loc, (float)r->texture_binding[i]->scale);
767778
}
779+
780+
if (binding->color_key_loc[i] != -1) {
781+
glUniform1ui(binding->color_key_loc[i],
782+
pgraph_reg_r(pg, NV_PGRAPH_COLORKEYCOLOR0 + i * 4));
783+
}
784+
if (binding->color_key_mask_loc[i] != -1) {
785+
glUniform1ui(binding->color_key_mask_loc[i],
786+
state->psh.colorkey_mask[i]);
787+
}
768788
}
769789

770790
if (binding->fog_color_loc != -1) {
@@ -794,7 +814,7 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
794814
assert(0);
795815
}
796816

797-
if (binding->state.fixed_function) {
817+
if (state->fixed_function) {
798818
/* update lighting constants */
799819
struct {
800820
uint32_t* v;
@@ -990,7 +1010,8 @@ static bool test_shaders_dirty(PGRAPHState *pg)
9901010
CF(pg->primitive_mode, primitive_mode) \
9911011
CF(pg->surface_scale_factor, surface_scale_factor) \
9921012
CF(pg->compressed_attrs, compressed_attrs) \
993-
CFA(pg->texture_matrix_enable, texture_matrix_enable)
1013+
CFA(pg->texture_matrix_enable, texture_matrix_enable) \
1014+
CR_4(NV_PGRAPH_COLORKEYCOLOR0)
9941015

9951016
#define CR_x(reg, x) CR_x__define(reg, x)
9961017
#define CF_x(type, src, name, x) CF_x__define(type, src, name, x)

hw/xbox/nv2a/pgraph/glsl/psh.c

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ enum PS_DOTMAPPING
174174
PS_DOTMAPPING_HILO_HEMISPHERE= 0x07L, // - * * *
175175
};
176176

177+
enum PS_COLORKEYMODE {
178+
COLOR_KEY_NONE = 0,
179+
COLOR_KEY_KILL_ALPHA = 1,
180+
COLOR_KEY_KILL_COLOR_AND_ALPHA = 2,
181+
COLOR_KEY_DISCARD = 3,
182+
};
183+
177184

178185
// Structures to describe the PS definition
179186

@@ -731,6 +738,19 @@ static void apply_convolution_filter(const struct PixelShader *ps, MString *vars
731738
"}\n", tex, tex, tex, tex, tex_remap, tex);
732739
}
733740

741+
static void define_colorkey_comparator(MString *preflight)
742+
{
743+
// clang-format off
744+
mstring_append(
745+
preflight,
746+
"bool check_color_key(vec4 texel, uint color_key, uint color_key_mask) {\n"
747+
" uvec4 c = uvec4(texel * 255.0 + 0.5);\n"
748+
" uint color = (c.a << 24) | (c.r << 16) | (c.g << 8) | c.b;\n"
749+
" return (color & color_key_mask) == (color_key & color_key_mask);\n"
750+
"}\n");
751+
// clang-format on
752+
}
753+
734754
static MString* psh_convert(struct PixelShader *ps)
735755
{
736756
const char *u = ps->state.vulkan ? "" : "uniform "; // FIXME: Remove
@@ -748,12 +768,15 @@ static MString* psh_convert(struct PixelShader *ps)
748768
"layout(location = 0) out vec4 fragColor;\n");
749769
}
750770

751-
mstring_append_fmt(preflight, "%sint alphaRef;\n"
752-
"%svec4 fogColor;\n"
753-
"%sivec4 clipRegion[8];\n"
754-
"%svec4 clipRange;\n"
755-
"%sfloat depthOffset;\n",
756-
u, u, u, u, u);
771+
mstring_append_fmt(preflight,
772+
"%sint alphaRef;\n"
773+
"%svec4 fogColor;\n"
774+
"%sivec4 clipRegion[8];\n"
775+
"%svec4 clipRange;\n"
776+
"%sfloat depthOffset;\n"
777+
"%suint colorKey[4];\n"
778+
"%suint colorKeyMask[4];\n",
779+
u, u, u, u, u, u, u);
757780
for (int i = 0; i < 4; i++) {
758781
mstring_append_fmt(preflight, "%smat2 bumpMat%d;\n"
759782
"%sfloat bumpScale%d;\n"
@@ -934,6 +957,8 @@ static MString* psh_convert(struct PixelShader *ps)
934957

935958
ps->code = mstring_new();
936959

960+
bool color_key_comparator_defined = false;
961+
937962
for (int i = 0; i < 4; i++) {
938963

939964
const char *sampler_type = get_sampler_type(ps->tex_modes[i], &ps->state, i);
@@ -1184,6 +1209,40 @@ static MString* psh_convert(struct PixelShader *ps)
11841209
i);
11851210
}
11861211

1212+
enum PS_COLORKEYMODE color_key_mode = ps->state.colorkey_mode[i];
1213+
if (color_key_mode != COLOR_KEY_NONE) {
1214+
if (!color_key_comparator_defined) {
1215+
define_colorkey_comparator(preflight);
1216+
color_key_comparator_defined = true;
1217+
}
1218+
1219+
// clang-format off
1220+
mstring_append_fmt(
1221+
vars,
1222+
"if (check_color_key(t%d, colorKey[%d], colorKeyMask[%d])) {\n",
1223+
i, i, i);
1224+
// clang-format on
1225+
1226+
switch (color_key_mode) {
1227+
case COLOR_KEY_DISCARD:
1228+
mstring_append(vars, " discard;\n");
1229+
break;
1230+
1231+
case COLOR_KEY_KILL_ALPHA:
1232+
mstring_append_fmt(vars, " t%d.a = 0.0;\n", i);
1233+
break;
1234+
1235+
case COLOR_KEY_KILL_COLOR_AND_ALPHA:
1236+
mstring_append_fmt(vars, " t%d = vec4(0.0);\n", i);
1237+
break;
1238+
1239+
default:
1240+
assert(!"Unhandled key mode.");
1241+
}
1242+
1243+
mstring_append(vars, "}\n");
1244+
}
1245+
11871246
if (ps->state.rect_tex[i]) {
11881247
mstring_append_fmt(preflight,
11891248
"vec2 norm%d(vec2 coord) {\n"

hw/xbox/nv2a/pgraph/methods.h.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ DEF_METHOD_RANGE(NV097, SET_COMBINER_FACTOR0, 8)
105105
DEF_METHOD_RANGE(NV097, SET_COMBINER_FACTOR1, 8)
106106
DEF_METHOD_RANGE(NV097, SET_COMBINER_ALPHA_OCW, 8)
107107
DEF_METHOD_RANGE(NV097, SET_COMBINER_COLOR_ICW, 8)
108+
DEF_METHOD_RANGE(NV097, SET_COLOR_KEY_COLOR, 4)
108109
DEF_METHOD_RANGE(NV097, SET_VIEWPORT_SCALE, 4)
109110
DEF_METHOD_RANGE(NV097, SET_TRANSFORM_PROGRAM, 32)
110111
DEF_METHOD_RANGE(NV097, SET_TRANSFORM_CONSTANT, 32)

hw/xbox/nv2a/pgraph/pgraph.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,6 +1966,12 @@ DEF_METHOD_INC(NV097, SET_COMBINER_COLOR_ICW)
19661966
pgraph_reg_w(pg, NV_PGRAPH_COMBINECOLORI0 + slot*4, parameter);
19671967
}
19681968

1969+
DEF_METHOD_INC(NV097, SET_COLOR_KEY_COLOR)
1970+
{
1971+
int slot = (method - NV097_SET_COLOR_KEY_COLOR) / 4;
1972+
pgraph_reg_w(pg, NV_PGRAPH_COLORKEYCOLOR0 + slot * 4, parameter);
1973+
}
1974+
19691975
DEF_METHOD_INC(NV097, SET_VIEWPORT_SCALE)
19701976
{
19711977
int slot = (method - NV097_SET_VIEWPORT_SCALE) / 4;

hw/xbox/nv2a/pgraph/psh.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ typedef struct PshState {
6969
bool snorm_tex[4];
7070
bool compare_mode[4][4];
7171
bool alphakill[4];
72+
int colorkey_mode[4];
73+
uint32_t colorkey_mask[4];
7274
enum ConvolutionFilter conv_tex[4];
7375
bool tex_x8y24[4];
7476
int dim_tex[4];

hw/xbox/nv2a/pgraph/shaders.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@
2424
#include "pgraph.h"
2525
#include "shaders.h"
2626

27+
// TODO: https://github.com/xemu-project/xemu/issues/2260
28+
// Investigate how color keying is handled for components with no alpha or
29+
// only alpha.
30+
static uint32_t get_colorkey_mask(unsigned int color_format)
31+
{
32+
switch (color_format) {
33+
case NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X1R5G5B5:
34+
case NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X8R8G8B8:
35+
case NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X1R5G5B5:
36+
case NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8:
37+
return 0x00FFFFFF;
38+
39+
default:
40+
return 0xFFFFFFFF;
41+
}
42+
}
43+
2744
ShaderState pgraph_get_shader_state(PGRAPHState *pg)
2845
{
2946
bool vertex_program = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
@@ -219,6 +236,7 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg)
219236
}
220237

221238
state.psh.alphakill[i] = ctl_0 & NV_PGRAPH_TEXCTL0_0_ALPHAKILLEN;
239+
state.psh.colorkey_mode[i] = ctl_0 & NV_PGRAPH_TEXCTL0_0_COLORKEYMODE;
222240

223241
uint32_t tex_fmt = pgraph_reg_r(pg, NV_PGRAPH_TEXFMT0 + i * 4);
224242
state.psh.dim_tex[i] = GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_DIMENSIONALITY);
@@ -228,6 +246,7 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg)
228246
state.psh.rect_tex[i] = f.linear;
229247
state.psh.tex_x8y24[i] = color_format == NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED ||
230248
color_format == NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FLOAT;
249+
state.psh.colorkey_mask[i] = get_colorkey_mask(color_format);
231250

232251
uint32_t border_source =
233252
GET_MASK(tex_fmt, NV_PGRAPH_TEXFMT0_BORDER_SOURCE);

hw/xbox/nv2a/pgraph/vk/glsl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,10 @@ void uniform4i(ShaderUniformLayout *layout, int idx, int v0, int v1, int v2, int
202202
uniform1iv(layout, idx, 4, values);
203203
}
204204

205+
static inline void uniform1uiv(ShaderUniformLayout *layout, int idx,
206+
size_t count, uint32_t *values)
207+
{
208+
uniform_copy(layout, idx, values, sizeof(uint32_t), count);
209+
}
210+
205211
#endif

hw/xbox/nv2a/pgraph/vk/renderer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ typedef struct ShaderBinding {
195195
int clip_region_loc;
196196
int material_alpha_loc;
197197

198+
int color_key_loc;
199+
int color_key_mask_loc;
200+
198201
int uniform_attrs_loc;
199202
} ShaderBinding;
200203

0 commit comments

Comments
 (0)