[Mesa-dev] [PATCH 03/84] st/nine: Move draw calls to nine_state

Axel Davy axel.davy at ens.fr
Wed Dec 7 22:54:36 UTC 2016


Part of the refactor to move all gallium calls to
nine_state.c, and have all internal states required
for those calls in nine_context.

Signed-off-by: Axel Davy <axel.davy at ens.fr>
---
 src/gallium/state_trackers/nine/device9.c       | 209 +++--------------
 src/gallium/state_trackers/nine/nine_ff.c       |  84 +++----
 src/gallium/state_trackers/nine/nine_state.c    | 283 +++++++++++++++++++++---
 src/gallium/state_trackers/nine/nine_state.h    |  41 +++-
 src/gallium/state_trackers/nine/pixelshader9.c  |   4 +-
 src/gallium/state_trackers/nine/pixelshader9.h  |   7 +-
 src/gallium/state_trackers/nine/stateblock9.c   |   6 +-
 src/gallium/state_trackers/nine/vertexshader9.c |   6 +-
 src/gallium/state_trackers/nine/vertexshader9.h |   7 +-
 9 files changed, 392 insertions(+), 255 deletions(-)

diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c
index 7e6d3b3..68eef8f 100644
--- a/src/gallium/state_trackers/nine/device9.c
+++ b/src/gallium/state_trackers/nine/device9.c
@@ -106,10 +106,10 @@ NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset )
     This->state.scissor.maxy = refSurf->desc.Height;
 
     if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil) {
-        This->state.rs[D3DRS_ZENABLE] = TRUE;
+        nine_context_set_render_state(This, D3DRS_ZENABLE, TRUE);
         This->state.rs_advertised[D3DRS_ZENABLE] = TRUE;
     }
-    if (This->state.rs[D3DRS_ZENABLE])
+    if (This->state.rs_advertised[D3DRS_ZENABLE])
         NineDevice9_SetDepthStencilSurface(
             This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf);
 }
@@ -2221,64 +2221,6 @@ NineDevice9_GetClipPlane( struct NineDevice9 *This,
     return D3D_OK;
 }
 
-#define RESZ_CODE 0x7fa05000
-
-static HRESULT
-NineDevice9_ResolveZ( struct NineDevice9 *This )
-{
-    struct nine_state *state = &This->state;
-    const struct util_format_description *desc;
-    struct NineSurface9 *source = state->ds;
-    struct NineBaseTexture9 *destination = state->texture[0];
-    struct pipe_resource *src, *dst;
-    struct pipe_blit_info blit;
-
-    DBG("RESZ resolve\n");
-
-    user_assert(source && destination &&
-                destination->base.type == D3DRTYPE_TEXTURE, D3DERR_INVALIDCALL);
-
-    src = source->base.resource;
-    dst = destination->base.resource;
-
-    user_assert(src && dst, D3DERR_INVALIDCALL);
-
-    /* check dst is depth format. we know already for src */
-    desc = util_format_description(dst->format);
-    user_assert(desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS, D3DERR_INVALIDCALL);
-
-    memset(&blit, 0, sizeof(blit));
-    blit.src.resource = src;
-    blit.src.level = 0;
-    blit.src.format = src->format;
-    blit.src.box.z = 0;
-    blit.src.box.depth = 1;
-    blit.src.box.x = 0;
-    blit.src.box.y = 0;
-    blit.src.box.width = src->width0;
-    blit.src.box.height = src->height0;
-
-    blit.dst.resource = dst;
-    blit.dst.level = 0;
-    blit.dst.format = dst->format;
-    blit.dst.box.z = 0;
-    blit.dst.box.depth = 1;
-    blit.dst.box.x = 0;
-    blit.dst.box.y = 0;
-    blit.dst.box.width = dst->width0;
-    blit.dst.box.height = dst->height0;
-
-    blit.mask = PIPE_MASK_ZS;
-    blit.filter = PIPE_TEX_FILTER_NEAREST;
-    blit.scissor_enable = FALSE;
-
-    This->pipe->blit(This->pipe, &blit);
-    return D3D_OK;
-}
-
-#define ALPHA_TO_COVERAGE_ENABLE   MAKEFOURCC('A', '2', 'M', '1')
-#define ALPHA_TO_COVERAGE_DISABLE  MAKEFOURCC('A', '2', 'M', '0')
-
 HRESULT NINE_WINAPI
 NineDevice9_SetRenderState( struct NineDevice9 *This,
                             D3DRENDERSTATETYPE State,
@@ -2291,43 +2233,19 @@ NineDevice9_SetRenderState( struct NineDevice9 *This,
 
     user_assert(State < D3DRS_COUNT, D3DERR_INVALIDCALL);
 
-    if (state->rs_advertised[State] == Value && likely(!This->is_recording))
+    if (unlikely(This->is_recording)) {
+        state->rs_advertised[State] = Value;
+        /* only need to record changed render states for stateblocks */
+        state->changed.rs[State / 32] |= 1 << (State % 32);
+        state->changed.group |= nine_render_state_group[State];
         return D3D_OK;
-
-    state->rs_advertised[State] = Value;
-
-    /* Amd hacks (equivalent to GL extensions) */
-    if (unlikely(State == D3DRS_POINTSIZE)) {
-        if (Value == RESZ_CODE)
-            return NineDevice9_ResolveZ(This);
-
-        if (Value == ALPHA_TO_COVERAGE_ENABLE ||
-            Value == ALPHA_TO_COVERAGE_DISABLE) {
-            state->rs[NINED3DRS_ALPHACOVERAGE] = (Value == ALPHA_TO_COVERAGE_ENABLE);
-            state->changed.group |= NINE_STATE_BLEND;
-            return D3D_OK;
-        }
     }
 
-    /* NV hack */
-    if (unlikely(State == D3DRS_ADAPTIVETESS_Y)) {
-        if (Value == D3DFMT_ATOC || (Value == D3DFMT_UNKNOWN && state->rs[NINED3DRS_ALPHACOVERAGE])) {
-            state->rs[NINED3DRS_ALPHACOVERAGE] = (Value == D3DFMT_ATOC) ? 3 : 0;
-            state->rs[NINED3DRS_ALPHACOVERAGE] &= state->rs[D3DRS_ALPHATESTENABLE] ? 3 : 2;
-            state->changed.group |= NINE_STATE_BLEND;
-            return D3D_OK;
-        }
-    }
-    if (unlikely(State == D3DRS_ALPHATESTENABLE && (state->rs[NINED3DRS_ALPHACOVERAGE] & 2))) {
-        DWORD alphacoverage_prev = state->rs[NINED3DRS_ALPHACOVERAGE];
-        state->rs[NINED3DRS_ALPHACOVERAGE] = (Value ? 3 : 2);
-        if (state->rs[NINED3DRS_ALPHACOVERAGE] != alphacoverage_prev)
-            state->changed.group |= NINE_STATE_BLEND;
-    }
+    if (state->rs_advertised[State] == Value)
+        return D3D_OK;
 
-    state->rs[State] = nine_fix_render_state_value(State, Value);
-    state->changed.rs[State / 32] |= 1 << (State % 32);
-    state->changed.group |= nine_render_state_group[State];
+    state->rs_advertised[State] = Value;
+    nine_context_set_render_state(This, State, Value);
 
     return D3D_OK;
 }
@@ -2717,7 +2635,7 @@ NineDevice9_ValidateDevice( struct NineDevice9 *This,
         }
     }
     if (state->ds &&
-        (state->rs[D3DRS_ZENABLE] || state->rs[D3DRS_STENCILENABLE])) {
+        (state->rs_advertised[D3DRS_ZENABLE] || state->rs_advertised[D3DRS_STENCILENABLE])) {
         if (w != 0 &&
             (state->ds->desc.Width != w || state->ds->desc.Height != h))
             return D3DERR_CONFLICTINGRENDERSTATE;
@@ -2821,44 +2739,16 @@ NineDevice9_GetNPatchMode( struct NineDevice9 *This )
     STUB(0);
 }
 
-static inline void
-init_draw_info(struct pipe_draw_info *info,
-               struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count)
-{
-    info->mode = d3dprimitivetype_to_pipe_prim(type);
-    info->count = prim_count_to_vertex_count(type, count);
-    info->start_instance = 0;
-    info->instance_count = 1;
-    if (dev->state.stream_instancedata_mask & dev->state.stream_usage_mask)
-        info->instance_count = MAX2(dev->state.stream_freq[0] & 0x7FFFFF, 1);
-    info->primitive_restart = FALSE;
-    info->restart_index = 0;
-    info->count_from_stream_output = NULL;
-    info->indirect = NULL;
-    info->indirect_params = NULL;
-}
-
 HRESULT NINE_WINAPI
 NineDevice9_DrawPrimitive( struct NineDevice9 *This,
                            D3DPRIMITIVETYPE PrimitiveType,
                            UINT StartVertex,
                            UINT PrimitiveCount )
 {
-    struct pipe_draw_info info;
-
     DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
         This, PrimitiveType, StartVertex, PrimitiveCount);
 
-    nine_update_state(This);
-
-    init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
-    info.indexed = FALSE;
-    info.start = StartVertex;
-    info.index_bias = 0;
-    info.min_index = info.start;
-    info.max_index = info.count - 1;
-
-    This->pipe->draw_vbo(This->pipe, &info);
+    nine_context_draw_primitive(This, PrimitiveType, StartVertex, PrimitiveCount);
 
     return D3D_OK;
 }
