st/nine: Fix volumetexture dtor on ctor failure
[mesa.git] / src / gallium / state_trackers / nine / stateblock9.c
index 4f5e9d7b8d3cd1fe3709648e9ca34c8ecfd5f4ec..50ed70aec3a3bae2df2710b919674b4d02829145 100644 (file)
 #include "basetexture9.h"
 #include "nine_helpers.h"
 #include "vertexdeclaration9.h"
+#include "vertexbuffer9.h"
+#include "indexbuffer9.h"
 
 #define DBG_CHANNEL DBG_STATEBLOCK
 
 /* XXX TODO: handling of lights is broken */
 
-#define VS_CONST_I_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_I_SWVP * sizeof(int[4])) : (NINE_MAX_CONST_I * sizeof(int[4])))
-#define VS_CONST_B_SIZE(device) (device->may_swvp ? (NINE_MAX_CONST_B_SWVP * sizeof(BOOL)) : (NINE_MAX_CONST_B * sizeof(BOOL)))
-#define VS_CONST_F_SWVP_SIZE    (NINE_MAX_CONST_F_SWVP * sizeof(float[4]))
-
 HRESULT
 NineStateBlock9_ctor( struct NineStateBlock9 *This,
                       struct NineUnknownParams *pParams,
@@ -48,7 +46,7 @@ NineStateBlock9_ctor( struct NineStateBlock9 *This,
 
     This->type = type;
 
-    This->state.vs_const_f = MALLOC(This->base.device->vs_const_size);
+    This->state.vs_const_f = MALLOC(VS_CONST_F_SIZE(This->base.device));
     This->state.ps_const_f = MALLOC(This->base.device->ps_const_size);
     This->state.vs_const_i = MALLOC(VS_CONST_I_SIZE(This->base.device));
     This->state.vs_const_b = MALLOC(VS_CONST_B_SIZE(This->base.device));
@@ -56,13 +54,6 @@ NineStateBlock9_ctor( struct NineStateBlock9 *This,
         !This->state.vs_const_i || !This->state.vs_const_b)
         return E_OUTOFMEMORY;
 
-    if (This->base.device->may_swvp) {
-        This->state.vs_const_f_swvp = MALLOC(VS_CONST_F_SWVP_SIZE);
-        if (!This->state.vs_const_f_swvp)
-            return E_OUTOFMEMORY;
-    } else
-        This->state.vs_const_f_swvp = NULL;
-
     return D3D_OK;
 }
 
@@ -73,13 +64,12 @@ NineStateBlock9_dtor( struct NineStateBlock9 *This )
     struct nine_range *r;
     struct nine_range_pool *pool = &This->base.device->range_pool;
 
-    nine_state_clear(state, FALSE);
+    nine_state_clear(state, false);
 
     FREE(state->vs_const_f);
     FREE(state->ps_const_f);
     FREE(state->vs_const_i);
     FREE(state->vs_const_b);
-    FREE(state->vs_const_f_swvp);
 
     FREE(state->ff.light);
 
@@ -105,6 +95,30 @@ NineStateBlock9_dtor( struct NineStateBlock9 *This )
     NineUnknown_dtor(&This->base);
 }
 
+static void
+NineStateBlock9_BindBuffer( struct NineDevice9 *device,
+                            boolean applyToDevice,
+                            struct NineBuffer9 **slot,
+                            struct NineBuffer9 *buf )
+{
+    if (applyToDevice)
+        NineBindBufferToDevice(device, slot, buf);
+    else
+        nine_bind(slot, buf);
+}
+
+static void
+NineStateBlock9_BindTexture( struct NineDevice9 *device,
+                             boolean applyToDevice,
+                             struct NineBaseTexture9 **slot,
+                             struct NineBaseTexture9 *tex )
+{
+    if (applyToDevice)
+        NineBindTextureToDevice(device, slot, tex);
+    else
+        nine_bind(slot, tex);
+}
+
 /* Copy state marked changed in @mask from @src to @dst.
  * If @apply is false, updating dst->changed can be omitted.
  * TODO: compare ?
@@ -120,8 +134,15 @@ nine_state_copy_common(struct NineDevice9 *device,
     unsigned i, s;
 
     DBG("apply:%d changed.group: %x\n", (int)apply, (int)mask->changed.group );
-    if (apply)
-       dst->changed.group |= mask->changed.group;
+
+    /* device changed.* are unused.
+     * Instead nine_context_apply_stateblock is used and will
+     * internally set the right context->changed fields.
+     * Uncomment these only if we want to apply a stateblock onto a stateblock.
+     *
+     * if (apply)
+     *     dst->changed.group |= mask->changed.group;
+     */
 
     if (mask->changed.group & NINE_STATE_VIEWPORT)
         dst->viewport = src->viewport;
