Merge commit 'origin/master' into gallium-sampler-view
authorKeith Whitwell <keithw@vmware.com>
Mon, 15 Mar 2010 09:44:52 +0000 (09:44 +0000)
committerKeith Whitwell <keithw@vmware.com>
Mon, 15 Mar 2010 09:44:52 +0000 (09:44 +0000)
Conflicts:
src/gallium/drivers/nv30/nv30_context.h
src/gallium/drivers/nv30/nv30_state.c
src/gallium/drivers/nv40/nv40_context.h
src/gallium/drivers/nv40/nv40_state.c
src/gallium/drivers/r300/r300_emit.c

1  2 
src/gallium/drivers/nv40/nv40_transfer.c
src/gallium/drivers/nvfx/nvfx_context.h
src/gallium/drivers/nvfx/nvfx_state.c
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_state.c

diff --cc src/gallium/drivers/nv40/nv40_transfer.c
index c552a681138096bb3e8278d99652f8948b2c1d2c,3d8c8e8c78a9d2714fcdc0bb46f423c16c2ec597..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,181 -1,181 +1,0 @@@
--#include "pipe/p_state.h"
--#include "pipe/p_defines.h"
--#include "util/u_inlines.h"
--#include "util/u_format.h"
--#include "util/u_memory.h"
--#include "util/u_math.h"
--#include "nouveau/nouveau_winsys.h"
--#include "nv40_context.h"
- #include "nv40_screen.h"
- #include "nv40_state.h"
 -#include "nvfx_screen.h"
 -#include "nvfx_state.h"
--
--struct nv40_transfer {
--      struct pipe_transfer base;
--      struct pipe_surface *surface;
--      boolean direct;
--};
--
--static void
--nv40_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height,
--                             struct pipe_texture *template)
--{
--      memset(template, 0, sizeof(struct pipe_texture));
--      template->target = pt->target;
--      template->format = pt->format;
--      template->width0 = width;
--      template->height0 = height;
--      template->depth0 = 1;
--      template->last_level = 0;
--      template->nr_samples = pt->nr_samples;
--
--      template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC |
--                            NOUVEAU_TEXTURE_USAGE_LINEAR;
--}
--
--static struct pipe_transfer *
--nv40_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt,
--                unsigned face, unsigned level, unsigned zslice,
--                enum pipe_transfer_usage usage,
--                unsigned x, unsigned y, unsigned w, unsigned h)
--{
--        struct pipe_screen *pscreen = pcontext->screen;
-       struct nv40_miptree *mt = (struct nv40_miptree *)pt;
 -      struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
--      struct nv40_transfer *tx;
--      struct pipe_texture tx_tex_template, *tx_tex;
--
--      tx = CALLOC_STRUCT(nv40_transfer);
--      if (!tx)
--              return NULL;
--
--      pipe_texture_reference(&tx->base.texture, pt);
--      tx->base.x = x;
--      tx->base.y = y;
--      tx->base.width = w;
--      tx->base.height = h;
--      tx->base.stride = mt->level[level].pitch;
--      tx->base.usage = usage;
--      tx->base.face = face;
--      tx->base.level = level;
--      tx->base.zslice = zslice;
--
--      /* Direct access to texture */
--      if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC ||
--           debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) &&
--          pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)
--      {
--              tx->direct = true;
--              tx->surface = pscreen->get_tex_surface(pscreen, pt,
--                                                     face, level, zslice,
--                                                     pipe_transfer_buffer_flags(&tx->base));
--              return &tx->base;
--      }
--
--      tx->direct = false;
--
--      nv40_compatible_transfer_tex(pt, w, h, &tx_tex_template);
--
--      tx_tex = pscreen->texture_create(pscreen, &tx_tex_template);
--      if (!tx_tex)
--      {
--              FREE(tx);
--              return NULL;
--      }
--
-       tx->base.stride = ((struct nv40_miptree*)tx_tex)->level[0].pitch;
 -      tx->base.stride = ((struct nvfx_miptree*)tx_tex)->level[0].pitch;