@@ -2872,8 +2762,6 @@ NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,
                                   UINT StartIndex,
                                   UINT PrimitiveCount )
 {
-    struct pipe_draw_info info;
-
     DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "
         "NumVertices %u, StartIndex %u, PrimitiveCount %u\n",
         This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices,
@@ -2882,17 +2770,9 @@ NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,
     user_assert(This->state.idxbuf, D3DERR_INVALIDCALL);
     user_assert(This->state.vdecl, D3DERR_INVALIDCALL);
 
-    nine_update_state(This);
-
-    init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
-    info.indexed = TRUE;
-    info.start = StartIndex;
-    info.index_bias = BaseVertexIndex;
-    /* These don't include index bias: */
-    info.min_index = MinVertexIndex;
-    info.max_index = MinVertexIndex + NumVertices - 1;
-
-    This->pipe->draw_vbo(This->pipe, &info);
+    nine_context_draw_indexed_primitive(This, PrimitiveType, BaseVertexIndex,
+                                        MinVertexIndex, NumVertices, StartIndex,
+                                        PrimitiveCount);
 
     return D3D_OK;
 }
@@ -2905,7 +2785,6 @@ NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
                              UINT VertexStreamZeroStride )
 {
     struct pipe_vertex_buffer vtxbuf;
-    struct pipe_draw_info info;
 
     DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",
         This, PrimitiveType, PrimitiveCount,
@@ -2915,15 +2794,6 @@ NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
                 D3DERR_INVALIDCALL);
     user_assert(PrimitiveCount, D3D_OK);
 
-    nine_update_state(This);
-
-    init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
-    info.indexed = FALSE;
-    info.start = 0;
-    info.index_bias = 0;
-    info.min_index = 0;
-    info.max_index = info.count - 1;
-
     vtxbuf.stride = VertexStreamZeroStride;
     vtxbuf.buffer_offset = 0;
     vtxbuf.buffer = NULL;
@@ -2932,7 +2802,7 @@ NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
     if (!This->driver_caps.user_vbufs) {
         u_upload_data(This->vertex_uploader,
                       0,
-                      (info.max_index + 1) * VertexStreamZeroStride, /* XXX */
+                      (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * VertexStreamZeroStride, /* XXX */
                       4,
                       vtxbuf.user_buffer,
                       &vtxbuf.buffer_offset,
@@ -2941,16 +2811,12 @@ NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
         vtxbuf.user_buffer = NULL;
     }
 
-    This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vtxbuf);
-
-    This->pipe->draw_vbo(This->pipe, &info);
+    nine_context_draw_primitive_from_vtxbuf(This, PrimitiveType, PrimitiveCount, &vtxbuf);
 
     NineDevice9_PauseRecording(This);
     NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
     NineDevice9_ResumeRecording(This);
 
-    pipe_resource_reference(&vtxbuf.buffer, NULL);
-
     return D3D_OK;
 }
 
@@ -2965,7 +2831,6 @@ NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
                                     const void *pVertexStreamZeroData,
                                     UINT VertexStreamZeroStride )
 {
-    struct pipe_draw_info info;
     struct pipe_vertex_buffer vbuf;
     struct pipe_index_buffer ibuf;
 
@@ -2982,15 +2847,6 @@ NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
                 IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL);
     user_assert(PrimitiveCount, D3D_OK);
 
-    nine_update_state(This);
-
-    init_draw_info(&info, This, PrimitiveType, PrimitiveCount);
-    info.indexed = TRUE;
-    info.start = 0;
-    info.index_bias = 0;
-    info.min_index = MinVertexIndex;
-    info.max_index = MinVertexIndex + NumVertices - 1;
-
     vbuf.stride = VertexStreamZeroStride;
     vbuf.buffer_offset = 0;
     vbuf.buffer = NULL;