@@ -138,51 +159,28 @@ nine_state_copy_common(struct NineDevice9 *device,
      * Various possibilities for optimization here, like creating a per-SB
      * constant buffer, or memcmp'ing for changes.
      * Will do that later depending on what works best for specific apps.
+     *
+     * Note: Currently when we apply stateblocks, it's always on the device state.
+     * Should it affect recording stateblocks ? Since it's on device state, there
+     * is no need to copy which ranges are dirty. If it turns out we should affect
+     * recording stateblocks, the info should be copied.
      */
     if (mask->changed.group & NINE_STATE_VS_CONST) {
         struct nine_range *r;
-        if (device->may_swvp) {
-            for (r = mask->changed.vs_const_f; r; r = r->next) {
-                int bgn = r->bgn;
-                int end = r->end;
-                memcpy(&dst->vs_const_f_swvp[bgn * 4],
-                       &src->vs_const_f_swvp[bgn * 4],
-                       (end - bgn) * 4 * sizeof(float));
-                if (apply)
-                    nine_ranges_insert(&dst->changed.vs_const_f, bgn, end,
-                                       pool);
-                if (bgn < device->max_vs_const_f) {
-                    end = MIN2(end, device->max_vs_const_f);
-                    memcpy(&dst->vs_const_f[bgn * 4],
-                           &src->vs_const_f[bgn * 4],
-                           (end - bgn) * 4 * sizeof(float));
-                }
-            }
-        } else {
-            for (r = mask->changed.vs_const_f; r; r = r->next) {
-                memcpy(&dst->vs_const_f[r->bgn * 4],
-                       &src->vs_const_f[r->bgn * 4],
-                       (r->end - r->bgn) * 4 * sizeof(float));
-                if (apply)
-                    nine_ranges_insert(&dst->changed.vs_const_f, r->bgn, r->end,
-                                       pool);
-            }
+        for (r = mask->changed.vs_const_f; r; r = r->next) {
+            memcpy(&dst->vs_const_f[r->bgn * 4],
+                   &src->vs_const_f[r->bgn * 4],
+                   (r->end - r->bgn) * 4 * sizeof(float));
         }
         for (r = mask->changed.vs_const_i; r; r = r->next) {
             memcpy(&dst->vs_const_i[r->bgn * 4],
                    &src->vs_const_i[r->bgn * 4],
                    (r->end - r->bgn) * 4 * sizeof(int));
-            if (apply)
-                nine_ranges_insert(&dst->changed.vs_const_i, r->bgn, r->end,
-                                   pool);
         }
         for (r = mask->changed.vs_const_b; r; r = r->next) {
             memcpy(&dst->vs_const_b[r->bgn],
                    &src->vs_const_b[r->bgn],
                    (r->end - r->bgn) * sizeof(int));
-            if (apply)
-                nine_ranges_insert(&dst->changed.vs_const_b, r->bgn, r->end,
-                                   pool);
         }
     }
 
@@ -193,35 +191,28 @@ nine_state_copy_common(struct NineDevice9 *device,
             memcpy(&dst->ps_const_f[r->bgn * 4],
                    &src->ps_const_f[r->bgn * 4],
                    (r->end - r->bgn) * 4 * sizeof(float));
-            if (apply)
-                nine_ranges_insert(&dst->changed.ps_const_f, r->bgn, r->end,
-                                   pool);
         }
         if (mask->changed.ps_const_i) {
             uint16_t m = mask->changed.ps_const_i;
             for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1)
                 if (m & 1)
                     memcpy(dst->ps_const_i[i], src->ps_const_i[i], 4 * sizeof(int));
-            if (apply)
-                dst->changed.ps_const_i |= mask->changed.ps_const_i;
         }
         if (mask->changed.ps_const_b) {
             uint16_t m = mask->changed.ps_const_b;
             for (i = ffs(m) - 1, m >>= i; m; ++i, m >>= 1)
                 if (m & 1)
                     dst->ps_const_b[i] = src->ps_const_b[i];
-            if (apply)
-                dst->changed.ps_const_b |= mask->changed.ps_const_b;
         }
     }
 
     /* Render states.
      * TODO: Maybe build a list ?
      */
