mirror of https://github.com/xemu-project/xemu.git
nv2a: Fix window clip coordinate transform
This commit is contained in:
parent
3884b8d44b
commit
ebcc77c6c8
|
@ -3622,34 +3622,22 @@ static void pgraph_shader_update_constants(PGRAPHState *pg,
|
||||||
|
|
||||||
/* Clipping regions */
|
/* Clipping regions */
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
if (pg->shader_binding->clip_region_loc[i] == -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t x = pg->regs[NV_PGRAPH_WINDOWCLIPX0 + i * 4];
|
uint32_t x = pg->regs[NV_PGRAPH_WINDOWCLIPX0 + i * 4];
|
||||||
unsigned int x_min = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMIN);
|
unsigned int x_min = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMIN);
|
||||||
unsigned int x_max = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMAX);
|
unsigned int x_max = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMAX);
|
||||||
|
|
||||||
/* Adjust y-coordinates for the OpenGL viewport: translate coordinates
|
|
||||||
* to have the origin at the bottom-left of the surface (as opposed to
|
|
||||||
* top-left), and flip y-min and y-max accordingly.
|
|
||||||
*/
|
|
||||||
// FIXME: Check
|
|
||||||
uint32_t y = pg->regs[NV_PGRAPH_WINDOWCLIPY0 + i * 4];
|
uint32_t y = pg->regs[NV_PGRAPH_WINDOWCLIPY0 + i * 4];
|
||||||
unsigned int y_min = pg->surface_binding_dim.clip_height
|
unsigned int y_min = GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMIN);
|
||||||
+ pg->surface_binding_dim.clip_y
|
unsigned int y_max = GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMAX);
|
||||||
- 1
|
|
||||||
- GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMAX);
|
|
||||||
unsigned int y_max = pg->surface_binding_dim.clip_height
|
|
||||||
+ pg->surface_binding_dim.clip_y
|
|
||||||
- 1
|
|
||||||
- GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMIN);
|
|
||||||
|
|
||||||
pgraph_apply_anti_aliasing_factor(pg, &x_min, &y_min);
|
pgraph_apply_anti_aliasing_factor(pg, &x_min, &y_min);
|
||||||
pgraph_apply_anti_aliasing_factor(pg, &x_max, &y_max);
|
pgraph_apply_anti_aliasing_factor(pg, &x_max, &y_max);
|
||||||
|
|
||||||
|
/* Translate for the GL viewport origin */
|
||||||
|
unsigned int y_min_xlat = MAX(pg->surface_binding_dim.height - y_max - 1, 0);
|
||||||
|
unsigned int y_max_xlat = MIN(pg->surface_binding_dim.height - y_min - 1,
|
||||||
|
pg->surface_binding_dim.height);
|
||||||
|
|
||||||
glUniform4i(pg->shader_binding->clip_region_loc[i],
|
glUniform4i(pg->shader_binding->clip_region_loc[i],
|
||||||
x_min, y_min, x_max + 1, y_max + 1);
|
x_min, y_min_xlat, x_max, y_max_xlat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3759,6 +3747,7 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
|
||||||
/* register combiner stuff */
|
/* register combiner stuff */
|
||||||
state.psh.window_clip_exclusive = pg->regs[NV_PGRAPH_SETUPRASTER]
|
state.psh.window_clip_exclusive = pg->regs[NV_PGRAPH_SETUPRASTER]
|
||||||
& NV_PGRAPH_SETUPRASTER_WINDOWCLIPTYPE;
|
& NV_PGRAPH_SETUPRASTER_WINDOWCLIPTYPE;
|
||||||
|
assert(!state.psh.window_clip_exclusive); /* FIXME: Untested */
|
||||||
state.psh.combiner_control = pg->regs[NV_PGRAPH_COMBINECTL];
|
state.psh.combiner_control = pg->regs[NV_PGRAPH_COMBINECTL];
|
||||||
state.psh.shader_stage_program = pg->regs[NV_PGRAPH_SHADERPROG];
|
state.psh.shader_stage_program = pg->regs[NV_PGRAPH_SHADERPROG];
|
||||||
state.psh.other_stage_input = pg->regs[NV_PGRAPH_SHADERCTL];
|
state.psh.other_stage_input = pg->regs[NV_PGRAPH_SHADERCTL];
|
||||||
|
@ -3859,45 +3848,6 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Window clip
|
|
||||||
*
|
|
||||||
* Optimization note: very quickly check to ignore any repeated or zero-size
|
|
||||||
* clipping regions. Note that if region number 7 is valid, but the rest are
|
|
||||||
* not, we will still add all of them. Clip regions seem to be typically
|
|
||||||
* front-loaded (meaning the first one or two regions are populated, and the
|
|
||||||
* following are zeroed-out), so let's avoid adding any more complicated
|
|
||||||
* masking or copying logic here for now unless we discover a valid case.
|
|
||||||
*/
|
|
||||||
assert(!state.psh.window_clip_exclusive); /* FIXME: Untested */
|
|
||||||
state.psh.window_clip_count = 0;
|
|
||||||
uint32_t last_x = 0, last_y = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
const uint32_t x = pg->regs[NV_PGRAPH_WINDOWCLIPX0 + i * 4];
|
|
||||||
const uint32_t y = pg->regs[NV_PGRAPH_WINDOWCLIPY0 + i * 4];
|
|
||||||
const uint32_t x_min = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMIN);
|
|
||||||
const uint32_t x_max = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMAX);
|
|
||||||
const uint32_t y_min = GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMIN);
|
|
||||||
const uint32_t y_max = GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMAX);
|
|
||||||
|
|
||||||
/* Check for zero width or height clipping region */
|
|
||||||
if ((x_min == x_max) || (y_min == y_max)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for in-order duplicate regions */
|
|
||||||
if ((x == last_x) && (y == last_y)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
NV2A_DPRINTF("Clipping Region %d: min=(%d, %d) max=(%d, %d)\n",
|
|
||||||
i, x_min, y_min, x_max, y_max);
|
|
||||||
|
|
||||||
state.psh.window_clip_count = i + 1;
|
|
||||||
last_x = x;
|
|
||||||
last_y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy content of enabled combiner stages */
|
/* Copy content of enabled combiner stages */
|
||||||
int num_stages = pg->regs[NV_PGRAPH_COMBINECTL] & 0xFF;
|
int num_stages = pg->regs[NV_PGRAPH_COMBINECTL] & 0xFF;
|
||||||
for (i = 0; i < num_stages; i++) {
|
for (i = 0; i < num_stages; i++) {
|
||||||
|
|
|
@ -609,38 +609,31 @@ static MString* psh_convert(struct PixelShader *ps)
|
||||||
|
|
||||||
/* Window Clipping */
|
/* Window Clipping */
|
||||||
MString *clip = mstring_new();
|
MString *clip = mstring_new();
|
||||||
if (ps->state.window_clip_count != 0) {
|
mstring_append(preflight, "uniform ivec4 clipRegion[8];\n");
|
||||||
mstring_append_fmt(preflight, "uniform ivec4 clipRegion[%d];\n",
|
mstring_append_fmt(clip, "/* Window-clip (%s) */\n",
|
||||||
ps->state.window_clip_count);
|
ps->state.window_clip_exclusive ?
|
||||||
mstring_append_fmt(clip, "/* Window-clip (%s) */\n",
|
"Exclusive" : "Inclusive");
|
||||||
ps->state.window_clip_exclusive ?
|
if (!ps->state.window_clip_exclusive) {
|
||||||
"Exclusive" : "Inclusive");
|
mstring_append(clip, "bool clipContained = false;\n");
|
||||||
if (!ps->state.window_clip_exclusive) {
|
}
|
||||||
mstring_append(clip, "bool clipContained = false;\n");
|
mstring_append(clip, "for (int i = 0; i < 8; i++) {\n"
|
||||||
}
|
" bvec4 clipTest = bvec4(lessThan(gl_FragCoord.xy-0.5, clipRegion[i].xy),\n"
|
||||||
mstring_append_fmt(clip, "for (int i = 0; i < %d; i++) {\n",
|
" greaterThan(gl_FragCoord.xy-0.5, clipRegion[i].zw));\n"
|
||||||
ps->state.window_clip_count);
|
" if (!any(clipTest)) {\n");
|
||||||
mstring_append(clip, " bvec4 clipTest = bvec4(lessThan(gl_FragCoord.xy, clipRegion[i].xy),\n"
|
if (ps->state.window_clip_exclusive) {
|
||||||
" greaterThan(gl_FragCoord.xy, clipRegion[i].zw));\n"
|
/* Pixel in clip region = exclude by discarding */
|
||||||
" if (!any(clipTest)) {\n");
|
mstring_append(clip, " discard;\n");
|
||||||
if (ps->state.window_clip_exclusive) {
|
assert(false); /* Untested */
|
||||||
/* Pixel in clip region = exclude by discarding */
|
} else {
|
||||||
mstring_append(clip, " discard;\n");
|
/* Pixel in clip region = mark pixel as contained and leave */
|
||||||
assert(false); /* Untested */
|
mstring_append(clip, " clipContained = true;\n"
|
||||||
} else {
|
" break;\n");
|
||||||
/* Pixel in clip region = mark pixel as contained and leave */
|
}
|
||||||
mstring_append(clip, " clipContained = true;\n"
|
mstring_append(clip, " }\n"
|
||||||
" break;\n");
|
"}\n");
|
||||||
}
|
/* Check for inclusive window clip */
|
||||||
mstring_append(clip, " }\n"
|
if (!ps->state.window_clip_exclusive) {
|
||||||
"}\n");
|
mstring_append(clip, "if (!clipContained) { discard; }\n");
|
||||||
/* Check for inclusive window clip */
|
|
||||||
if (!ps->state.window_clip_exclusive) {
|
|
||||||
mstring_append(clip, "if (!clipContained) { discard; }\n");
|
|
||||||
}
|
|
||||||
} else if (ps->state.window_clip_exclusive) {
|
|
||||||
/* Clip everything */
|
|
||||||
mstring_append(clip, "discard;\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* calculate perspective-correct inputs */
|
/* calculate perspective-correct inputs */
|
||||||
|
|
|
@ -60,7 +60,6 @@ typedef struct PshState {
|
||||||
enum PshAlphaFunc alpha_func;
|
enum PshAlphaFunc alpha_func;
|
||||||
|
|
||||||
bool window_clip_exclusive;
|
bool window_clip_exclusive;
|
||||||
unsigned int window_clip_count;
|
|
||||||
} PshState;
|
} PshState;
|
||||||
|
|
||||||
MString *psh_translate(const PshState state);
|
MString *psh_translate(const PshState state);
|
||||||
|
|
Loading…
Reference in New Issue