@@ -3002,11 +2858,10 @@ NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
     ibuf.user_buffer = pIndexData;
 
     if (!This->driver_caps.user_vbufs) {
-        const unsigned base = info.min_index * VertexStreamZeroStride;
+        const unsigned base = MinVertexIndex * VertexStreamZeroStride;
         u_upload_data(This->vertex_uploader,
                       base,
-                      (info.max_index -
-                       info.min_index + 1) * VertexStreamZeroStride, /* XXX */
+                      NumVertices * VertexStreamZeroStride, /* XXX */
                       4,
                       (const uint8_t *)vbuf.user_buffer + base,
                       &vbuf.buffer_offset,
@@ -3019,7 +2874,7 @@ NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
     if (!This->driver_caps.user_ibufs) {
         u_upload_data(This->index_uploader,
                       0,
-                      info.count * ibuf.index_size,
+                      (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * ibuf.index_size,
                       4,
                       ibuf.user_buffer,
                       &ibuf.offset,
@@ -3028,13 +2883,12 @@ NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
         ibuf.user_buffer = NULL;
     }
 
-    This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vbuf);
-    This->pipe->set_index_buffer(This->pipe, &ibuf);
-
-    This->pipe->draw_vbo(This->pipe, &info);
-
-    pipe_resource_reference(&vbuf.buffer, NULL);
-    pipe_resource_reference(&ibuf.buffer, NULL);
+    nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(This, PrimitiveType,
+                                                           MinVertexIndex,
+                                                           NumVertices,
+                                                           PrimitiveCount,
+                                                           &vbuf,
+                                                           &ibuf);
 
     NineDevice9_PauseRecording(This);
     NineDevice9_SetIndices(This, NULL);
@@ -3139,7 +2993,14 @@ NineDevice9_ProcessVertices( struct NineDevice9 *This,
         return D3DERR_DRIVERINTERNALERROR;
     }
 
-    init_draw_info(&draw, This, D3DPT_POINTLIST, VertexCount);
+    draw.mode = PIPE_PRIM_POINTS;
+    draw.count = VertexCount;
+    draw.start_instance = 0;
+    draw.primitive_restart = FALSE;
+    draw.restart_index = 0;
+    draw.count_from_stream_output = NULL;
+    draw.indirect = NULL;
+    draw.indirect_params = NULL;
     draw.instance_count = 1;
     draw.indexed = FALSE;
     draw.start = 0;
diff --git a/src/gallium/state_trackers/nine/nine_ff.c b/src/gallium/state_trackers/nine/nine_ff.c
index b9ce1b6..c01db01 100644
--- a/src/gallium/state_trackers/nine/nine_ff.c
+++ b/src/gallium/state_trackers/nine/nine_ff.c
@@ -1559,6 +1559,7 @@ static struct NineVertexShader9 *
 nine_ff_get_vs(struct NineDevice9 *device)
 {
     const struct nine_state *state = &device->state;
+    const struct nine_context *context = &device->context;
     struct NineVertexShader9 *vs;
     enum pipe_error err;
     struct vs_build_ctx bld;
@@ -1616,34 +1617,34 @@ nine_ff_get_vs(struct NineDevice9 *device)
                          (1 << NINE_DECLUSAGE_TESSFACTOR) | (1 << NINE_DECLUSAGE_SAMPLE));
     if (!key.position_t)
         key.passthrough = 0;
-    key.pointscale = !!state->rs[D3DRS_POINTSCALEENABLE];
+    key.pointscale = !!context->rs[D3DRS_POINTSCALEENABLE];
 
-    key.lighting = !!state->rs[D3DRS_LIGHTING] &&  state->ff.num_lights_active;
-    key.darkness = !!state->rs[D3DRS_LIGHTING] && !state->ff.num_lights_active;
+    key.lighting = !!context->rs[D3DRS_LIGHTING] &&  state->ff.num_lights_active;
+    key.darkness = !!context->rs[D3DRS_LIGHTING] && !state->ff.num_lights_active;
     if (key.position_t) {
         key.darkness = 0; /* |= key.lighting; */ /* XXX ? */
         key.lighting = 0;
     }
-    if ((key.lighting | key.darkness) && state->rs[D3DRS_COLORVERTEX]) {
+    if ((key.lighting | key.darkness) && context->rs[D3DRS_COLORVERTEX]) {
         uint32_t mask = (key.color0in_one ? 0 : 1) | (key.color1in_zero ? 0 : 2);
-        key.mtl_diffuse = state->rs[D3DRS_DIFFUSEMATERIALSOURCE] & mask;
-        key.mtl_ambient = state->rs[D3DRS_AMBIENTMATERIALSOURCE] & mask;
-        key.mtl_specular = state->rs[D3DRS_SPECULARMATERIALSOURCE] & mask;
-        key.mtl_emissive = state->rs[D3DRS_EMISSIVEMATERIALSOURCE] & mask;
+        key.mtl_diffuse = context->rs[D3DRS_DIFFUSEMATERIALSOURCE] & mask;
+        key.mtl_ambient = context->rs[D3DRS_AMBIENTMATERIALSOURCE] & mask;
+        key.mtl_specular = context->rs[D3DRS_SPECULARMATERIALSOURCE] & mask;
+        key.mtl_emissive = context->rs[D3DRS_EMISSIVEMATERIALSOURCE] & mask;
     }
-    key.fog = !!state->rs[D3DRS_FOGENABLE];
-    key.fog_mode = (!key.position_t && state->rs[D3DRS_FOGENABLE]) ? state->rs[D3DRS_FOGVERTEXMODE] : 0;
+    key.fog = !!context->rs[D3DRS_FOGENABLE];
+    key.fog_mode = (!key.position_t && context->rs[D3DRS_FOGENABLE]) ? context->rs[D3DRS_FOGVERTEXMODE] : 0;
     if (key.fog_mode)
-        key.fog_range = state->rs[D3DRS_RANGEFOGENABLE];
+        key.fog_range = context->rs[D3DRS_RANGEFOGENABLE];
 
-    key.localviewer = !!state->rs[D3DRS_LOCALVIEWER];
-    key.normalizenormals = !!state->rs[D3DRS_NORMALIZENORMALS];
-    key.ucp = !!state->rs[D3DRS_CLIPPLANEENABLE];
+    key.localviewer = !!context->rs[D3DRS_LOCALVIEWER];
+    key.normalizenormals = !!context->rs[D3DRS_NORMALIZENORMALS];
+    key.ucp = !!context->rs[D3DRS_CLIPPLANEENABLE];
 
-    if (state->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) {
-        key.vertexblend_indexed = !!state->rs[D3DRS_INDEXEDVERTEXBLENDENABLE] && has_indexes;
+    if (context->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) {
+        key.vertexblend_indexed = !!context->rs[D3DRS_INDEXEDVERTEXBLENDENABLE] && has_indexes;
 
-        switch (state->rs[D3DRS_VERTEXBLEND]) {
+        switch (context->rs[D3DRS_VERTEXBLEND]) {
         case D3DVBF_0WEIGHTS: key.vertexblend = key.vertexblend_indexed; break;
         case D3DVBF_1WEIGHTS: key.vertexblend = 2; break;
         case D3DVBF_2WEIGHTS: key.vertexblend = 3; break;
@@ -1653,7 +1654,7 @@ nine_ff_get_vs(struct NineDevice9 *device)
             assert(!"invalid D3DVBF");
             break;
         }
-        if (!has_weights && state->rs[D3DRS_VERTEXBLEND] != D3DVBF_0WEIGHTS)
+        if (!has_weights && context->rs[D3DRS_VERTEXBLEND] != D3DVBF_0WEIGHTS)
             key.vertexblend = 0; /* TODO: if key.vertexblend_indexed, perhaps it should use 1.0 as weight, or revert to D3DVBF_0WEIGHTS */
     }
 
@@ -1714,6 +1715,7 @@ static struct NinePixelShader9 *
 nine_ff_get_ps(struct NineDevice9 *device)
 {
     struct nine_state *state = &device->state;
+    struct nine_context *context = &device->context;
     D3DMATRIX *projection_matrix = GET_D3DTS(PROJECTION);
     struct NinePixelShader9 *ps;
     enum pipe_error err;
@@ -1817,13 +1819,13 @@ nine_ff_get_ps(struct NineDevice9 *device)
         key.ts[s-1].resultarg = 0;
 
     key.projected = nine_ff_get_projected_key(state);
-    key.specular = !!state->rs[D3DRS_SPECULARENABLE];
+    key.specular = !!context->rs[D3DRS_SPECULARENABLE];
 
     for (; s < 8; ++s)
         key.ts[s].colorop = key.ts[s].alphaop = D3DTOP_DISABLE;
-    if (state->rs[D3DRS_FOGENABLE])
-        key.fog_mode = state->rs[D3DRS_FOGTABLEMODE];
-    key.fog = !!state->rs[D3DRS_FOGENABLE];
+    if (context->rs[D3DRS_FOGENABLE])
+        key.fog_mode = context->rs[D3DRS_FOGTABLEMODE];
+    key.fog = !!context->rs[D3DRS_FOGENABLE];
     /* Pixel fog (with WFOG advertised): source is either Z or W.
      * W is the source if vs ff is used, and the
      * projection matrix is not orthogonal.
@@ -1859,6 +1861,7 @@ static void
 nine_ff_load_vs_transforms(struct NineDevice9 *device)
 {
     struct nine_state *state = &device->state;
+    struct nine_context *context = &device->context;
     D3DMATRIX T;
     D3DMATRIX *M = (D3DMATRIX *)device->ff.vs_const;
     unsigned i;
@@ -1885,20 +1888,21 @@ nine_ff_load_vs_transforms(struct NineDevice9 *device)
         M[40] = M[1];
     }
 
-    if (state->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) {
+    if (context->rs[D3DRS_VERTEXBLEND] != D3DVBF_DISABLE) {
         /* load other world matrices */
         for (i = 1; i <= 8; ++i) {
             nine_d3d_matrix_matrix_mul(&M[40 + i], GET_D3DTS(WORLDMATRIX(i)), GET_D3DTS(VIEW));
         }
     }
 
-    device->ff.vs_const[30 * 4] = asfloat(state->rs[D3DRS_TWEENFACTOR]);
+    device->ff.vs_const[30 * 4] = asfloat(context->rs[D3DRS_TWEENFACTOR]);
 }
 
 static void
 nine_ff_load_lights(struct NineDevice9 *device)
 {
     struct nine_state *state = &device->state;
+    struct nine_context *context = &device->context;
     struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const;
     unsigned l;
 
@@ -1910,7 +1914,7 @@ nine_ff_load_lights(struct NineDevice9 *device)
         memcpy(&dst[22], &mtl->Specular, 4 * sizeof(float));
         dst[23].x = mtl->Power;
         memcpy(&dst[24], &mtl->Emissive, 4 * sizeof(float));
-        d3dcolor_to_rgba(&dst[25].x, state->rs[D3DRS_AMBIENT]);
+        d3dcolor_to_rgba(&dst[25].x, context->rs[D3DRS_AMBIENT]);
         dst[19].x = dst[25].x * mtl->Ambient.r + mtl->Emissive.r;
         dst[19].y = dst[25].y * mtl->Ambient.g + mtl->Emissive.g;
         dst[19].z = dst[25].z * mtl->Ambient.b + mtl->Emissive.b;
@@ -1944,21 +1948,22 @@ static void
 nine_ff_load_point_and_fog_params(struct NineDevice9 *device)
 {
     const struct nine_state *state = &device->state;
+    struct nine_context *context = &device->context;
     struct fvec4 *dst = (struct fvec4 *)device->ff.vs_const;
 
     if (!(state->changed.group & NINE_STATE_FF_OTHER))
         return;
-    dst[26].x = asfloat(state->rs[D3DRS_POINTSIZE_MIN]);
-    dst[26].y = asfloat(state->rs[D3DRS_POINTSIZE_MAX]);
-    dst[26].z = asfloat(state->rs[D3DRS_POINTSIZE]);
-    dst[26].w = asfloat(state->rs[D3DRS_POINTSCALE_A]);
-    dst[27].x = asfloat(state->rs[D3DRS_POINTSCALE_B]);
-    dst[27].y = asfloat(state->rs[D3DRS_POINTSCALE_C]);
-    dst[28].x = asfloat(state->rs[D3DRS_FOGEND]);
-    dst[28].y = 1.0f / (asfloat(state->rs[D3DRS_FOGEND]) - asfloat(state->rs[D3DRS_FOGSTART]));
+    dst[26].x = asfloat(context->rs[D3DRS_POINTSIZE_MIN]);
+    dst[26].y = asfloat(context->rs[D3DRS_POINTSIZE_MAX]);
+    dst[26].z = asfloat(context->rs[D3DRS_POINTSIZE]);
+    dst[26].w = asfloat(context->rs[D3DRS_POINTSCALE_A]);
+    dst[27].x = asfloat(context->rs[D3DRS_POINTSCALE_B]);
+    dst[27].y = asfloat(context->rs[D3DRS_POINTSCALE_C]);
+    dst[28].x = asfloat(context->rs[D3DRS_FOGEND]);
+    dst[28].y = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART]));
     if (isinf(dst[28].y))
         dst[28].y = 0.0f;
-    dst[28].z = asfloat(state->rs[D3DRS_FOGDENSITY]);
+    dst[28].z = asfloat(context->rs[D3DRS_FOGDENSITY]);
 }
 
 static void
@@ -1980,6 +1985,7 @@ static void
 nine_ff_load_ps_params(struct NineDevice9 *device)
 {
     const struct nine_state *state = &device->state;
+    struct nine_context *context = &device->context;
     struct fvec4 *dst = (struct fvec4 *)device->ff.ps_const;
     unsigned s;
 
@@ -2003,11 +2009,11 @@ nine_ff_load_ps_params(struct NineDevice9 *device)
         }
     }
 
-    d3dcolor_to_rgba(&dst[20].x, state->rs[D3DRS_TEXTUREFACTOR]);
-    d3dcolor_to_rgba(&dst[21].x, state->rs[D3DRS_FOGCOLOR]);
-    dst[22].x = asfloat(state->rs[D3DRS_FOGEND]);
-    dst[22].y = 1.0f / (asfloat(state->rs[D3DRS_FOGEND]) - asfloat(state->rs[D3DRS_FOGSTART]));
-    dst[22].z = asfloat(state->rs[D3DRS_FOGDENSITY]);
+    d3dcolor_to_rgba(&dst[20].x, context->rs[D3DRS_TEXTUREFACTOR]);
+    d3dcolor_to_rgba(&dst[21].x, context->rs[D3DRS_FOGCOLOR]);
+    dst[22].x = asfloat(context->rs[D3DRS_FOGEND]);
+    dst[22].y = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART]));
+    dst[22].z = asfloat(context->rs[D3DRS_FOGDENSITY]);
 }
 
 static void
diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c
index 46b301d..b99be2c 100644
--- a/src/gallium/state_trackers/nine/nine_state.c
+++ b/src/gallium/state_trackers/nine/nine_state.c
@@ -32,6 +32,7 @@
 #include "pixelshader9.h"
 #include "nine_pipe.h"
 #include "nine_ff.h"
+#include "nine_limits.h"
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
 #include "cso_cache/cso_context.h"
@@ -47,7 +48,7 @@
 static inline DWORD
 check_multisample(struct NineDevice9 *device)
 {
-    DWORD *rs = device->state.rs;
+    DWORD *rs = device->context.rs;
     DWORD new_value = (rs[D3DRS_ZENABLE] || rs[D3DRS_STENCILENABLE]) &&
                       device->state.rt[0]->desc.MultiSampleType >= 1 &&
                       rs[D3DRS_MULTISAMPLEANTIALIAS];
@@ -63,21 +64,21 @@ check_multisample(struct NineDevice9 *device)
 static inline void
 prepare_blend(struct NineDevice9 *device)
 {
-    nine_convert_blend_state(&device->context.pipe.blend, device->state.rs);
+    nine_convert_blend_state(&device->context.pipe.blend, device->context.rs);
     device->context.commit |= NINE_STATE_COMMIT_BLEND;
 }
 
 static inline void
 prepare_dsa(struct NineDevice9 *device)
 {
-    nine_convert_dsa_state(&device->context.pipe.dsa, device->state.rs);
+    nine_convert_dsa_state(&device->context.pipe.dsa, device->context.rs);
     device->context.commit |= NINE_STATE_COMMIT_DSA;
 }
 
 static inline void
 prepare_rasterizer(struct NineDevice9 *device)
 {
-    nine_convert_rasterizer_state(device, &device->context.pipe.rast, device->state.rs);
+    nine_convert_rasterizer_state(device, &device->context.pipe.rast, device->context.rs);
     device->context.commit |= NINE_STATE_COMMIT_RASTERIZER;
 }
 
@@ -350,19 +351,19 @@ prepare_ps_constants_userbuf(struct NineDevice9 *device)
     }
 
     if (state->ps->byte_code.version < 0x30 &&
-        state->rs[D3DRS_FOGENABLE]) {
+        context->rs[D3DRS_FOGENABLE]) {
         float *dst = &state->ps_lconstf_temp[4 * 32];
         if (cb.user_buffer != state->ps_lconstf_temp) {
             memcpy(state->ps_lconstf_temp, cb.user_buffer, cb.buffer_size);
             cb.user_buffer = state->ps_lconstf_temp;
         }
 
-        d3dcolor_to_rgba(dst, state->rs[D3DRS_FOGCOLOR]);
-        if (state->rs[D3DRS_FOGTABLEMODE] == D3DFOG_LINEAR) {
-            dst[4] = asfloat(state->rs[D3DRS_FOGEND]);
-            dst[5] = 1.0f / (asfloat(state->rs[D3DRS_FOGEND]) - asfloat(state->rs[D3DRS_FOGSTART]));
-        } else if (state->rs[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
-            dst[4] = asfloat(state->rs[D3DRS_FOGDENSITY]);
+        d3dcolor_to_rgba(dst, context->rs[D3DRS_FOGCOLOR]);
+        if (context->rs[D3DRS_FOGTABLEMODE] == D3DFOG_LINEAR) {
+            dst[4] = asfloat(context->rs[D3DRS_FOGEND]);
+            dst[5] = 1.0f / (asfloat(context->rs[D3DRS_FOGEND]) - asfloat(context->rs[D3DRS_FOGSTART]));
+        } else if (context->rs[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
+            dst[4] = asfloat(context->rs[D3DRS_FOGDENSITY]);
         }
         cb.buffer_size = 4 * 4 * 34;
     }
@@ -419,8 +420,8 @@ prepare_vs(struct NineDevice9 *device, uint8_t shader_changed)
         context->cso.vs = vs->ff_cso;
     }
 
-    if (state->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) {
-        state->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size;
+    if (context->rs[NINED3DRS_VSPOINTSIZE] != vs->point_size) {
+        context->rs[NINED3DRS_VSPOINTSIZE] = vs->point_size;
         changed_group |= NINE_STATE_RASTERIZER;
     }
 
@@ -442,7 +443,7 @@ prepare_ps(struct NineDevice9 *device, uint8_t shader_changed)
     int has_key_changed = 0;
 
     if (likely(ps))
-        has_key_changed = NinePixelShader9_UpdateKey(ps, state);
+        has_key_changed = NinePixelShader9_UpdateKey(ps, state, context);
 
     if (!shader_changed && !has_key_changed)
         return 0;
@@ -480,7 +481,7 @@ update_framebuffer(struct NineDevice9 *device, bool is_clear)
     unsigned nr_samples = rt0->base.info.nr_samples;
     unsigned ps_mask = state->ps ? state->ps->rt_mask : 1;
     unsigned mask = is_clear ? 0xf : ps_mask;
-    const int sRGB = state->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
+    const int sRGB = context->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
 
     DBG("\n");
 
@@ -1006,7 +1007,7 @@ update_managed_buffers(struct NineDevice9 *device)
     }
 }
 
-boolean
+static void
 nine_update_state(struct NineDevice9 *device)
 {
     struct pipe_context *pipe = device->pipe;
@@ -1095,19 +1096,19 @@ nine_update_state(struct NineDevice9 *device)
             commit_scissor(device);
         if (group & NINE_STATE_BLEND_COLOR) {
             struct pipe_blend_color color;
-            d3dcolor_to_rgba(&color.color[0], state->rs[D3DRS_BLENDFACTOR]);
+            d3dcolor_to_rgba(&color.color[0], context->rs[D3DRS_BLENDFACTOR]);
             pipe->set_blend_color(pipe, &color);
         }
         if (group & NINE_STATE_SAMPLE_MASK) {
             if (state->rt[0]->desc.MultiSampleType <= D3DMULTISAMPLE_NONMASKABLE) {
                 pipe->set_sample_mask(pipe, ~0);
             } else {
-                pipe->set_sample_mask(pipe, state->rs[D3DRS_MULTISAMPLEMASK]);
+                pipe->set_sample_mask(pipe, context->rs[D3DRS_MULTISAMPLEMASK]);
             }
         }
         if (group & NINE_STATE_STENCIL_REF) {
             struct pipe_stencil_ref ref;
-            ref.ref_value[0] = state->rs[D3DRS_STENCILREF];
+            ref.ref_value[0] = context->rs[D3DRS_STENCILREF];
             ref.ref_value[1] = ref.ref_value[0];
             pipe->set_stencil_ref(pipe, &ref);
         }
@@ -1117,8 +1118,126 @@ nine_update_state(struct NineDevice9 *device)
         (NINE_STATE_FF | NINE_STATE_VS_CONST | NINE_STATE_PS_CONST);
 
     DBG("finished\n");
+}
+
+#define RESZ_CODE 0x7fa05000
+
+static void
+NineDevice9_ResolveZ( struct NineDevice9 *device )
+{
+    struct nine_state *state = &device->state;
+    const struct util_format_description *desc;
+    struct NineSurface9 *source = state->ds;
+    struct NineBaseTexture9 *destination = state->texture[0];
+    struct pipe_resource *src, *dst;
+    struct pipe_blit_info blit;
+
+    DBG("RESZ resolve\n");
+
+    if (!source || !destination ||
+        destination->base.type != D3DRTYPE_TEXTURE)
+        return;
 
-    return TRUE;
+    src = source->base.resource;
+    dst = destination->base.resource;
+
+    if (!src || !dst)
+        return;
+
+    /* check dst is depth format. we know already for src */
+    desc = util_format_description(dst->format);
+    if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
+        return;
+
+    memset(&blit, 0, sizeof(blit));
+    blit.src.resource = src;
+    blit.src.level = 0;
+    blit.src.format = src->format;
+    blit.src.box.z = 0;
+    blit.src.box.depth = 1;
+    blit.src.box.x = 0;
+    blit.src.box.y = 0;
+    blit.src.box.width = src->width0;
+    blit.src.box.height = src->height0;
+
+    blit.dst.resource = dst;
+    blit.dst.level = 0;
+    blit.dst.format = dst->format;
+    blit.dst.box.z = 0;
+    blit.dst.box.depth = 1;
+    blit.dst.box.x = 0;
+    blit.dst.box.y = 0;
+    blit.dst.box.width = dst->width0;
+    blit.dst.box.height = dst->height0;
+
+    blit.mask = PIPE_MASK_ZS;
+    blit.filter = PIPE_TEX_FILTER_NEAREST;
+    blit.scissor_enable = FALSE;
+
+    device->pipe->blit(device->pipe, &blit);
+}
+
+#define ALPHA_TO_COVERAGE_ENABLE   MAKEFOURCC('A', '2', 'M', '1')
+#define ALPHA_TO_COVERAGE_DISABLE  MAKEFOURCC('A', '2', 'M', '0')
+
+
+void
+nine_context_set_render_state(struct NineDevice9 *device,
+                              D3DRENDERSTATETYPE State,
+                              DWORD Value)
+{
+    struct nine_state *state = &device->state;
+    struct nine_context *context = &device->context;
+
+    /* Amd hacks (equivalent to GL extensions) */
+    if (unlikely(State == D3DRS_POINTSIZE)) {
+        if (Value == RESZ_CODE) {
+            NineDevice9_ResolveZ(device);
+            return;
+        }
+
+        if (Value == ALPHA_TO_COVERAGE_ENABLE ||
+            Value == ALPHA_TO_COVERAGE_DISABLE) {
+            context->rs[NINED3DRS_ALPHACOVERAGE] = (Value == ALPHA_TO_COVERAGE_ENABLE);
+            state->changed.group |= NINE_STATE_BLEND;
+            return;
+        }
+    }
+
+    /* NV hack */
+    if (unlikely(State == D3DRS_ADAPTIVETESS_Y)) {
+        if (Value == D3DFMT_ATOC || (Value == D3DFMT_UNKNOWN && context->rs[NINED3DRS_ALPHACOVERAGE])) {
+            context->rs[NINED3DRS_ALPHACOVERAGE] = (Value == D3DFMT_ATOC) ? 3 : 0;
+            context->rs[NINED3DRS_ALPHACOVERAGE] &= context->rs[D3DRS_ALPHATESTENABLE] ? 3 : 2;
+            state->changed.group |= NINE_STATE_BLEND;
+            return;
+        }
+    }
+    if (unlikely(State == D3DRS_ALPHATESTENABLE && (context->rs[NINED3DRS_ALPHACOVERAGE] & 2))) {
+        DWORD alphacoverage_prev = context->rs[NINED3DRS_ALPHACOVERAGE];
+        context->rs[NINED3DRS_ALPHACOVERAGE] = (Value ? 3 : 2);
+        if (context->rs[NINED3DRS_ALPHACOVERAGE] != alphacoverage_prev)
+            state->changed.group |= NINE_STATE_BLEND;
+    }
+
+    context->rs[State] = nine_fix_render_state_value(State, Value);
+    state->changed.group |= nine_render_state_group[State];
+}
+
+void
+nine_context_apply_stateblock(struct nine_context *dst,
+                              const struct nine_state *src)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(src->changed.rs); ++i) {
+        uint32_t m = src->changed.rs[i];
+        while (m) {
+            const int r = ffs(m) - 1;
+            m &= ~(1 << r);
+            dst->rs[i * 32 + r] = nine_fix_render_state_value(i * 32 + r, src->rs_advertised[i * 32 + r]);
+        }
+    }
 }
 
 static void