--
--      tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
--                                             0, 0, 0,
--                                             pipe_transfer_buffer_flags(&tx->base));
--
--      pipe_texture_reference(&tx_tex, NULL);
--
--      if (!tx->surface)
--      {
--              pipe_surface_reference(&tx->surface, NULL);
--              FREE(tx);
--              return NULL;
--      }
--
--      if (usage & PIPE_TRANSFER_READ) {
-               struct nv40_screen *nvscreen = nv40_screen(pscreen);
 -              struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
--              struct pipe_surface *src;
--
--              src = pscreen->get_tex_surface(pscreen, pt,
--                                             face, level, zslice,
--                                             PIPE_BUFFER_USAGE_GPU_READ);
--
--              /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
--              /* TODO: Check if SIFM can un-swizzle */
--              nvscreen->eng2d->copy(nvscreen->eng2d,
--                                    tx->surface, 0, 0,
--                                    src, x, y,
--                                    w, h);
--
--              pipe_surface_reference(&src, NULL);
--      }
--
--      return &tx->base;
--}
--
--static void
--nv40_transfer_del(struct pipe_context *pcontext, struct pipe_transfer *ptx)
--{
--      struct nv40_transfer *tx = (struct nv40_transfer *)ptx;
--
--      if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) {
--              struct pipe_screen *pscreen = pcontext->screen;
-               struct nv40_screen *nvscreen = nv40_screen(pscreen);
 -              struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
--              struct pipe_surface *dst;
--
--              dst = pscreen->get_tex_surface(pscreen, ptx->texture,
--                                             ptx->face, ptx->level, ptx->zslice,
--                                             PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER);
--
--              /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
--              nvscreen->eng2d->copy(nvscreen->eng2d,
--                                    dst, tx->base.x, tx->base.y,
--                                    tx->surface, 0, 0,
--                                    tx->base.width, tx->base.height);
--
--              pipe_surface_reference(&dst, NULL);
--      }
--
--      pipe_surface_reference(&tx->surface, NULL);
--      pipe_texture_reference(&ptx->texture, NULL);
--      FREE(ptx);
--}
--
--static void *
--nv40_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx)
--{
--        struct pipe_screen *pscreen = pcontext->screen;
--      struct nv40_transfer *tx = (struct nv40_transfer *)ptx;
--      struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
-       struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture;
 -      struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
--      void *map = pipe_buffer_map(pscreen, mt->buffer,
--                                  pipe_transfer_buffer_flags(ptx));
--
--      if(!tx->direct)
--              return map + ns->base.offset;
--      else
--              return map + ns->base.offset + ptx->y * ns->pitch + ptx->x * util_format_get_blocksize(ptx->texture->format);
--}
--
--static void
--nv40_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx)
--{
--        struct pipe_screen *pscreen = pcontext->screen;
--      struct nv40_transfer *tx = (struct nv40_transfer *)ptx;
-       struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture;
 -      struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
--
--      pipe_buffer_unmap(pscreen, mt->buffer);
--}
--
--void
- nv40_init_transfer_functions(struct nv40_context *nv40)
 -nv40_init_transfer_functions(struct nvfx_context *nvfx)
