From f617029db3f8786d94c64f1a73c42b89b6d261fa Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Fri, 8 May 2015 00:15:22 -0400 Subject: [PATCH] nv50: keep track of PGRAPH state in nv50_screen Normally this is kept in nv50_context, and on switching the active context, the state is copied from the previous context. However when the last context is destroyed, this is lost, and a new context might later be created. When the currently-active context is destroyed, save its state in the screen, and restore it when setting the current context. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90363 Reported-by: Matteo Bruni Signed-off-by: Ilia Mirkin Tested-by: Matteo Bruni Cc: mesa-stable@lists.freedesktop.org --- .../drivers/nouveau/nv50/nv50_context.c | 11 +++++-- .../drivers/nouveau/nv50/nv50_context.h | 29 +------------------ .../drivers/nouveau/nv50/nv50_screen.h | 24 +++++++++++++++ .../nouveau/nv50/nv50_state_validate.c | 2 ++ 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c index 2cfd5db5ea0..5b5d3912c20 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_context.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c @@ -138,8 +138,11 @@ nv50_destroy(struct pipe_context *pipe) { struct nv50_context *nv50 = nv50_context(pipe); - if (nv50_context_screen(nv50)->cur_ctx == nv50) - nv50_context_screen(nv50)->cur_ctx = NULL; + if (nv50->screen->cur_ctx == nv50) { + nv50->screen->cur_ctx = NULL; + /* Save off the state in case another context gets created */ + nv50->screen->save_state = nv50->state; + } nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL); nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel); @@ -290,6 +293,10 @@ nv50_create(struct pipe_screen *pscreen, void *priv) pipe->get_sample_position = nv50_context_get_sample_position; if (!screen->cur_ctx) { + /* Restore the last context's state here, normally handled during + * context switch + */ + nv50->state = screen->save_state; screen->cur_ctx = nv50; nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx); } diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.h b/src/gallium/drivers/nouveau/nv50/nv50_context.h index 45eb554eb4f..1f123ef7e92 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_context.h +++ b/src/gallium/drivers/nouveau/nv50/nv50_context.h @@ -104,28 +104,7 @@ struct nv50_context { uint32_t dirty; boolean cb_dirty; - struct { - uint32_t instance_elts; /* bitmask of per-instance elements */ - uint32_t instance_base; - uint32_t interpolant_ctrl; - uint32_t semantic_color; - uint32_t semantic_psize; - int32_t index_bias; - boolean uniform_buffer_bound[3]; - boolean prim_restart; - boolean point_sprite; - boolean rt_serialize; - boolean flushed; - boolean rasterizer_discard; - uint8_t tls_required; - boolean new_tls_space; - uint8_t num_vtxbufs; - uint8_t num_vtxelts; - uint8_t num_textures[3]; - uint8_t num_samplers[3]; - uint8_t prim_size; - uint16_t scissor; - } state; + struct nv50_graph_state state; struct nv50_blend_stateobj *blend; struct nv50_rasterizer_stateobj *rast; @@ -191,12 +170,6 @@ nv50_context(struct pipe_context *pipe) return (struct nv50_context *)pipe; } -static INLINE struct nv50_screen * -nv50_context_screen(struct nv50_context *nv50) -{ - return nv50_screen(&nv50->base.screen->base); -} - /* return index used in nv50_context arrays for a specific shader type */ static INLINE unsigned nv50_context_shader_stage(unsigned pipe) diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.h b/src/gallium/drivers/nouveau/nv50/nv50_screen.h index f8ce365135a..881051b1862 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.h +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.h @@ -25,10 +25,34 @@ struct nv50_context; struct nv50_blitter; +struct nv50_graph_state { + uint32_t instance_elts; /* bitmask of per-instance elements */ + uint32_t instance_base; + uint32_t interpolant_ctrl; + uint32_t semantic_color; + uint32_t semantic_psize; + int32_t index_bias; + boolean uniform_buffer_bound[3]; + boolean prim_restart; + boolean point_sprite; + boolean rt_serialize; + boolean flushed; + boolean rasterizer_discard; + uint8_t tls_required; + boolean new_tls_space; + uint8_t num_vtxbufs; + uint8_t num_vtxelts; + uint8_t num_textures[3]; + uint8_t num_samplers[3]; + uint8_t prim_size; + uint16_t scissor; +}; + struct nv50_screen { struct nouveau_screen base; struct nv50_context *cur_ctx; + struct nv50_graph_state save_state; struct nouveau_bo *code; struct nouveau_bo *uniforms; diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c index 85e19b4c623..116bf4bba7c 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c @@ -394,6 +394,8 @@ nv50_switch_pipe_context(struct nv50_context *ctx_to) if (ctx_from) ctx_to->state = ctx_from->state; + else + ctx_to->state = ctx_to->screen->save_state; ctx_to->dirty = ~0; ctx_to->viewports_dirty = ~0; -- 2.30.2