Skip to content

Commit 2415bc9

Browse files
committed
nv2a: Ignore alpha when processing PVIDEO color keying
Discards the alpha value passed to the color key register, matching tested hardware behavior. Fixes #2421 Tests: https://github.com/abaire/nxdk_pgraph_tests/blob/c64f5af5f7c3a890f1a00a927c6b72c2656ea025/src/tests/pvideo_tests.cpp#L761 Note: PVIDEO tests do not produce artifacts so they must be compared manually against HW. I have verified that they are identical for the subset of surface formats supported by xemu.
1 parent c678433 commit 2415bc9

File tree

4 files changed

+15
-23
lines changed

4 files changed

+15
-23
lines changed

hw/xbox/nv2a/nv2a_regs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,6 @@
696696
# define NV_PVIDEO_COLOR_KEY_RED 0x00FF0000
697697
# define NV_PVIDEO_COLOR_KEY_GREEN 0x0000FF00
698698
# define NV_PVIDEO_COLOR_KEY_BLUE 0x000000FF
699-
# define NV_PVIDEO_COLOR_KEY_ALPHA 0xFF000000
700699

701700

702701
#define NV_PTIMER_INTR_0 0x00000100

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

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,22 @@ void pgraph_gl_init_display(NV2AState *d)
6060
"uniform vec4 pvideo_pos;\n"
6161
"uniform vec3 pvideo_scale;\n"
6262
"uniform bool pvideo_color_key_enable;\n"
63-
"uniform vec4 pvideo_color_key;\n"
63+
"uniform vec3 pvideo_color_key;\n"
6464
"uniform vec2 display_size;\n"
6565
"uniform float line_offset;\n"
6666
"layout(location = 0) out vec4 out_Color;\n"
6767
"void main()\n"
6868
"{\n"
6969
" vec2 texCoord = gl_FragCoord.xy/display_size;\n"
7070
" float rel = display_size.y/textureSize(tex, 0).y/line_offset;\n"
71-
" texCoord.y = rel*(1.0f - texCoord.y);"
71+
" texCoord.y = rel*(1.0f - texCoord.y);\n"
7272
" out_Color.rgba = texture(tex, texCoord);\n"
7373
" if (pvideo_enable) {\n"
7474
" vec2 screenCoord = gl_FragCoord.xy - 0.5;\n"
7575
" vec4 output_region = vec4(pvideo_pos.xy, pvideo_pos.xy + pvideo_pos.zw);\n"
7676
" bvec4 clip = bvec4(lessThan(screenCoord, output_region.xy),\n"
7777
" greaterThan(screenCoord, output_region.zw));\n"
78-
" if (!any(clip) && (!pvideo_color_key_enable || out_Color.rgba == pvideo_color_key)) {\n"
78+
" if (!any(clip) && (!pvideo_color_key_enable || out_Color.rgb == pvideo_color_key)) {\n"
7979
" vec2 out_xy = (screenCoord - pvideo_pos.xy) * pvideo_scale.z;\n"
8080
" vec2 in_st = (pvideo_in_pos + out_xy * pvideo_scale.xy) / textureSize(pvideo_tex, 0);\n"
8181
" in_st.y *= -1.0;\n"
@@ -242,15 +242,11 @@ static void render_display_pvideo_overlay(NV2AState *d)
242242
glUniform1ui(r->disp_rndr.pvideo_color_key_enable_loc,
243243
color_key_enabled);
244244

245-
// TODO: Verify that masking off the top byte is correct.
246-
// SeaBlade sets a color key of 0x80000000 but the texture passed into the
247-
// shader is cleared to 0 alpha.
248-
unsigned int color_key = d->pvideo.regs[NV_PVIDEO_COLOR_KEY] & 0xFFFFFF;
249-
glUniform4f(r->disp_rndr.pvideo_color_key_loc,
245+
unsigned int color_key = d->pvideo.regs[NV_PVIDEO_COLOR_KEY] & 0xFFFFF;
246+
glUniform3f(r->disp_rndr.pvideo_color_key_loc,
250247
GET_MASK(color_key, NV_PVIDEO_COLOR_KEY_RED) / 255.0,
251248
GET_MASK(color_key, NV_PVIDEO_COLOR_KEY_GREEN) / 255.0,
252-
GET_MASK(color_key, NV_PVIDEO_COLOR_KEY_BLUE) / 255.0,
253-
GET_MASK(color_key, NV_PVIDEO_COLOR_KEY_ALPHA) / 255.0);
249+
GET_MASK(color_key, NV_PVIDEO_COLOR_KEY_BLUE) / 255.0);
254250

255251
assert(offset + in_pitch * in_height <= limit);
256252
hwaddr end = base + offset + in_pitch * in_height;

hw/xbox/nv2a/pgraph/pgraph.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3063,7 +3063,7 @@ void pgraph_get_clear_color(PGRAPHState *pg, float rgba[4])
30633063
*b = 1.0f;
30643064
fprintf(stderr, "CLEAR_SURFACE for color_format 0x%x unsupported",
30653065
pg->surface_shape.color_format);
3066-
assert(false);
3066+
assert(!"CLEAR_SURFACE not supported for selected surface format");
30673067
break;
30683068
}
30693069

@@ -3077,7 +3077,7 @@ void pgraph_get_clear_color(PGRAPHState *pg, float rgba[4])
30773077
case NV097_SET_SURFACE_FORMAT_COLOR_LE_X1A7R8G8B8_Z1A7R8G8B8:
30783078
case NV097_SET_SURFACE_FORMAT_COLOR_LE_X1A7R8G8B8_O1A7R8G8B8:
30793079
*a = ((clear_color >> 24) & 0x7F) / 127.0f;
3080-
assert(false); /* Untested */
3080+
assert(!"CLEAR_SURFACE handling for LE_X1A7R8G8B8_Z1A7R8G8B8 and LE_X1A7R8G8B8_O1A7R8G8B8 is untested"); /* Untested */
30813081
break;
30823082
case NV097_SET_SURFACE_FORMAT_COLOR_LE_A8R8G8B8:
30833083
*a = ((clear_color >> 24) & 0xFF) / 255.0f;

hw/xbox/nv2a/pgraph/vk/display.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -213,22 +213,22 @@ static const char *display_frag_glsl =
213213
" vec4 pvideo_pos;\n"
214214
" vec4 pvideo_scale;\n"
215215
" bool pvideo_color_key_enable;\n"
216-
" vec4 pvideo_color_key;\n"
216+
" vec3 pvideo_color_key;\n"
217217
"};\n"
218218
"layout(location = 0) out vec4 out_Color;\n"
219219
"void main()\n"
220220
"{\n"
221221
" vec2 tex_coord = gl_FragCoord.xy/display_size;\n"
222222
" float rel = display_size.y/textureSize(tex, 0).y/line_offset;\n"
223-
" tex_coord.y = 1 + rel*(tex_coord.y - 1);"
223+
" tex_coord.y = 1 + rel*(tex_coord.y - 1);\n"
224224
" tex_coord.y = 1 - tex_coord.y;\n" // GL compat
225225
" out_Color.rgba = texture(tex, tex_coord);\n"
226226
" if (pvideo_enable) {\n"
227227
" vec2 screen_coord = vec2(gl_FragCoord.x, display_size.y - gl_FragCoord.y) * pvideo_scale.z;\n"
228228
" vec4 output_region = vec4(pvideo_pos.xy, pvideo_pos.xy + pvideo_pos.zw);\n"
229229
" bvec4 clip = bvec4(lessThan(screen_coord, output_region.xy),\n"
230230
" greaterThan(screen_coord, output_region.zw));\n"
231-
" if (!any(clip) && (!pvideo_color_key_enable || out_Color.rgba == pvideo_color_key)) {\n"
231+
" if (!any(clip) && (!pvideo_color_key_enable || out_Color.rgb == pvideo_color_key)) {\n"
232232
" vec2 out_xy = screen_coord - pvideo_pos.xy;\n"
233233
" vec2 in_st = (pvideo_in_pos + out_xy * pvideo_scale.xy) / textureSize(pvideo_tex, 0);\n"
234234
" out_Color.rgba = texture(pvideo_tex, in_st);\n"
@@ -849,10 +849,8 @@ static PvideoState get_pvideo_state(PGRAPHState *pg)
849849
state.color_key_enabled =
850850
GET_MASK(d->pvideo.regs[NV_PVIDEO_FORMAT], NV_PVIDEO_FORMAT_DISPLAY);
851851

852-
// TODO: Verify that masking off the top byte is correct.
853-
// SeaBlade sets a color key of 0x80000000 but the texture passed into the
854-
// shader is cleared to 0 alpha.
855-
state.color_key = d->pvideo.regs[NV_PVIDEO_COLOR_KEY] & 0xFFFFFF;
852+
// Note: PVIDEO color keying ignores alpha.
853+
state.color_key = d->pvideo.regs[NV_PVIDEO_COLOR_KEY] & 0xFFFFF;
856854

857855
assert(state.offset + state.pitch * state.in_height <= state.limit);
858856
hwaddr end = state.base + state.offset + state.pitch * state.in_height;
@@ -883,12 +881,11 @@ static void update_uniforms(PGRAPHState *pg, SurfaceBinding *surface)
883881
if (pvideo->enabled) {
884882
uniform1i(l, uniform_index(l, "pvideo_color_key_enable"),
885883
pvideo->color_key_enabled);
886-
uniform4f(
884+
uniform3f(
887885
l, uniform_index(l, "pvideo_color_key"),
888886
GET_MASK(pvideo->color_key, NV_PVIDEO_COLOR_KEY_RED) / 255.0,
889887
GET_MASK(pvideo->color_key, NV_PVIDEO_COLOR_KEY_GREEN) / 255.0,
890-
GET_MASK(pvideo->color_key, NV_PVIDEO_COLOR_KEY_BLUE) / 255.0,
891-
GET_MASK(pvideo->color_key, NV_PVIDEO_COLOR_KEY_ALPHA) / 255.0);
888+
GET_MASK(pvideo->color_key, NV_PVIDEO_COLOR_KEY_BLUE) / 255.0);
892889
uniform2f(l, uniform_index(l, "pvideo_in_pos"), pvideo->in_s,
893890
pvideo->in_t);
894891
uniform4f(l, uniform_index(l, "pvideo_pos"), pvideo->out_x,

0 commit comments

Comments
 (0)