--{
-       nv40->pipe.get_tex_transfer = nv40_transfer_new;
-       nv40->pipe.tex_transfer_destroy = nv40_transfer_del;
-       nv40->pipe.transfer_map = nv40_transfer_map;
-       nv40->pipe.transfer_unmap = nv40_transfer_unmap;
 -      nvfx->pipe.get_tex_transfer = nv40_transfer_new;
 -      nvfx->pipe.tex_transfer_destroy = nv40_transfer_del;
 -      nvfx->pipe.transfer_map = nv40_transfer_map;
 -      nvfx->pipe.transfer_unmap = nv40_transfer_unmap;
--}
index 0000000000000000000000000000000000000000,5eed8a560e59b3c9901280e499be7a344a9f0c4a..001b19eedf04d33976371639e87b44d2e0ee37c2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,264 +1,265 @@@
+ #ifndef __NVFX_CONTEXT_H__
+ #define __NVFX_CONTEXT_H__
+ #include <stdio.h>
+ #include "pipe/p_context.h"
+ #include "pipe/p_defines.h"
+ #include "pipe/p_state.h"
+ #include "pipe/p_compiler.h"
+ #include "util/u_memory.h"
+ #include "util/u_math.h"
+ #include "util/u_inlines.h"
+ #include "draw/draw_vertex.h"
+ #include "nouveau/nouveau_winsys.h"
+ #include "nouveau/nouveau_gldefs.h"
+ #include "nouveau/nouveau_context.h"
+ #include "nouveau/nouveau_stateobj.h"
+ #include "nvfx_state.h"
+ #define NOUVEAU_ERR(fmt, args...) \
+       fprintf(stderr, "%s:%d -  "fmt, __func__, __LINE__, ##args);
+ #define NOUVEAU_MSG(fmt, args...) \
+       fprintf(stderr, "nouveau: "fmt, ##args);
+ enum nvfx_state_index {
+       NVFX_STATE_FB = 0,
+       NVFX_STATE_VIEWPORT = 1,
+       NVFX_STATE_BLEND = 2,
+       NVFX_STATE_RAST = 3,
+       NVFX_STATE_ZSA = 4,
+       NVFX_STATE_BCOL = 5,
+       NVFX_STATE_CLIP = 6,
+       NVFX_STATE_SCISSOR = 7,
+       NVFX_STATE_STIPPLE = 8,
+       NVFX_STATE_FRAGPROG = 9,
+       NVFX_STATE_VERTPROG = 10,
+       NVFX_STATE_FRAGTEX0 = 11,
+       NVFX_STATE_FRAGTEX1 = 12,
+       NVFX_STATE_FRAGTEX2 = 13,
+       NVFX_STATE_FRAGTEX3 = 14,
+       NVFX_STATE_FRAGTEX4 = 15,
+       NVFX_STATE_FRAGTEX5 = 16,
+       NVFX_STATE_FRAGTEX6 = 17,
+       NVFX_STATE_FRAGTEX7 = 18,
+       NVFX_STATE_FRAGTEX8 = 19,
+       NVFX_STATE_FRAGTEX9 = 20,
+       NVFX_STATE_FRAGTEX10 = 21,
+       NVFX_STATE_FRAGTEX11 = 22,
+       NVFX_STATE_FRAGTEX12 = 23,
+       NVFX_STATE_FRAGTEX13 = 24,
+       NVFX_STATE_FRAGTEX14 = 25,
+       NVFX_STATE_FRAGTEX15 = 26,
+       NVFX_STATE_VERTTEX0 = 27,
+       NVFX_STATE_VERTTEX1 = 28,
+       NVFX_STATE_VERTTEX2 = 29,
+       NVFX_STATE_VERTTEX3 = 30,
+       NVFX_STATE_VTXBUF = 31,
+       NVFX_STATE_VTXFMT = 32,
+       NVFX_STATE_VTXATTR = 33,
+       NVFX_STATE_SR = 34,
+       NVFX_STATE_MAX = 35
+ };
+ #include "nvfx_screen.h"
+ #define NVFX_NEW_BLEND                (1 <<  0)
+ #define NVFX_NEW_RAST         (1 <<  1)
+ #define NVFX_NEW_ZSA          (1 <<  2)
+ #define NVFX_NEW_SAMPLER      (1 <<  3)
+ #define NVFX_NEW_FB           (1 <<  4)
+ #define NVFX_NEW_STIPPLE      (1 <<  5)
+ #define NVFX_NEW_SCISSOR      (1 <<  6)
+ #define NVFX_NEW_VIEWPORT     (1 <<  7)
+ #define NVFX_NEW_BCOL         (1 <<  8)
+ #define NVFX_NEW_VERTPROG     (1 <<  9)
+ #define NVFX_NEW_FRAGPROG     (1 << 10)
+ #define NVFX_NEW_ARRAYS               (1 << 11)
+ #define NVFX_NEW_UCP          (1 << 12)
+ #define NVFX_NEW_SR           (1 << 13)
+ struct nvfx_rasterizer_state {
+       struct pipe_rasterizer_state pipe;
+       struct nouveau_stateobj *so;
+ };
+ struct nvfx_zsa_state {
+       struct pipe_depth_stencil_alpha_state pipe;
+       struct nouveau_stateobj *so;
+ };
+ struct nvfx_blend_state {
+       struct pipe_blend_state pipe;
+       struct nouveau_stateobj *so;
+ };
+ struct nvfx_state {
+       unsigned scissor_enabled;
+       unsigned stipple_enabled;
+       unsigned fp_samplers;
+       uint64_t dirty;
+       struct nouveau_stateobj *hw[NVFX_STATE_MAX];
+ };
+ struct nvfx_vtxelt_state {
+       struct pipe_vertex_element pipe[16];
+       unsigned num_elements;
+ };
+ struct nvfx_context {
+       struct pipe_context pipe;
+       struct nouveau_winsys *nvws;
+       struct nvfx_screen *screen;
+       unsigned is_nv4x; /* either 0 or ~0 */
+       struct draw_context *draw;
+       /* HW state derived from pipe states */
+       struct nvfx_state state;
+       struct {
+               struct nvfx_vertex_program *vertprog;
+               unsigned nr_attribs;
+               unsigned hw[PIPE_MAX_SHADER_INPUTS];
+               unsigned draw[PIPE_MAX_SHADER_INPUTS];
+               unsigned emit[PIPE_MAX_SHADER_INPUTS];
+       } swtnl;
+       enum {
+               HW, SWTNL, SWRAST
+       } render_mode;
+       unsigned fallback_swtnl;
+       unsigned fallback_swrast;
+       /* Context state */
+       unsigned dirty, draw_dirty;
+       struct pipe_scissor_state scissor;
+       unsigned stipple[32];
+       struct pipe_clip_state clip;
+       struct nvfx_vertex_program *vertprog;
+       struct nvfx_fragment_program *fragprog;
+       struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
+       unsigned constbuf_nr[PIPE_SHADER_TYPES];
+       struct nvfx_rasterizer_state *rasterizer;
+       struct nvfx_zsa_state *zsa;
+       struct nvfx_blend_state *blend;
+       struct pipe_blend_color blend_colour;
+       struct pipe_stencil_ref stencil_ref;
+       struct pipe_viewport_state viewport;
+       struct pipe_framebuffer_state framebuffer;
+       struct pipe_buffer *idxbuf;
+       unsigned idxbuf_format;
+       struct nvfx_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
+       struct nvfx_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
++      struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS];
+       unsigned nr_samplers;
+       unsigned nr_textures;
+       unsigned dirty_samplers;
+       struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
+       unsigned vtxbuf_nr;
+       struct nvfx_vtxelt_state *vtxelt;
+ };
+ static INLINE struct nvfx_context *
+ nvfx_context(struct pipe_context *pipe)
+ {
+       return (struct nvfx_context *)pipe;
+ }
+ struct nvfx_state_entry {
+       boolean (*validate)(struct nvfx_context *nvfx);
+       struct {
+               unsigned pipe;
+               unsigned hw;
+       } dirty;
+ };
+ extern struct nvfx_state_entry nvfx_state_blend;
+ extern struct nvfx_state_entry nvfx_state_blend_colour;
+ extern struct nvfx_state_entry nvfx_state_fragprog;
+ extern struct nvfx_state_entry nvfx_state_fragtex;
+ extern struct nvfx_state_entry nvfx_state_framebuffer;
+ extern struct nvfx_state_entry nvfx_state_rasterizer;
+ extern struct nvfx_state_entry nvfx_state_scissor;
+ extern struct nvfx_state_entry nvfx_state_sr;
+ extern struct nvfx_state_entry nvfx_state_stipple;
+ extern struct nvfx_state_entry nvfx_state_vbo;
+ extern struct nvfx_state_entry nvfx_state_vertprog;
+ extern struct nvfx_state_entry nvfx_state_viewport;
+ extern struct nvfx_state_entry nvfx_state_vtxfmt;
+ extern struct nvfx_state_entry nvfx_state_zsa;
+ extern void nvfx_init_query_functions(struct nvfx_context *nvfx);
+ extern void nvfx_init_surface_functions(struct nvfx_context *nvfx);
+ /* nvfx_context.c */
+ struct pipe_context *
+ nvfx_create(struct pipe_screen *pscreen, void *priv);
+ /* nvfx_clear.c */
+ extern void nvfx_clear(struct pipe_context *pipe, unsigned buffers,
+                      const float *rgba, double depth, unsigned stencil);
+ /* nvfx_draw.c */
+ extern struct draw_stage *nvfx_draw_render_stage(struct nvfx_context *nvfx);
+ extern void nvfx_draw_elements_swtnl(struct pipe_context *pipe,
+                                       struct pipe_buffer *idxbuf,
+                                       unsigned ib_size, unsigned mode,
+                                       unsigned start, unsigned count);
+ /* nvfx_fragprog.c */
+ extern void nvfx_fragprog_destroy(struct nvfx_context *,
+                                   struct nvfx_fragment_program *);
+ /* nv30_fragtex.c */
+ extern void
+ nv30_sampler_state_init(struct pipe_context *pipe,
+                         struct nvfx_sampler_state *ps,
+                         const struct pipe_sampler_state *cso);
+ extern void nv30_fragtex_bind(struct nvfx_context *);
+ extern struct nouveau_stateobj *
+ nv30_fragtex_build(struct nvfx_context *nvfx, int unit);
+ /* nv40_fragtex.c */
+ extern void
+ nv40_sampler_state_init(struct pipe_context *pipe,
+                         struct nvfx_sampler_state *ps,
+                         const struct pipe_sampler_state *cso);
+ extern void nv40_fragtex_bind(struct nvfx_context *);
+ extern struct nouveau_stateobj *
+ nv40_fragtex_build(struct nvfx_context *nvfx, int unit);
+ /* nvfx_state.c */
+ extern void nvfx_init_state_functions(struct nvfx_context *nvfx);
+ /* nvfx_state_emit.c */
+ extern void nvfx_state_flush_notify(struct nouveau_channel *chan);
+ extern boolean nvfx_state_validate(struct nvfx_context *nvfx);
+ extern boolean nvfx_state_validate_swtnl(struct nvfx_context *nvfx);
+ extern void nvfx_state_emit(struct nvfx_context *nvfx);
+ /* nvfx_transfer.c */
+ extern void nvfx_init_transfer_functions(struct nvfx_context *nvfx);
+ /* nvfx_vbo.c */
+ extern void nvfx_draw_arrays(struct pipe_context *, unsigned mode,
+                               unsigned start, unsigned count);
+ extern void nvfx_draw_elements(struct pipe_context *pipe,
+                                 struct pipe_buffer *indexBuffer,
+                                 unsigned indexSize,
+                                 unsigned mode, unsigned start,
+                                 unsigned count);
+ /* nvfx_vertprog.c */
+ extern void nvfx_vertprog_destroy(struct nvfx_context *,
+                                 struct nvfx_vertex_program *);
+ #endif
index 0000000000000000000000000000000000000000,88a9d01c509b3b56d179ba54a784f611662f5fd4..32a81997528ddc2789d7ea7f2bf3f12f0b2ff7fe
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,619 +1,652 @@@
 -nvfx_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
 -                       struct pipe_texture **miptree)