@@ -1142,7 +1261,7 @@ nine_context_clear_fb(struct NineDevice9 *device,
               float Z,
               DWORD Stencil)
 {
-    const int sRGB = device->state.rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
+    const int sRGB = device->context.rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
     struct pipe_surface *cbuf, *zsbuf;
     struct pipe_context *pipe = device->pipe;
     struct NineSurface9 *zsbuf_surf = device->state.ds;
@@ -1171,7 +1290,7 @@ nine_context_clear_fb(struct NineDevice9 *device,
     rect.y2 = device->state.viewport.Height + rect.y1;
 
     /* Both rectangles apply, which is weird, but that's D3D9. */
-    if (device->state.rs[D3DRS_SCISSORTESTENABLE]) {
+    if (device->context.rs[D3DRS_SCISSORTESTENABLE]) {
         rect.x1 = MAX2(rect.x1, device->state.scissor.minx);
         rect.y1 = MAX2(rect.y1, device->state.scissor.miny);
         rect.x2 = MIN2(rect.x2, device->state.scissor.maxx);
@@ -1276,6 +1395,120 @@ nine_context_clear_fb(struct NineDevice9 *device,
     return;
 }
 
+
+static inline void
+init_draw_info(struct pipe_draw_info *info,
+               struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count)
+{
+    info->mode = d3dprimitivetype_to_pipe_prim(type);
+    info->count = prim_count_to_vertex_count(type, count);
+    info->start_instance = 0;
+    info->instance_count = 1;
+    if (dev->state.stream_instancedata_mask & dev->state.stream_usage_mask)
+        info->instance_count = MAX2(dev->state.stream_freq[0] & 0x7FFFFF, 1);
+    info->primitive_restart = FALSE;
+    info->restart_index = 0;
+    info->count_from_stream_output = NULL;
+    info->indirect = NULL;
+    info->indirect_params = NULL;
+}
+
+void
+nine_context_draw_primitive(struct NineDevice9 *device,
+                            D3DPRIMITIVETYPE PrimitiveType,
+                            UINT StartVertex,
+                            UINT PrimitiveCount)
+{
+    struct pipe_draw_info info;
+
+    nine_update_state(device);
+
+    init_draw_info(&info, device, PrimitiveType, PrimitiveCount);
+    info.indexed = FALSE;
+    info.start = StartVertex;
+    info.index_bias = 0;
+    info.min_index = info.start;
+    info.max_index = info.count - 1;
+
+    device->pipe->draw_vbo(device->pipe, &info);
+}
+
+void
+nine_context_draw_indexed_primitive(struct NineDevice9 *device,
+                                    D3DPRIMITIVETYPE PrimitiveType,
+                                    INT BaseVertexIndex,
+                                    UINT MinVertexIndex,
+                                    UINT NumVertices,
+                                    UINT StartIndex,
+                                    UINT PrimitiveCount)
+{
+    struct pipe_draw_info info;
+
+    nine_update_state(device);
+
+    init_draw_info(&info, device, PrimitiveType, PrimitiveCount);
+    info.indexed = TRUE;
+    info.start = StartIndex;
+    info.index_bias = BaseVertexIndex;
+    /* These don't include index bias: */
+    info.min_index = MinVertexIndex;
+    info.max_index = MinVertexIndex + NumVertices - 1;
+
+    device->pipe->draw_vbo(device->pipe, &info);
+}
+
+void
+nine_context_draw_primitive_from_vtxbuf(struct NineDevice9 *device,
+                                        D3DPRIMITIVETYPE PrimitiveType,
+                                        UINT PrimitiveCount,
+                                        struct pipe_vertex_buffer *vtxbuf)
+{
+    struct pipe_draw_info info;
+
+    nine_update_state(device);
+
+    init_draw_info(&info, device, PrimitiveType, PrimitiveCount);
+    info.indexed = FALSE;
+    info.start = 0;
+    info.index_bias = 0;
+    info.min_index = 0;
+    info.max_index = info.count - 1;
+
+    device->pipe->set_vertex_buffers(device->pipe, 0, 1, vtxbuf);
+
+    device->pipe->draw_vbo(device->pipe, &info);
+
+    pipe_resource_reference(&vtxbuf->buffer, NULL);
+}
+
+void
+nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(struct NineDevice9 *device,
+                                                       D3DPRIMITIVETYPE PrimitiveType,
+                                                       UINT MinVertexIndex,
+                                                       UINT NumVertices,
+                                                       UINT PrimitiveCount,
+                                                       struct pipe_vertex_buffer *vbuf,
+                                                       struct pipe_index_buffer *ibuf)
+{
+    struct pipe_draw_info info;
+
+    nine_update_state(device);
+
+    init_draw_info(&info, device, PrimitiveType, PrimitiveCount);
+    info.indexed = TRUE;
+    info.start = 0;
+    info.index_bias = 0;
+    info.min_index = MinVertexIndex;
+    info.max_index = MinVertexIndex + NumVertices - 1;
+    device->pipe->set_vertex_buffers(device->pipe, 0, 1, vbuf);
+    device->pipe->set_index_buffer(device->pipe, ibuf);
+
+    device->pipe->draw_vbo(device->pipe, &info);
+
+    pipe_resource_reference(&vbuf->buffer, NULL);
+    pipe_resource_reference(&ibuf->buffer, NULL);
+}
+
 /* State defaults */
 
 static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] =
@@ -1456,7 +1689,7 @@ nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps,
 
     /* Initialize defaults.
      */
-    memcpy(state->rs, nine_render_state_defaults, sizeof(state->rs));
+    memcpy(context->rs, nine_render_state_defaults, sizeof(context->rs));
 
     for (s = 0; s < ARRAY_SIZE(state->ff.tex_stage); ++s) {
         memcpy(&state->ff.tex_stage[s], nine_tex_stage_state_defaults,
@@ -1481,9 +1714,9 @@ nine_state_set_defaults(struct NineDevice9 *device, const D3DCAPS9 *caps,
 
     /* Cap dependent initial state:
      */
-    state->rs[D3DRS_POINTSIZE_MAX] = fui(caps->MaxPointSize);
+    context->rs[D3DRS_POINTSIZE_MAX] = fui(caps->MaxPointSize);
 
-    memcpy(state->rs_advertised, state->rs, sizeof(state->rs));
+    memcpy(state->rs_advertised, context->rs, sizeof(context->rs));
 
     /* Set changed flags to initialize driver.
      */
diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h
index bb1064a..b5f4976 100644
--- a/src/gallium/state_trackers/nine/nine_state.h
+++ b/src/gallium/state_trackers/nine/nine_state.h
@@ -135,7 +135,7 @@ struct nine_state
 {
     struct {
         uint32_t group;
-        uint32_t rs[(NINED3DRS_COUNT + 31) / 32];
+        uint32_t rs[(NINED3DRS_COUNT + 31) / 32]; /* stateblocks only */
         uint32_t vtxbuf;
         uint32_t stream_freq;
         uint32_t texture;
@@ -187,7 +187,6 @@ struct nine_state
 
     struct pipe_clip_state clip;
 
-    DWORD rs[NINED3DRS_COUNT];
     DWORD rs_advertised[NINED3DRS_COUNT]; /* the ones apps get with GetRenderState */
 
     struct NineBaseTexture9 *texture[NINE_MAX_SAMPLERS]; /* PS, DMAP, VS */
@@ -228,6 +227,8 @@ struct nine_context {
 
     uint8_t rt_mask;
 
+    DWORD rs[NINED3DRS_COUNT];
+
     uint8_t bound_samplers_mask_vs;
     uint16_t bound_samplers_mask_ps;
 
@@ -266,12 +267,46 @@ extern const uint32_t nine_render_states_vertex[(NINED3DRS_COUNT + 31) / 32];
 
 struct NineDevice9;
 
-boolean nine_update_state(struct NineDevice9 *);
+void
+nine_context_set_render_state(struct NineDevice9 *device,
+                              D3DRENDERSTATETYPE State,
+                              DWORD Value);
+
 void
 nine_context_clear_fb(struct NineDevice9 *device, DWORD Count,
                       const D3DRECT *pRects, DWORD Flags,
                       D3DCOLOR Color, float Z, DWORD Stencil);
 
+void
+nine_context_draw_primitive(struct NineDevice9 *device,
+                            D3DPRIMITIVETYPE PrimitiveType,
+                            UINT StartVertex,
+                            UINT PrimitiveCount);
+
+void
+nine_context_draw_indexed_primitive(struct NineDevice9 *device,
+                                    D3DPRIMITIVETYPE PrimitiveType,
+                                    INT BaseVertexIndex,
+                                    UINT MinVertexIndex,
+                                    UINT NumVertices,
+                                    UINT StartIndex,
+                                    UINT PrimitiveCount);
+
+void
+nine_context_draw_primitive_from_vtxbuf(struct NineDevice9 *device,
+                                        D3DPRIMITIVETYPE PrimitiveType,
+                                        UINT PrimitiveCount,
+                                        struct pipe_vertex_buffer *vtxbuf);
+
+void
+nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(struct NineDevice9 *device,
+                                                       D3DPRIMITIVETYPE PrimitiveType,
+                                                       UINT MinVertexIndex,
+                                                       UINT NumVertices,
+                                                       UINT PrimitiveCount,
+                                                       struct pipe_vertex_buffer *vbuf,
+                                                       struct pipe_index_buffer *ibuf);
+
 void nine_state_restore_non_cso(struct NineDevice9 *device);
 void nine_state_set_defaults(struct NineDevice9 *, const D3DCAPS9 *,
                              boolean is_reset);
diff --git a/src/gallium/state_trackers/nine/pixelshader9.c b/src/gallium/state_trackers/nine/pixelshader9.c
index d34b7b1..133f0da 100644
--- a/src/gallium/state_trackers/nine/pixelshader9.c
+++ b/src/gallium/state_trackers/nine/pixelshader9.c
@@ -159,8 +159,8 @@ NinePixelShader9_GetVariant( struct NinePixelShader9 *This )
         info.byte_code = This->byte_code.tokens;
         info.sampler_mask_shadow = key & 0xffff;
         info.sampler_ps1xtypes = key;
-        info.fog_enable = device->state.rs[D3DRS_FOGENABLE];
-        info.fog_mode = device->state.rs[D3DRS_FOGTABLEMODE];
+        info.fog_enable = device->context.rs[D3DRS_FOGENABLE];
+        info.fog_mode = device->context.rs[D3DRS_FOGTABLEMODE];
         info.force_color_in_centroid = key >> 34 & 1;
         info.projected = (key >> 48) & 0xffff;
         info.process_vertices = false;
diff --git a/src/gallium/state_trackers/nine/pixelshader9.h b/src/gallium/state_trackers/nine/pixelshader9.h
index 9ff3d51..bc52cc7 100644
--- a/src/gallium/state_trackers/nine/pixelshader9.h
+++ b/src/gallium/state_trackers/nine/pixelshader9.h
@@ -65,7 +65,8 @@ NinePixelShader9( void *data )
 
 static inline BOOL
 NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps,
-                            struct nine_state *state )
+                            struct nine_state *state,
+                            struct nine_context *context )
 {
     uint16_t samplers_shadow;
     uint32_t samplers_ps1_types;
@@ -89,8 +90,8 @@ NinePixelShader9_UpdateKey( struct NinePixelShader9 *ps,
     }
 
     if (ps->byte_code.version < 0x30) {
-        key |= ((uint64_t)state->rs[D3DRS_FOGENABLE]) << 32;
-        key |= ((uint64_t)state->rs[D3DRS_FOGTABLEMODE]) << 33;
+        key |= ((uint64_t)context->rs[D3DRS_FOGENABLE]) << 32;
+        key |= ((uint64_t)context->rs[D3DRS_FOGTABLEMODE]) << 33;
     }
 
     /* centroid interpolation automatically used for color ps inputs */
diff --git a/src/gallium/state_trackers/nine/stateblock9.c b/src/gallium/state_trackers/nine/stateblock9.c
index fbbd41b..0a5641f 100644
--- a/src/gallium/state_trackers/nine/stateblock9.c
+++ b/src/gallium/state_trackers/nine/stateblock9.c
@@ -225,8 +225,7 @@ nine_state_copy_common(struct NineDevice9 *device,
         while (m) {
             const int r = ffs(m) - 1;
             m &= ~(1 << r);
-            dst->rs[i * 32 + r] = src->rs[i * 32 + r];
-            DBG("State %d %s = %d\n", i * 32 + r, nine_d3drs_to_string(i * 32 + r), (int)src->rs[i * 32 + r]);
+            DBG("State %d %s = %d\n", i * 32 + r, nine_d3drs_to_string(i * 32 + r), (int)src->rs_advertised[i * 32 + r]);
             dst->rs_advertised[i * 32 + r] = src->rs_advertised[i * 32 + r];
         }
     }
@@ -438,7 +437,6 @@ nine_state_copy_common_all(struct NineDevice9 *device,
     }
 
     /* Render states. */
-    memcpy(dst->rs, src->rs, sizeof(dst->rs));
     memcpy(dst->rs_advertised, src->rs_advertised, sizeof(dst->rs_advertised));
     if (apply)
         memcpy(dst->changed.rs, src->changed.rs, sizeof(dst->changed.rs));
@@ -572,6 +570,8 @@ NineStateBlock9_Apply( struct NineStateBlock9 *This )
     else
         nine_state_copy_common(device, dst, src, src, TRUE, pool);
 
+    nine_context_apply_stateblock(&device->context, src);
+
     if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl)
         NineDevice9_SetVertexDeclaration(This->base.device, (IDirect3DVertexDeclaration9 *)src->vdecl);
 
diff --git a/src/gallium/state_trackers/nine/vertexshader9.c b/src/gallium/state_trackers/nine/vertexshader9.c
index 6b053e4..b8c9ec0 100644
--- a/src/gallium/state_trackers/nine/vertexshader9.c
+++ b/src/gallium/state_trackers/nine/vertexshader9.c
@@ -186,9 +186,9 @@ NineVertexShader9_GetVariant( struct NineVertexShader9 *This )
         info.const_b_base = NINE_CONST_B_BASE(device->max_vs_const_f) / 16;
         info.byte_code = This->byte_code.tokens;
         info.sampler_mask_shadow = key & 0xf;
-        info.fog_enable = device->state.rs[D3DRS_FOGENABLE];
-        info.point_size_min = asfloat(device->state.rs[D3DRS_POINTSIZE_MIN]);
-        info.point_size_max = asfloat(device->state.rs[D3DRS_POINTSIZE_MAX]);
+        info.fog_enable = device->context.rs[D3DRS_FOGENABLE];
+        info.point_size_min = asfloat(device->context.rs[D3DRS_POINTSIZE_MIN]);
+        info.point_size_max = asfloat(device->context.rs[D3DRS_POINTSIZE_MAX]);
         info.swvp_on = device->swvp;
         info.process_vertices = false;
 
diff --git a/src/gallium/state_trackers/nine/vertexshader9.h b/src/gallium/state_trackers/nine/vertexshader9.h
index 1f0cfd6..f1d8ec1 100644
--- a/src/gallium/state_trackers/nine/vertexshader9.h
+++ b/src/gallium/state_trackers/nine/vertexshader9.h
@@ -81,6 +81,7 @@ NineVertexShader9_UpdateKey( struct NineVertexShader9 *vs,
                              struct NineDevice9 *device )
 {
     struct nine_state *state = &(device->state);
+    struct nine_context *context = &(device->context);
     uint8_t samplers_shadow;
     uint64_t key;
     BOOL res;
@@ -90,15 +91,15 @@ NineVertexShader9_UpdateKey( struct NineVertexShader9 *vs,
     key = samplers_shadow;
 
     if (vs->byte_code.version < 0x30)
-        key |= (uint32_t) ((!!state->rs[D3DRS_FOGENABLE]) << 8);
+        key |= (uint32_t) ((!!context->rs[D3DRS_FOGENABLE]) << 8);
     key |= (uint32_t) (device->swvp << 9);
 
     /* We want to use a 64 bits key for performance.
      * Use compressed float16 values for the pointsize min/max in the key.
      * Shaders do not usually output psize.*/
     if (vs->point_size) {
-        key |= ((uint64_t)util_float_to_half(asfloat(state->rs[D3DRS_POINTSIZE_MIN]))) << 32;
-        key |= ((uint64_t)util_float_to_half(asfloat(state->rs[D3DRS_POINTSIZE_MAX]))) << 48;
+        key |= ((uint64_t)util_float_to_half(asfloat(context->rs[D3DRS_POINTSIZE_MIN]))) << 32;
+        key |= ((uint64_t)util_float_to_half(asfloat(context->rs[D3DRS_POINTSIZE_MAX]))) << 48;
     }
 
     res = vs->last_key != key;
-- 
2.10.2



More information about the mesa-dev mailing list