-    for (i = 0; i < ARRAY_SIZE(dst->changed.rs); ++i) {
+    for (i = 0; i < ARRAY_SIZE(mask->changed.rs); ++i) {
         uint32_t m = mask->changed.rs[i];
-        if (apply)
-            dst->changed.rs[i] |= m;
+        /* if (apply)
+         *     dst->changed.rs[i] |= m; */
         while (m) {
             const int r = ffs(m) - 1;
             m &= ~(1 << r);
@@ -238,15 +229,14 @@ nine_state_copy_common(struct NineDevice9 *device,
             if (mask->changed.ucp & (1 << i))
                 memcpy(dst->clip.ucp[i],
                        src->clip.ucp[i], sizeof(src->clip.ucp[0]));
-        if (apply)
-           dst->changed.ucp |= mask->changed.ucp;
+        /* if (apply)
+         *    dst->changed.ucp |= mask->changed.ucp;*/
     }
 
     /* Sampler state. */
     if (mask->changed.group & NINE_STATE_SAMPLER) {
         for (s = 0; s < NINE_MAX_SAMPLERS; ++s) {
             if (mask->changed.sampler[s] == 0x3ffe) {
-                memcpy(&dst->samp[s], &src->samp[s], sizeof(dst->samp[s]));
                 memcpy(&dst->samp_advertised[s], &src->samp_advertised[s], sizeof(dst->samp_advertised[s]));
             } else {
                 uint32_t m = mask->changed.sampler[s];
@@ -254,18 +244,20 @@ nine_state_copy_common(struct NineDevice9 *device,
                 while (m) {
                     const int i = ffs(m) - 1;
                     m &= ~(1 << i);
-                    dst->samp[s][i] = src->samp[s][i];
                     dst->samp_advertised[s][i] = src->samp_advertised[s][i];
                 }
             }
-            if (apply)
-                dst->changed.sampler[s] |= mask->changed.sampler[s];
+            /* if (apply)
+             *     dst->changed.sampler[s] |= mask->changed.sampler[s];*/
         }
     }
 
     /* Index buffer. */
     if (mask->changed.group & NINE_STATE_IDXBUF)
-        nine_bind(&dst->idxbuf, src->idxbuf);
+        NineStateBlock9_BindBuffer(device,
+                                   apply,
+                                   (struct NineBuffer9 **)&dst->idxbuf,
+                                   (struct NineBuffer9 *)src->idxbuf);
 
     /* Vertex streams. */
     if (mask->changed.vtxbuf | mask->changed.stream_freq) {
@@ -273,23 +265,31 @@ nine_state_copy_common(struct NineDevice9 *device,
         uint32_t m = mask->changed.vtxbuf | mask->changed.stream_freq;
         for (i = 0; m; ++i, m >>= 1) {
             if (mask->changed.vtxbuf & (1 << i)) {
-                nine_bind(&dst->stream[i], src->stream[i]);
+                NineStateBlock9_BindBuffer(device,
+                                           apply,
+                                           (struct NineBuffer9 **)&dst->stream[i],
+                                           (struct NineBuffer9 *)src->stream[i]);
                 if (src->stream[i]) {
                     dst->vtxbuf[i].buffer_offset = src->vtxbuf[i].buffer_offset;
-                    pipe_resource_reference(&dst->vtxbuf[i].buffer, src->vtxbuf[i].buffer);
                     dst->vtxbuf[i].stride = src->vtxbuf[i].stride;
                 }
             }
             if (mask->changed.stream_freq & (1 << i))
                 dst->stream_freq[i] = src->stream_freq[i];
         }
-        dst->stream_instancedata_mask &= ~mask->changed.stream_freq;
-        dst->stream_instancedata_mask |=
-            src->stream_instancedata_mask & mask->changed.stream_freq;
-        if (apply) {
-            dst->changed.vtxbuf |= mask->changed.vtxbuf;
-            dst->changed.stream_freq |= mask->changed.stream_freq;
-        }
+        /*
+         * if (apply) {
+         *     dst->changed.vtxbuf |= mask->changed.vtxbuf;
+         *     dst->changed.stream_freq |= mask->changed.stream_freq;
+         * }*/
+    }
+
+    /* Textures */
+    if (mask->changed.texture) {
+        uint32_t m = mask->changed.texture;
+        for (s = 0; m; ++s, m >>= 1)
+            if (m & 1)
+                NineStateBlock9_BindTexture(device, apply, &dst->texture[s], src->texture[s]);
     }
 
     if (!(mask->changed.group & NINE_STATE_FF))
@@ -301,18 +301,19 @@ nine_state_copy_common(struct NineDevice9 *device,
     if (mask->changed.group & NINE_STATE_FF_MATERIAL)
         dst->ff.material = src->ff.material;
 
-    if (mask->changed.group & NINE_STATE_FF_PSSTAGES) {
+    if (mask->changed.group & NINE_STATE_FF_PS_CONSTS) {
         for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) {
             for (i = 0; i < NINED3DTSS_COUNT; ++i)
                 if (mask->ff.changed.tex_stage[s][i / 32] & (1 << (i % 32)))
                     dst->ff.tex_stage[s][i] = src->ff.tex_stage[s][i];
-            if (apply) {
-                /* TODO: it's 32 exactly, just offset by 1 as 0 is unused */
-                dst->ff.changed.tex_stage[s][0] |=
-                    mask->ff.changed.tex_stage[s][0];
-                dst->ff.changed.tex_stage[s][1] |=
-                    mask->ff.changed.tex_stage[s][1];
-            }
+            /*
+             * if (apply) {
+             *    TODO: it's 32 exactly, just offset by 1 as 0 is unused
+             *    dst->ff.changed.tex_stage[s][0] |=
+             *        mask->ff.changed.tex_stage[s][0];
+             *    dst->ff.changed.tex_stage[s][1] |=
+             *        mask->ff.changed.tex_stage[s][1];
+             * }*/
         }
     }
     if (mask->changed.group & NINE_STATE_FF_LIGHTING) {
@@ -364,12 +365,11 @@ nine_state_copy_common(struct NineDevice9 *device,
             for (s = i * 32; s < (i * 32 + 32); ++s) {
                 if (!(mask->ff.changed.transform[i] & (1 << (s % 32))))
                     continue;
-                *nine_state_access_transform(dst, s, TRUE) =
-                    *nine_state_access_transform( /* const because !alloc */
-                        (struct nine_state *)src, s, FALSE);
+                *nine_state_access_transform(&dst->ff, s, TRUE) =
+                    *nine_state_access_transform(&src->ff, s, FALSE);
             }
-            if (apply)
-                dst->ff.changed.transform[i] |= mask->ff.changed.transform[i];
+            /* if (apply)
+             *     dst->ff.changed.transform[i] |= mask->ff.changed.transform[i];*/
         }
     }
 }
@@ -377,7 +377,7 @@ nine_state_copy_common(struct NineDevice9 *device,
 static void
 nine_state_copy_common_all(struct NineDevice9 *device,
                            struct nine_state *dst,
-                           const struct nine_state *src,
+                           struct nine_state *src,
                            struct nine_state *help,
                            const boolean apply,
                            struct nine_range_pool *pool,
@@ -385,8 +385,9 @@ nine_state_copy_common_all(struct NineDevice9 *device,
 {
     unsigned i;
 
-    if (apply)
-       dst->changed.group |= src->changed.group;
+    /* if (apply)
+     *     dst->changed.group |= src->changed.group;
+     */
 
     dst->viewport = src->viewport;
     dst->scissor = src->scissor;
@@ -401,23 +402,11 @@ nine_state_copy_common_all(struct NineDevice9 *device,
      * Will do that later depending on what works best for specific apps.
      */
     if (1) {
-        struct nine_range *r = help->changed.vs_const_f;
         memcpy(&dst->vs_const_f[0],
-               &src->vs_const_f[0], device->max_vs_const_f * 4 * sizeof(float));
-        if (device->may_swvp)
-            memcpy(dst->vs_const_f_swvp,
-                   src->vs_const_f_swvp, VS_CONST_F_SWVP_SIZE);
-        if (apply)
-            nine_ranges_insert(&dst->changed.vs_const_f, r->bgn, r->end, pool);
+               &src->vs_const_f[0], VS_CONST_F_SIZE(device));
 
         memcpy(dst->vs_const_i, src->vs_const_i, VS_CONST_I_SIZE(device));
         memcpy(dst->vs_const_b, src->vs_const_b, VS_CONST_B_SIZE(device));
-        if (apply) {
-            r = help->changed.vs_const_i;
-            nine_ranges_insert(&dst->changed.vs_const_i, r->bgn, r->end, pool);
-            r = help->changed.vs_const_b;
-            nine_ranges_insert(&dst->changed.vs_const_b, r->bgn, r->end, pool);
-        }
     }
 
     /* Pixel constants. */
@@ -425,54 +414,57 @@ nine_state_copy_common_all(struct NineDevice9 *device,
         struct nine_range *r = help->changed.ps_const_f;
         memcpy(&dst->ps_const_f[0],
                &src->ps_const_f[0], (r->end - r->bgn) * 4 * sizeof(float));
-        if (apply)
-            nine_ranges_insert(&dst->changed.ps_const_f, r->bgn, r->end, pool);
 
         memcpy(dst->ps_const_i, src->ps_const_i, sizeof(dst->ps_const_i));
         memcpy(dst->ps_const_b, src->ps_const_b, sizeof(dst->ps_const_b));
-        if (apply) {
-            dst->changed.ps_const_i |= src->changed.ps_const_i;
-            dst->changed.ps_const_b |= src->changed.ps_const_b;
-        }
     }
 
     /* Render states. */
     memcpy(dst->rs_advertised, src->rs_advertised, sizeof(dst->rs_advertised));
-    if (apply)
-        memcpy(dst->changed.rs, src->changed.rs, sizeof(dst->changed.rs));
+    /* if (apply)
+     *     memcpy(dst->changed.rs, src->changed.rs, sizeof(dst->changed.rs));*/
 
 
     /* Clip planes. */
     memcpy(&dst->clip, &src->clip, sizeof(dst->clip));
-    if (apply)
-        dst->changed.ucp = src->changed.ucp;
+    /* if (apply)
+     *     dst->changed.ucp = src->changed.ucp;*/
 
     /* Sampler state. */
-    memcpy(dst->samp, src->samp, sizeof(dst->samp));
     memcpy(dst->samp_advertised, src->samp_advertised, sizeof(dst->samp_advertised));
-    if (apply)
-        memcpy(dst->changed.sampler,
-               src->changed.sampler, sizeof(dst->changed.sampler));
+    /* if (apply)
+     *     memcpy(dst->changed.sampler,
+     *            src->changed.sampler, sizeof(dst->changed.sampler));*/
 
     /* Index buffer. */
-    nine_bind(&dst->idxbuf, src->idxbuf);
+    NineStateBlock9_BindBuffer(device,
+                               apply,
+                               (struct NineBuffer9 **)&dst->idxbuf,
+                               (struct NineBuffer9 *)src->idxbuf);
 
     /* Vertex streams. */
     if (1) {
         for (i = 0; i < ARRAY_SIZE(dst->stream); ++i) {
-            nine_bind(&dst->stream[i], src->stream[i]);
+            NineStateBlock9_BindBuffer(device,
+                                       apply,
+                                       (struct NineBuffer9 **)&dst->stream[i],
+                                       (struct NineBuffer9 *)src->stream[i]);
             if (src->stream[i]) {
                 dst->vtxbuf[i].buffer_offset = src->vtxbuf[i].buffer_offset;
-                pipe_resource_reference(&dst->vtxbuf[i].buffer, src->vtxbuf[i].buffer);
                 dst->vtxbuf[i].stride = src->vtxbuf[i].stride;
             }
             dst->stream_freq[i] = src->stream_freq[i];
         }
-        dst->stream_instancedata_mask = src->stream_instancedata_mask;
-        if (apply) {
-            dst->changed.vtxbuf = (1ULL << MaxStreams) - 1;
-            dst->changed.stream_freq = (1ULL << MaxStreams) - 1;
-        }
+        /* if (apply) {
+         *     dst->changed.vtxbuf = (1ULL << MaxStreams) - 1;
+         *     dst->changed.stream_freq = (1ULL << MaxStreams) - 1;
+         *  }*/
+    }
+
+    /* Textures */
+    if (1) {
+        for (i = 0; i < NINE_MAX_SAMPLERS; i++)
+            NineStateBlock9_BindTexture(device, apply, &dst->texture[i], src->texture[i]);
     }
 
     /* keep this check in case we want to disable FF */
@@ -484,9 +476,9 @@ nine_state_copy_common_all(struct NineDevice9 *device,
     dst->ff.material = src->ff.material;
 
     memcpy(dst->ff.tex_stage, src->ff.tex_stage, sizeof(dst->ff.tex_stage));
-    if (apply) /* TODO: memset */
-        memcpy(dst->ff.changed.tex_stage,
-               src->ff.changed.tex_stage, sizeof(dst->ff.changed.tex_stage));
+    /* if (apply) TODO: memset
+     *     memcpy(dst->ff.changed.tex_stage,
+     *            src->ff.changed.tex_stage, sizeof(dst->ff.changed.tex_stage));*/
 
     /* Lights. */
     if (1) {
@@ -505,17 +497,23 @@ nine_state_copy_common_all(struct NineDevice9 *device,
 
     /* Transforms. */
     if (1) {
-        if (dst->ff.num_transforms < src->ff.num_transforms) {
-            dst->ff.transform = REALLOC(dst->ff.transform,
-                dst->ff.num_transforms * sizeof(dst->ff.transform[0]),
-                src->ff.num_transforms * sizeof(src->ff.transform[0]));
-            dst->ff.num_transforms = src->ff.num_transforms;
+        /* Increase dst size if required (to copy the new states).
+         * Increase src size if required (to initialize missing transforms).
+         */
+        if (dst->ff.num_transforms != src->ff.num_transforms) {
+            int num_transforms = MAX2(src->ff.num_transforms, dst->ff.num_transforms);
+            nine_state_resize_transform(&src->ff, num_transforms);
+            nine_state_resize_transform(&dst->ff, num_transforms);
         }
         memcpy(dst->ff.transform,
-               src->ff.transform, src->ff.num_transforms * sizeof(D3DMATRIX));
-        if (apply) /* TODO: memset */
-            memcpy(dst->ff.changed.transform,
-                   src->ff.changed.transform, sizeof(dst->ff.changed.transform));
+               src->ff.transform, dst->ff.num_transforms * sizeof(D3DMATRIX));
+        /* Apply is always used on device state.
+         * src is then the D3DSBT_ALL stateblock which
+         * ff.changed.transform indicates all matrices are dirty.
+         *
+         * if (apply)
+         *     memcpy(dst->ff.changed.transform,
+         *            src->ff.changed.transform, sizeof(dst->ff.changed.transform));*/
     }
 }
 
@@ -529,7 +527,6 @@ NineStateBlock9_Capture( struct NineStateBlock9 *This )
     struct nine_state *dst = &This->state;
     struct nine_state *src = &device->state;
     const int MaxStreams = device->caps.MaxStreams;
-    unsigned s;
 
     DBG("This=%p\n", This);
 
@@ -541,14 +538,6 @@ NineStateBlock9_Capture( struct NineStateBlock9 *This )
     if (dst->changed.group & NINE_STATE_VDECL)
         nine_bind(&dst->vdecl, src->vdecl);
 
-    /* Textures */
-    if (dst->changed.texture) {
-        uint32_t m = dst->changed.texture;
-        for (s = 0; m; ++s, m >>= 1)
-            if (m & 1)
-                nine_bind(&dst->texture[s], src->texture[s]);
-    }
-
     return D3D_OK;
 }
 
@@ -561,7 +550,6 @@ NineStateBlock9_Apply( struct NineStateBlock9 *This )
     struct nine_state *src = &This->state;
     struct nine_range_pool *pool = &device->range_pool;
     const int MaxStreams = device->caps.MaxStreams;
-    unsigned s;
 
     DBG("This=%p\n", This);
 
@@ -573,29 +561,7 @@ NineStateBlock9_Apply( struct NineStateBlock9 *This )
     nine_context_apply_stateblock(device, src);
 
     if ((src->changed.group & NINE_STATE_VDECL) && src->vdecl)
-        NineDevice9_SetVertexDeclaration(This->base.device, (IDirect3DVertexDeclaration9 *)src->vdecl);
-
-    /* Recomputing it is needed if we changed vs but not vdecl */
-    dst->programmable_vs = dst->vs && !(dst->vdecl && dst->vdecl->position_t);
-
-    /* Textures */
-    if (src->changed.texture) {
-        uint32_t m = src->changed.texture;
-
-        for (s = 0; m; ++s, m >>= 1) {
-            struct NineBaseTexture9 *tex = src->texture[s];
-            if (!(m & 1))
-                continue;
-            if (tex) {
-                tex->bind_count++;
-                if ((tex->managed.dirty | tex->dirty_mip) && LIST_IS_EMPTY(&tex->list))
-                    list_add(&tex->list, &This->base.device->update_textures);
-            }
-            if (src->texture[s])
-                src->texture[s]->bind_count--;
-            nine_bind(&dst->texture[s], src->texture[s]);
-        }
-    }
+        nine_bind(&dst->vdecl, src->vdecl);
 
     return D3D_OK;
 }