+ #include "pipe/p_state.h"
+ #include "pipe/p_defines.h"
+ #include "util/u_inlines.h"
+ #include "draw/draw_context.h"
+ #include "tgsi/tgsi_parse.h"
+ #include "nvfx_context.h"
+ #include "nvfx_state.h"
+ #include "nvfx_tex.h"
+ static void *
+ nvfx_blend_state_create(struct pipe_context *pipe,
+                       const struct pipe_blend_state *cso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
+       struct nvfx_blend_state *bso = CALLOC(1, sizeof(*bso));
+       struct nouveau_stateobj *so = so_new(5, 8, 0);
+       if (cso->rt[0].blend_enable) {
+               so_method(so, eng3d, NV34TCL_BLEND_FUNC_ENABLE, 3);
+               so_data  (so, 1);
+               so_data  (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) |
+                              nvgl_blend_func(cso->rt[0].rgb_src_factor));
+               so_data  (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 |
+                             nvgl_blend_func(cso->rt[0].rgb_dst_factor));
+               if(nvfx->screen->base.device->chipset < 0x40) {
+                       so_method(so, eng3d, NV34TCL_BLEND_EQUATION, 1);
+                       so_data  (so, nvgl_blend_eqn(cso->rt[0].rgb_func));
+               } else {
+                       so_method(so, eng3d, NV40TCL_BLEND_EQUATION, 1);
+                       so_data  (so, nvgl_blend_eqn(cso->rt[0].alpha_func) << 16 |
+                             nvgl_blend_eqn(cso->rt[0].rgb_func));
+               }
+       } else {
+               so_method(so, eng3d, NV34TCL_BLEND_FUNC_ENABLE, 1);
+               so_data  (so, 0);
+       }
+       so_method(so, eng3d, NV34TCL_COLOR_MASK, 1);
+       so_data  (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) |
+              ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) |
+              ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 <<  8) : 0) |
+              ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 <<  0) : 0)));
+       /* TODO: add NV40 MRT color mask */
+       if (cso->logicop_enable) {
+               so_method(so, eng3d, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2);
+               so_data  (so, 1);
+               so_data  (so, nvgl_logicop_func(cso->logicop_func));
+       } else {
+               so_method(so, eng3d, NV34TCL_COLOR_LOGIC_OP_ENABLE, 1);
+               so_data  (so, 0);
+       }
+       so_method(so, eng3d, NV34TCL_DITHER_ENABLE, 1);
+       so_data  (so, cso->dither ? 1 : 0);
+       so_ref(so, &bso->so);
+       so_ref(NULL, &so);
+       bso->pipe = *cso;
+       return (void *)bso;
+ }
+ static void
+ nvfx_blend_state_bind(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->blend = hwcso;
+       nvfx->dirty |= NVFX_NEW_BLEND;
+ }
+ static void
+ nvfx_blend_state_delete(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_blend_state *bso = hwcso;
+       so_ref(NULL, &bso->so);
+       FREE(bso);
+ }
+ static void *
+ nvfx_sampler_state_create(struct pipe_context *pipe,
+                         const struct pipe_sampler_state *cso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_sampler_state *ps;
+       ps = MALLOC(sizeof(struct nvfx_sampler_state));
+       /* on nv30, we use this as an internal flag */
+       ps->fmt = cso->normalized_coords ? 0 : NV40TCL_TEX_FORMAT_RECT;
+       ps->en = 0;
+       ps->filt = nvfx_tex_filter(cso);
+       ps->wrap = (nvfx_tex_wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) |
+                   (nvfx_tex_wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) |
+                   (nvfx_tex_wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT) |
+                   nvfx_tex_wrap_compare_mode(cso);
+       ps->bcol = nvfx_tex_border_color(cso->border_color);
+       if(nvfx->is_nv4x)
+               nv40_sampler_state_init(pipe, ps, cso);
+       else
+               nv30_sampler_state_init(pipe, ps, cso);
+       return (void *)ps;
+ }
+ static void
+ nvfx_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       unsigned unit;
+       for (unit = 0; unit < nr; unit++) {
+               nvfx->tex_sampler[unit] = sampler[unit];
+               nvfx->dirty_samplers |= (1 << unit);
+       }
+       for (unit = nr; unit < nvfx->nr_samplers; unit++) {
+               nvfx->tex_sampler[unit] = NULL;
+               nvfx->dirty_samplers |= (1 << unit);
+       }
+       nvfx->nr_samplers = nr;
+       nvfx->dirty |= NVFX_NEW_SAMPLER;
+ }
+ static void
+ nvfx_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
+ {
+       FREE(hwcso);
+ }
+ static void
++nvfx_set_fragment_sampler_views(struct pipe_context *pipe,
++                              unsigned nr,
++                              struct pipe_sampler_view **views)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       unsigned unit;
+       for (unit = 0; unit < nr; unit++) {
++              pipe_sampler_view_reference(&nv30->fragment_sampler_views[unit],
++                                            views[unit]);
+               pipe_texture_reference((struct pipe_texture **)
+                                      &nvfx->tex_miptree[unit], miptree[unit]);
+               nvfx->dirty_samplers |= (1 << unit);
+       }
+       for (unit = nr; unit < nvfx->nr_textures; unit++) {
++              pipe_sampler_view_reference(&nv30->fragment_sampler_views[unit],
++                                            NULL);
+               pipe_texture_reference((struct pipe_texture **)
+                                      &nvfx->tex_miptree[unit], NULL);
+               nvfx->dirty_samplers |= (1 << unit);
+       }
+       nvfx->nr_textures = nr;
+       nvfx->dirty |= NVFX_NEW_SAMPLER;
+ }
++
++static struct pipe_sampler_view *
++nv30_create_sampler_view(struct pipe_context *pipe,
++                       struct pipe_texture *texture,
++                       const struct pipe_sampler_view *templ)
++{
++      struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
++
++      if (view) {
++              *view = *templ;
++              view->reference.count = 1;
++              view->texture = NULL;
++              pipe_texture_reference(&view->texture, texture);
++              view->context = pipe;
++      }
++
++      return view;
++}
++
++
++static void
++nv30_sampler_view_destroy(struct pipe_context *pipe,
++                        struct pipe_sampler_view *view)
++{
++      pipe_texture_reference(&view->texture, NULL);
++      FREE(view);
++}
++
+ static void *
+ nvfx_rasterizer_state_create(struct pipe_context *pipe,
+                            const struct pipe_rasterizer_state *cso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso));
+       struct nouveau_stateobj *so = so_new(9, 19, 0);
+       struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
+       /*XXX: ignored:
+        *      light_twoside
+        *      point_smooth -nohw
+        *      multisample
+        */
+       so_method(so, eng3d, NV34TCL_SHADE_MODEL, 1);
+       so_data  (so, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT :
+                                      NV34TCL_SHADE_MODEL_SMOOTH);
+       so_method(so, eng3d, NV34TCL_LINE_WIDTH, 2);
+       so_data  (so, (unsigned char)(cso->line_width * 8.0) & 0xff);
+       so_data  (so, cso->line_smooth ? 1 : 0);
+       so_method(so, eng3d, NV34TCL_LINE_STIPPLE_ENABLE, 2);
+       so_data  (so, cso->line_stipple_enable ? 1 : 0);
+       so_data  (so, (cso->line_stipple_pattern << 16) |
+                      cso->line_stipple_factor);
+       so_method(so, eng3d, NV34TCL_POINT_SIZE, 1);
+       so_data  (so, fui(cso->point_size));
+       so_method(so, eng3d, NV34TCL_POLYGON_MODE_FRONT, 6);
+       if (cso->front_winding == PIPE_WINDING_CCW) {
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV34TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV34TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV34TCL_CULL_FACE_BACK);
+                       break;
+               }
+               so_data(so, NV34TCL_FRONT_FACE_CCW);
+       } else {
+               so_data(so, nvgl_polygon_mode(cso->fill_cw));
+               so_data(so, nvgl_polygon_mode(cso->fill_ccw));
+               switch (cso->cull_mode) {
+               case PIPE_WINDING_CCW:
+                       so_data(so, NV34TCL_CULL_FACE_BACK);
+                       break;
+               case PIPE_WINDING_CW:
+                       so_data(so, NV34TCL_CULL_FACE_FRONT);
+                       break;
+               case PIPE_WINDING_BOTH:
+                       so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK);
+                       break;
+               default:
+                       so_data(so, NV34TCL_CULL_FACE_BACK);
+                       break;
+               }
+               so_data(so, NV34TCL_FRONT_FACE_CW);
+       }
+       so_data(so, cso->poly_smooth ? 1 : 0);
+       so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0);
+       so_method(so, eng3d, NV34TCL_POLYGON_STIPPLE_ENABLE, 1);
+       so_data  (so, cso->poly_stipple_enable ? 1 : 0);
+       so_method(so, eng3d, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) ||
+           (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL))
+               so_data(so, 1);
+       else
+               so_data(so, 0);
+       if (cso->offset_cw || cso->offset_ccw) {
+               so_method(so, eng3d, NV34TCL_POLYGON_OFFSET_FACTOR, 2);
+               so_data  (so, fui(cso->offset_scale));
+               so_data  (so, fui(cso->offset_units * 2));
+       }
+       so_method(so, eng3d, NV34TCL_POINT_SPRITE, 1);
+       if (cso->point_quad_rasterization) {
+               unsigned psctl = (1 << 0), i;
+               for (i = 0; i < 8; i++) {
+                       if ((cso->sprite_coord_enable >> i) & 1)
+                               psctl |= (1 << (8 + i));
+               }
+               so_data(so, psctl);
+       } else {
+               so_data(so, 0);
+       }
+       so_ref(so, &rsso->so);
+       so_ref(NULL, &so);
+       rsso->pipe = *cso;
+       return (void *)rsso;
+ }
+ static void
+ nvfx_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->rasterizer = hwcso;
+       nvfx->dirty |= NVFX_NEW_RAST;
+       nvfx->draw_dirty |= NVFX_NEW_RAST;
+ }
+ static void
+ nvfx_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_rasterizer_state *rsso = hwcso;
+       so_ref(NULL, &rsso->so);
+       FREE(rsso);
+ }
+ static void *
+ nvfx_depth_stencil_alpha_state_create(struct pipe_context *pipe,
+                       const struct pipe_depth_stencil_alpha_state *cso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso));
+       struct nouveau_stateobj *so = so_new(6, 20, 0);
+       struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
+       so_method(so, eng3d, NV34TCL_DEPTH_FUNC, 3);
+       so_data  (so, nvgl_comparison_op(cso->depth.func));
+       so_data  (so, cso->depth.writemask ? 1 : 0);
+       so_data  (so, cso->depth.enabled ? 1 : 0);
+       so_method(so, eng3d, NV34TCL_ALPHA_FUNC_ENABLE, 3);
+       so_data  (so, cso->alpha.enabled ? 1 : 0);
+       so_data  (so, nvgl_comparison_op(cso->alpha.func));
+       so_data  (so, float_to_ubyte(cso->alpha.ref_value));
+       if (cso->stencil[0].enabled) {
+               so_method(so, eng3d, NV34TCL_STENCIL_FRONT_ENABLE, 3);
+               so_data  (so, cso->stencil[0].enabled ? 1 : 0);
+               so_data  (so, cso->stencil[0].writemask);
+               so_data  (so, nvgl_comparison_op(cso->stencil[0].func));
+               so_method(so, eng3d, NV34TCL_STENCIL_FRONT_FUNC_MASK, 4);
+               so_data  (so, cso->stencil[0].valuemask);
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].fail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
+       } else {
+               so_method(so, eng3d, NV34TCL_STENCIL_FRONT_ENABLE, 1);
+               so_data  (so, 0);
+       }
+       if (cso->stencil[1].enabled) {
+               so_method(so, eng3d, NV34TCL_STENCIL_BACK_ENABLE, 3);
+               so_data  (so, cso->stencil[1].enabled ? 1 : 0);
+               so_data  (so, cso->stencil[1].writemask);
+               so_data  (so, nvgl_comparison_op(cso->stencil[1].func));
+               so_method(so, eng3d, NV34TCL_STENCIL_BACK_FUNC_MASK, 4);
+               so_data  (so, cso->stencil[1].valuemask);
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].fail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
+               so_data  (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
+       } else {
+               so_method(so, eng3d, NV34TCL_STENCIL_BACK_ENABLE, 1);
+               so_data  (so, 0);
+       }
+       so_ref(so, &zsaso->so);
+       so_ref(NULL, &so);
+       zsaso->pipe = *cso;
+       return (void *)zsaso;
+ }
+ static void
+ nvfx_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->zsa = hwcso;
+       nvfx->dirty |= NVFX_NEW_ZSA;
+ }
+ static void
+ nvfx_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_zsa_state *zsaso = hwcso;
+       so_ref(NULL, &zsaso->so);
+       FREE(zsaso);
+ }
+ static void *
+ nvfx_vp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_vertex_program *vp;
+       vp = CALLOC(1, sizeof(struct nvfx_vertex_program));
+       vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+       vp->draw = draw_create_vertex_shader(nvfx->draw, &vp->pipe);
+       return (void *)vp;
+ }
+ static void
+ nvfx_vp_state_bind(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->vertprog = hwcso;
+       nvfx->dirty |= NVFX_NEW_VERTPROG;
+       nvfx->draw_dirty |= NVFX_NEW_VERTPROG;
+ }
+ static void
+ nvfx_vp_state_delete(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_vertex_program *vp = hwcso;
+       draw_delete_vertex_shader(nvfx->draw, vp->draw);
+       nvfx_vertprog_destroy(nvfx, vp);
+       FREE((void*)vp->pipe.tokens);
+       FREE(vp);
+ }
+ static void *
+ nvfx_fp_state_create(struct pipe_context *pipe,
+                    const struct pipe_shader_state *cso)
+ {
+       struct nvfx_fragment_program *fp;
+       fp = CALLOC(1, sizeof(struct nvfx_fragment_program));
+       fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+       tgsi_scan_shader(fp->pipe.tokens, &fp->info);
+       return (void *)fp;
+ }
+ static void
+ nvfx_fp_state_bind(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->fragprog = hwcso;
+       nvfx->dirty |= NVFX_NEW_FRAGPROG;
+ }
+ static void
+ nvfx_fp_state_delete(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_fragment_program *fp = hwcso;
+       nvfx_fragprog_destroy(nvfx, fp);
+       FREE((void*)fp->pipe.tokens);
+       FREE(fp);
+ }
+ static void
+ nvfx_set_blend_color(struct pipe_context *pipe,
+                    const struct pipe_blend_color *bcol)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->blend_colour = *bcol;
+       nvfx->dirty |= NVFX_NEW_BCOL;
+ }
+ static void
+ nvfx_set_stencil_ref(struct pipe_context *pipe,
+                    const struct pipe_stencil_ref *sr)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->stencil_ref = *sr;
+       nvfx->dirty |= NVFX_NEW_SR;
+ }
+ static void
+ nvfx_set_clip_state(struct pipe_context *pipe,
+                   const struct pipe_clip_state *clip)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->clip = *clip;
+       nvfx->dirty |= NVFX_NEW_UCP;
+       nvfx->draw_dirty |= NVFX_NEW_UCP;
+ }
+ static void
+ nvfx_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
+                        struct pipe_buffer *buf )
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->constbuf[shader] = buf;
+       nvfx->constbuf_nr[shader] = buf->size / (4 * sizeof(float));
+       if (shader == PIPE_SHADER_VERTEX) {
+               nvfx->dirty |= NVFX_NEW_VERTPROG;
+       } else
+       if (shader == PIPE_SHADER_FRAGMENT) {
+               nvfx->dirty |= NVFX_NEW_FRAGPROG;
+       }
+ }
+ static void
+ nvfx_set_framebuffer_state(struct pipe_context *pipe,
+                          const struct pipe_framebuffer_state *fb)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->framebuffer = *fb;
+       nvfx->dirty |= NVFX_NEW_FB;
+ }
+ static void
+ nvfx_set_polygon_stipple(struct pipe_context *pipe,
+                        const struct pipe_poly_stipple *stipple)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       memcpy(nvfx->stipple, stipple->stipple, 4 * 32);
+       nvfx->dirty |= NVFX_NEW_STIPPLE;
+ }
+ static void
+ nvfx_set_scissor_state(struct pipe_context *pipe,
+                      const struct pipe_scissor_state *s)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->scissor = *s;
+       nvfx->dirty |= NVFX_NEW_SCISSOR;
+ }
+ static void
+ nvfx_set_viewport_state(struct pipe_context *pipe,
+                       const struct pipe_viewport_state *vpt)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->viewport = *vpt;
+       nvfx->dirty |= NVFX_NEW_VIEWPORT;
+       nvfx->draw_dirty |= NVFX_NEW_VIEWPORT;
+ }
+ static void
+ nvfx_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
+                       const struct pipe_vertex_buffer *vb)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       memcpy(nvfx->vtxbuf, vb, sizeof(*vb) * count);
+       nvfx->vtxbuf_nr = count;
+       nvfx->dirty |= NVFX_NEW_ARRAYS;
+       nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
+ }
+ static void *
+ nvfx_vtxelts_state_create(struct pipe_context *pipe,
+                         unsigned num_elements,
+                         const struct pipe_vertex_element *elements)
+ {
+       struct nvfx_vtxelt_state *cso = CALLOC_STRUCT(nvfx_vtxelt_state);
+       assert(num_elements < 16); /* not doing fallbacks yet */
+       cso->num_elements = num_elements;
+       memcpy(cso->pipe, elements, num_elements * sizeof(*elements));
+ /*    nvfx_vtxelt_construct(cso);*/
+       return (void *)cso;
+ }
+ static void
+ nvfx_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso)
+ {
+       FREE(hwcso);
+ }
+ static void
+ nvfx_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso)
+ {
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       nvfx->vtxelt = hwcso;
+       nvfx->dirty |= NVFX_NEW_ARRAYS;
+       /*nvfx->draw_dirty |= NVFX_NEW_ARRAYS;*/
+ }
+ void
+ nvfx_init_state_functions(struct nvfx_context *nvfx)
+ {
+       nvfx->pipe.create_blend_state = nvfx_blend_state_create;
+       nvfx->pipe.bind_blend_state = nvfx_blend_state_bind;
+       nvfx->pipe.delete_blend_state = nvfx_blend_state_delete;
+       nvfx->pipe.create_sampler_state = nvfx_sampler_state_create;
+       nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind;
+       nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete;
+       nvfx->pipe.set_fragment_sampler_textures = nvfx_set_sampler_texture;
+       nvfx->pipe.create_rasterizer_state = nvfx_rasterizer_state_create;
+       nvfx->pipe.bind_rasterizer_state = nvfx_rasterizer_state_bind;
+       nvfx->pipe.delete_rasterizer_state = nvfx_rasterizer_state_delete;
+       nvfx->pipe.create_depth_stencil_alpha_state =
+               nvfx_depth_stencil_alpha_state_create;
+       nvfx->pipe.bind_depth_stencil_alpha_state =
+               nvfx_depth_stencil_alpha_state_bind;
+       nvfx->pipe.delete_depth_stencil_alpha_state =
+               nvfx_depth_stencil_alpha_state_delete;
+       nvfx->pipe.create_vs_state = nvfx_vp_state_create;
+       nvfx->pipe.bind_vs_state = nvfx_vp_state_bind;
+       nvfx->pipe.delete_vs_state = nvfx_vp_state_delete;
+       nvfx->pipe.create_fs_state = nvfx_fp_state_create;
+       nvfx->pipe.bind_fs_state = nvfx_fp_state_bind;
+       nvfx->pipe.delete_fs_state = nvfx_fp_state_delete;
+       nvfx->pipe.set_blend_color = nvfx_set_blend_color;
+         nvfx->pipe.set_stencil_ref = nvfx_set_stencil_ref;
+       nvfx->pipe.set_clip_state = nvfx_set_clip_state;
+       nvfx->pipe.set_constant_buffer = nvfx_set_constant_buffer;
+       nvfx->pipe.set_framebuffer_state = nvfx_set_framebuffer_state;
+       nvfx->pipe.set_polygon_stipple = nvfx_set_polygon_stipple;
+       nvfx->pipe.set_scissor_state = nvfx_set_scissor_state;
+       nvfx->pipe.set_viewport_state = nvfx_set_viewport_state;
+       nvfx->pipe.create_vertex_elements_state = nvfx_vtxelts_state_create;
+       nvfx->pipe.delete_vertex_elements_state = nvfx_vtxelts_state_delete;
+       nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind;
+       nvfx->pipe.set_vertex_buffers = nvfx_set_vertex_buffers;
+ }
index fc8a8a27738205c14997034edb3fcc7fb5aaf7c8,d8c64dd90019bbf2b69ccbf37fb71cede8d4a3a6..0a3f0f45c032fbd02f8c757e0c0e596135f5d18a
@@@ -1034,12 -1042,12 +1042,12 @@@ validate
          }
      }
      /* ...textures... */
 -    for (i = 0; i < texstate->count; i++) {
 -        tex = texstate->textures[i];
 -        if (!tex || !texstate->sampler_states[i])
 +    for (i = 0; i < r300->fragment_sampler_view_count; i++) {
 +        if (!r300->fragment_sampler_views[i])
              continue;
-         if (!r300->winsys->add_buffer(r300->winsys, tex->buffer,
-                     RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) {
 +        tex = (struct r300_texture *)r300->fragment_sampler_views[i]->texture;
+         if (!r300_add_texture(r300->rws, tex,
+                             RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) {
              r300->context.flush(&r300->context, 0, NULL);
              goto validate;
          }
Simple merge