mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-04 05:28:05 +02:00
nv50,nvc0: add states mask to state validation function
This prevents null dereferences in validation of interdependent state after a switch to a pipe context where we mark all state as dirty but where not all state is valid / set yet.
This commit is contained in:
parent
9f4998639c
commit
222b3ea653
8 changed files with 31 additions and 24 deletions
|
|
@ -172,7 +172,8 @@ extern void nv50_init_state_functions(struct nv50_context *);
|
|||
|
||||
/* nv50_state_validate.c */
|
||||
/* @words: check for space before emitting relocs */
|
||||
extern boolean nv50_state_validate(struct nv50_context *, unsigned words);
|
||||
extern boolean nv50_state_validate(struct nv50_context *, uint32_t state_mask,
|
||||
unsigned space_words);
|
||||
|
||||
/* nv50_surface.c */
|
||||
extern void nv50_clear(struct pipe_context *, unsigned buffers,
|
||||
|
|
|
|||
|
|
@ -306,7 +306,11 @@ nv50_switch_pipe_context(struct nv50_context *ctx_to)
|
|||
if (!ctx_to->blend)
|
||||
ctx_to->dirty &= ~NV50_NEW_BLEND;
|
||||
if (!ctx_to->rast)
|
||||
#ifdef NV50_SCISSORS_CLIPPING
|
||||
ctx_to->dirty &= ~(NV50_NEW_RASTERIZER | NV50_NEW_SCISSOR);
|
||||
#else
|
||||
ctx_to->dirty &= ~NV50_NEW_RASTERIZER;
|
||||
#endif
|
||||
if (!ctx_to->zsa)
|
||||
ctx_to->dirty &= ~NV50_NEW_ZSA;
|
||||
|
||||
|
|
@ -350,21 +354,24 @@ static struct state_validate {
|
|||
#define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
|
||||
|
||||
boolean
|
||||
nv50_state_validate(struct nv50_context *nv50, unsigned words)
|
||||
nv50_state_validate(struct nv50_context *nv50, uint32_t mask, unsigned words)
|
||||
{
|
||||
uint32_t state_mask;
|
||||
unsigned i;
|
||||
|
||||
if (nv50->screen->cur_ctx != nv50)
|
||||
nv50_switch_pipe_context(nv50);
|
||||
|
||||
if (nv50->dirty) {
|
||||
state_mask = nv50->dirty & mask;
|
||||
|
||||
if (state_mask) {
|
||||
for (i = 0; i < validate_list_len; ++i) {
|
||||
struct state_validate *validate = &validate_list[i];
|
||||
|
||||
if (nv50->dirty & validate->states)
|
||||
if (state_mask & validate->states)
|
||||
validate->func(nv50);
|
||||
}
|
||||
nv50->dirty = 0;
|
||||
nv50->dirty &= ~state_mask;
|
||||
}
|
||||
|
||||
MARK_RING(nv50->screen->base.channel, words, 0);
|
||||
|
|
|
|||
|
|
@ -370,12 +370,10 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers,
|
|||
struct nouveau_channel *chan = nv50->screen->base.channel;
|
||||
struct pipe_framebuffer_state *fb = &nv50->framebuffer;
|
||||
unsigned i;
|
||||
const unsigned dirty = nv50->dirty;
|
||||
uint32_t mode = 0;
|
||||
|
||||
/* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
|
||||
nv50->dirty &= NV50_NEW_FRAMEBUFFER;
|
||||
if (!nv50_state_validate(nv50, 9 + (fb->nr_cbufs * 2)))
|
||||
if (!nv50_state_validate(nv50, NV50_NEW_FRAMEBUFFER, 9 + (fb->nr_cbufs * 2)))
|
||||
return;
|
||||
|
||||
if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
|
||||
|
|
@ -408,8 +406,6 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers,
|
|||
BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
|
||||
OUT_RING (chan, (i << 6) | 0x3c);
|
||||
}
|
||||
|
||||
nv50->dirty = dirty & ~NV50_NEW_FRAMEBUFFER;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -851,7 +847,7 @@ nv50_resource_resolve(struct pipe_context *pipe,
|
|||
|
||||
nv50_blitctx_prepare_state(blit);
|
||||
|
||||
nv50_state_validate(nv50, 36);
|
||||
nv50_state_validate(nv50, ~0, 36);
|
||||
|
||||
x_range =
|
||||
(float)(info->src.x1 - info->src.x0) /
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
|
|||
if (nv50->vbo_user && !(nv50->dirty & (NV50_NEW_VERTEX | NV50_NEW_ARRAYS)))
|
||||
nv50_update_user_vbufs(nv50);
|
||||
|
||||
nv50_state_validate(nv50, 8); /* 8 as minimum, we use flush_notify here */
|
||||
nv50_state_validate(nv50, ~0, 8); /* 8 as minimum, we use flush_notify */
|
||||
|
||||
chan->flush_notify = nv50_draw_vbo_flush_notify;
|
||||
|
||||
|
|
|
|||
|
|
@ -179,7 +179,8 @@ void nvc0_tfb_validate(struct nvc0_context *);
|
|||
extern void nvc0_init_state_functions(struct nvc0_context *);
|
||||
|
||||
/* nvc0_state_validate.c */
|
||||
extern boolean nvc0_state_validate(struct nvc0_context *);
|
||||
extern boolean nvc0_state_validate(struct nvc0_context *, uint32_t state_mask,
|
||||
unsigned space_words);
|
||||
|
||||
/* nvc0_surface.c */
|
||||
extern void nvc0_clear(struct pipe_context *, unsigned buffers,
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ nvc0_switch_pipe_context(struct nvc0_context *ctx_to)
|
|||
if (!ctx_to->blend)
|
||||
ctx_to->dirty &= ~NVC0_NEW_BLEND;
|
||||
if (!ctx_to->rast)
|
||||
ctx_to->dirty &= ~NVC0_NEW_RASTERIZER;
|
||||
ctx_to->dirty &= ~(NVC0_NEW_RASTERIZER | NVC0_NEW_SCISSOR);
|
||||
if (!ctx_to->zsa)
|
||||
ctx_to->dirty &= ~NVC0_NEW_ZSA;
|
||||
|
||||
|
|
@ -490,23 +490,28 @@ static struct state_validate {
|
|||
#define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
|
||||
|
||||
boolean
|
||||
nvc0_state_validate(struct nvc0_context *nvc0)
|
||||
nvc0_state_validate(struct nvc0_context *nvc0, uint32_t mask, unsigned words)
|
||||
{
|
||||
uint32_t state_mask;
|
||||
unsigned i;
|
||||
|
||||
if (nvc0->screen->cur_ctx != nvc0)
|
||||
nvc0_switch_pipe_context(nvc0);
|
||||
|
||||
if (nvc0->dirty) {
|
||||
state_mask = nvc0->dirty & mask;
|
||||
|
||||
if (state_mask) {
|
||||
for (i = 0; i < validate_list_len; ++i) {
|
||||
struct state_validate *validate = &validate_list[i];
|
||||
|
||||
if (nvc0->dirty & validate->states)
|
||||
if (state_mask & validate->states)
|
||||
validate->func(nvc0);
|
||||
}
|
||||
nvc0->dirty = 0;
|
||||
nvc0->dirty &= ~state_mask;
|
||||
}
|
||||
|
||||
MARK_RING(nvc0->screen->base.channel, words, 0);
|
||||
|
||||
nvc0_bufctx_emit_relocs(nvc0);
|
||||
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -383,12 +383,10 @@ nvc0_clear(struct pipe_context *pipe, unsigned buffers,
|
|||
struct nouveau_channel *chan = nvc0->screen->base.channel;
|
||||
struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
|
||||
unsigned i;
|
||||
const unsigned dirty = nvc0->dirty;
|
||||
uint32_t mode = 0;
|
||||
|
||||
/* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
|
||||
nvc0->dirty &= NVC0_NEW_FRAMEBUFFER;
|
||||
if (!nvc0_state_validate(nvc0))
|
||||
if (!nvc0_state_validate(nvc0, NVC0_NEW_FRAMEBUFFER, 9 + (fb->nr_cbufs * 2)))
|
||||
return;
|
||||
|
||||
if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
|
||||
|
|
@ -421,8 +419,6 @@ nvc0_clear(struct pipe_context *pipe, unsigned buffers,
|
|||
BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
|
||||
OUT_RING (chan, (i << 6) | 0x3c);
|
||||
}
|
||||
|
||||
nvc0->dirty = dirty & ~NVC0_NEW_FRAMEBUFFER;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -584,7 +584,8 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
|
|||
if (nvc0->vbo_user && !(nvc0->dirty & (NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS)))
|
||||
nvc0_update_user_vbufs(nvc0);
|
||||
|
||||
nvc0_state_validate(nvc0);
|
||||
/* 8 as minimum to avoid immediate double validation of new buffers */
|
||||
nvc0_state_validate(nvc0, ~0, 8);
|
||||
|
||||
chan->flush_notify = nvc0_draw_vbo_flush_notify;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue