r300: program explicit scissor around viewport

Signed-off-by: Pavel Ondračka <pavel.ondracka@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37977>
This commit is contained in:
Pavel Ondračka
2025-10-20 14:56:04 +02:00
committed by Marge Bot
parent 94093488eb
commit 4d36c637dd
5 changed files with 58 additions and 10 deletions

View File

@@ -416,6 +416,9 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300_init_render_functions(r300);
r300_init_states(&r300->context);
r300->viewport_scissor.maxx = 16384;
r300->viewport_scissor.maxy = 16384;
r300->uploader = u_upload_create(&r300->context, 128 * 1024,
PIPE_BIND_CUSTOM, PIPE_USAGE_STREAM, 0);
r300->context.stream_uploader = u_upload_create(&r300->context, 1024 * 1024,

View File

@@ -545,6 +545,7 @@ struct r300_context {
struct pipe_stencil_ref stencil_ref;
struct pipe_viewport_state viewport;
struct pipe_scissor_state viewport_scissor;
/* Stream locations for SWTCL. */
int stream_loc_notcl[16];
@@ -563,6 +564,7 @@ struct r300_context {
int sprite_coord_enable;
/* Whether we are drawing points, to disable sprite coord if not */
bool is_point;
bool scissor_enabled;
/* Whether two-sided color selection is enabled (AKA light_twoside). */
bool two_sided_color;
bool flatshade;

View File

@@ -863,20 +863,28 @@ void r300_emit_scissor_state(struct r300_context* r300,
unsigned size, void* state)
{
struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state;
struct pipe_scissor_state final = r300->viewport_scissor;
CS_LOCALS(r300);
if (r300->scissor_enabled && scissor) {
final.minx = MAX2(final.minx, scissor->minx);
final.miny = MAX2(final.miny, scissor->miny);
final.maxx = MIN2(final.maxx, scissor->maxx);
final.maxy = MIN2(final.maxy, scissor->maxy);
}
BEGIN_CS(size);
OUT_CS_REG_SEQ(R300_SC_CLIPRECT_TL_0, 2);
if (r300->screen->caps.is_r500) {
OUT_CS((scissor->minx << R300_CLIPRECT_X_SHIFT) |
(scissor->miny << R300_CLIPRECT_Y_SHIFT));
OUT_CS(((scissor->maxx - 1) << R300_CLIPRECT_X_SHIFT) |
((scissor->maxy - 1) << R300_CLIPRECT_Y_SHIFT));
OUT_CS((final.minx << R300_CLIPRECT_X_SHIFT) |
(final.miny << R300_CLIPRECT_Y_SHIFT));
OUT_CS(((final.maxx - 1) << R300_CLIPRECT_X_SHIFT) |
((final.maxy - 1) << R300_CLIPRECT_Y_SHIFT));
} else {
OUT_CS(((scissor->minx + 1440) << R300_CLIPRECT_X_SHIFT) |
((scissor->miny + 1440) << R300_CLIPRECT_Y_SHIFT));
OUT_CS(((scissor->maxx + 1440-1) << R300_CLIPRECT_X_SHIFT) |
((scissor->maxy + 1440-1) << R300_CLIPRECT_Y_SHIFT));
OUT_CS(((final.minx + 1440) << R300_CLIPRECT_X_SHIFT) |
((final.miny + 1440) << R300_CLIPRECT_Y_SHIFT));
OUT_CS(((final.maxx + 1440-1) << R300_CLIPRECT_X_SHIFT) |
((final.maxy + 1440-1) << R300_CLIPRECT_Y_SHIFT));
}
END_CS;
}

View File

@@ -1160,10 +1160,13 @@ void r300_blitter_draw_rectangle(struct blitter_context *blitter,
struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter));
unsigned last_sprite_coord_enable = r300->sprite_coord_enable;
unsigned last_is_point = r300->is_point;
/* We othewise always scissor to the viewport, but blits ignore it. */
struct pipe_scissor_state last_vp_scissor = r300->viewport_scissor;
r300->viewport_scissor = (struct pipe_scissor_state){0, 0, 16384, 16384};
unsigned width = x2 - x1;
unsigned height = y2 - y1;
unsigned vertex_size = !r300->draw ? 8 : 4;
unsigned dwords = 13 + vertex_size +
unsigned dwords = 15 + vertex_size +
(type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY ? 7 : 0);
CS_LOCALS(r300);
@@ -1202,6 +1205,7 @@ void r300_blitter_draw_rectangle(struct blitter_context *blitter,
BEGIN_CS(dwords);
/* Set up GA. */
OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16));
OUT_CS_REG(R300_SC_CLIP_RULE, r300->scissor_enabled ? 0xAAAA : 0xFFFF);
if (type == UTIL_BLITTER_ATTRIB_TEXCOORD_XY) {
/* Set up the GA to generate texcoords. */
@@ -1242,9 +1246,11 @@ done:
/* Restore the state. */
r300_mark_atom_dirty(r300, &r300->rs_state);
r300_mark_atom_dirty(r300, &r300->viewport_state);
r300_mark_atom_dirty(r300, &r300->scissor_state);
r300->sprite_coord_enable = last_sprite_coord_enable;
r300->is_point = last_is_point;
r300->viewport_scissor = last_vp_scissor;
}
void r300_init_render_functions(struct r300_context *r300)

View File

@@ -41,6 +41,20 @@
r300_mark_atom_dirty(r300, &(atom)); \
}
static void
r300_get_scissor_from_viewport(const struct pipe_viewport_state *vp,
struct pipe_scissor_state *scissor)
{
/* SC_CLIP_*_A/B fields are 13 bits. */
unsigned max_scissor = 16384;
float half_w = fabsf(vp->scale[0]);
float half_h = fabsf(vp->scale[1]);
scissor->minx = CLAMP(-half_w + vp->translate[0], 0, max_scissor);
scissor->maxx = CLAMP(half_w + vp->translate[0], 0, max_scissor);
scissor->miny = CLAMP(-half_h + vp->translate[1], 0, max_scissor);
scissor->maxy = CLAMP(half_h + vp->translate[1], 0, max_scissor);
}
static void r300_delete_vs_state(struct pipe_context* pipe, void* shader);
static void r300_delete_fs_state(struct pipe_context* pipe, void* shader);
@@ -1329,7 +1343,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
rs->color_control = R300_SHADE_MODEL_SMOOTH;
}
clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
/* We always clip, either to the user specified settings or the viewport. */
clip_rule = 0xAAAA;
/* Point sprites coord mode */
if (rs->rs.sprite_coord_enable) {
@@ -1419,6 +1434,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
bool last_msaa_enable = r300->msaa_enable;
bool last_flatshade = r300->flatshade;
bool last_clip_halfz = r300->clip_halfz;
bool last_scissor_enabled = r300->scissor_enabled;
if (r300->draw && rs) {
draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state);
@@ -1431,6 +1447,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
r300->msaa_enable = rs->rs.multisample;
r300->flatshade = rs->rs.flatshade;
r300->clip_halfz = rs->rs.clip_halfz;
r300->scissor_enabled = rs->rs.scissor;
} else {
r300->polygon_offset_enabled = false;
r300->sprite_coord_enable = 0;
@@ -1438,6 +1455,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
r300->msaa_enable = false;
r300->flatshade = false;
r300->clip_halfz = false;
r300->scissor_enabled = false;
}
UPDATE_STATE(state, r300->rs_state);
@@ -1463,6 +1481,10 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
if (r300->screen->caps.has_tcl && last_clip_halfz != r300->clip_halfz) {
r300_mark_atom_dirty(r300, &r300->vs_state);
}
if (last_scissor_enabled != r300->scissor_enabled) {
r300_mark_atom_dirty(r300, &r300->scissor_state);
}
}
/* Free rasterizer state. */
@@ -1769,6 +1791,13 @@ static void r300_set_viewport_states(struct pipe_context* pipe,
r300->viewport = *state;
struct pipe_scissor_state vp_scissor;
r300_get_scissor_from_viewport(state, &vp_scissor);
if (memcmp(&vp_scissor, &r300->viewport_scissor, sizeof(vp_scissor)) != 0) {
r300->viewport_scissor = vp_scissor;
r300_mark_atom_dirty(r300, &r300->scissor_state);
}
if (r300->draw) {
draw_set_viewport_states(r300->draw, start_slot, num_viewports, state);
viewport->vte_control = R300_VTX_XY_FMT | R300_VTX_Z_FMT;