Merge branch 'mesa_7_6_branch'
[mesa.git] / src / gallium / drivers / nv30 / nv30_state.c
index e65c4b215d4121f013e134e1bc8160579458214b..b91e972c12336783abd0910564f87e011eaf7b31 100644 (file)
@@ -1,6 +1,8 @@
 #include "pipe/p_state.h"
 #include "pipe/p_defines.h"
-#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "tgsi/tgsi_parse.h"
 
 #include "nv30_context.h"
 #include "nv30_state.h"
@@ -21,9 +23,10 @@ nv30_blend_state_create(struct pipe_context *pipe,
                               nvgl_blend_func(cso->rgb_src_factor));
                so_data  (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 |
                              nvgl_blend_func(cso->rgb_dst_factor));
+               /* FIXME: Gallium assumes GL_EXT_blend_func_separate.
+                  It is not the case for NV30 */
                so_method(so, rankine, NV34TCL_BLEND_EQUATION, 1);
-               so_data  (so, nvgl_blend_eqn(cso->alpha_func) << 16 |
-                             nvgl_blend_eqn(cso->rgb_func));
+               so_data  (so, nvgl_blend_eqn(cso->rgb_func));
        } else {
                so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 1);
                so_data  (so, 0);
@@ -48,6 +51,7 @@ nv30_blend_state_create(struct pipe_context *pipe,
        so_data  (so, cso->dither ? 1 : 0);
 
        so_ref(so, &bso->so);
+       so_ref(NULL, &so);
        bso->pipe = *cso;
        return (void *)bso;
 }
@@ -116,41 +120,33 @@ nv30_sampler_state_create(struct pipe_context *pipe,
        struct nv30_sampler_state *ps;
        uint32_t filter = 0;
 
-       ps = malloc(sizeof(struct nv30_sampler_state));
+       ps = MALLOC(sizeof(struct nv30_sampler_state));
 
        ps->fmt = 0;
-       if (!cso->normalized_coords)
-               ps->fmt |= NV34TCL_TX_FORMAT_RECT;
+       /* TODO: Not all RECTs formats have this bit set, bits 15-8 of format
+          are the tx format to use. We should store normalized coord flag
+          in sampler state structure, and set appropriate format in
+          nvxx_fragtex_build()
+        */
+       /*NV34TCL_TX_FORMAT_RECT*/
+       /*if (!cso->normalized_coords) {
+               ps->fmt |= (1<<14) ;
+       }*/
 
        ps->wrap = ((wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) |
                    (wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) |
                    (wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT));
 
        ps->en = 0;
+
+       if (cso->max_anisotropy >= 8.0) {
+               ps->en |= NV34TCL_TX_ENABLE_ANISO_8X;
+       } else
+       if (cso->max_anisotropy >= 4.0) {
+               ps->en |= NV34TCL_TX_ENABLE_ANISO_4X;
+       } else
        if (cso->max_anisotropy >= 2.0) {
-               /* no idea, binary driver sets it, works without it.. meh.. */
-               ps->wrap |= (1 << 5);
-
-/*             if (cso->max_anisotropy >= 16.0) {
-                       ps->en |= NV34TCL_TX_ENABLE_ANISO_16X;
-               } else
-               if (cso->max_anisotropy >= 12.0) {
-                       ps->en |= NV34TCL_TX_ENABLE_ANISO_12X;
-               } else
-               if (cso->max_anisotropy >= 10.0) {
-                       ps->en |= NV34TCL_TX_ENABLE_ANISO_10X;
-               } else
-               if (cso->max_anisotropy >= 8.0) {
-                       ps->en |= NV34TCL_TX_ENABLE_ANISO_8X;
-               } else
-               if (cso->max_anisotropy >= 6.0) {
-                       ps->en |= NV34TCL_TX_ENABLE_ANISO_6X;
-               } else
-               if (cso->max_anisotropy >= 4.0) {
-                       ps->en |= NV34TCL_TX_ENABLE_ANISO_4X;
-               } else {
-                       ps->en |= NV34TCL_TX_ENABLE_ANISO_2X;
-               }*/
+               ps->en |= NV34TCL_TX_ENABLE_ANISO_2X;
        }
 
        switch (cso->mag_img_filter) {
@@ -197,7 +193,20 @@ nv30_sampler_state_create(struct pipe_context *pipe,
 
        ps->filt = filter;
 
-/*     if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+       {
+               float limit;
+
+               limit = CLAMP(cso->lod_bias, -16.0, 15.0);
+               ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
+
+               limit = CLAMP(cso->max_lod, 0.0, 15.0);
+               ps->en |= (int)(limit) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/;
+
+               limit = CLAMP(cso->min_lod, 0.0, 15.0);
+               ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/;
+       }
+
+       if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
                switch (cso->compare_func) {
                case PIPE_FUNC_NEVER:
                        ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NEVER;
@@ -226,7 +235,7 @@ nv30_sampler_state_create(struct pipe_context *pipe,
                default:
                        break;
                }
-       }*/
+       }
 
        ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) |
                    (float_to_ubyte(cso->border_color[0]) << 16) |
@@ -242,20 +251,24 @@ nv30_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
        struct nv30_context *nv30 = nv30_context(pipe);
        unsigned unit;
 
-       if (!sampler) {
-               return;
-       }
-
        for (unit = 0; unit < nr; unit++) {
                nv30->tex_sampler[unit] = sampler[unit];
                nv30->dirty_samplers |= (1 << unit);
        }
+
+       for (unit = nr; unit < nv30->nr_samplers; unit++) {
+               nv30->tex_sampler[unit] = NULL;
+               nv30->dirty_samplers |= (1 << unit);
+       }
+
+       nv30->nr_samplers = nr;
+       nv30->dirty |= NV30_NEW_SAMPLER;
 }
 
 static void
 nv30_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
 {
-       free(hwcso);
+       FREE(hwcso);
 }
 
 static void
@@ -266,9 +279,19 @@ nv30_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
        unsigned unit;
 
        for (unit = 0; unit < nr; unit++) {
-               nv30->tex_miptree[unit] = (struct nv30_miptree *)miptree[unit];
+               pipe_texture_reference((struct pipe_texture **)
+                                      &nv30->tex_miptree[unit], miptree[unit]);
+               nv30->dirty_samplers |= (1 << unit);
+       }
+
+       for (unit = nr; unit < nv30->nr_textures; unit++) {
+               pipe_texture_reference((struct pipe_texture **)
+                                      &nv30->tex_miptree[unit], NULL);
                nv30->dirty_samplers |= (1 << unit);
        }
+
+       nv30->nr_textures = nr;
+       nv30->dirty |= NV30_NEW_SAMPLER;
 }
 
 static void *
@@ -382,6 +405,7 @@ nv30_rasterizer_state_create(struct pipe_context *pipe,
        }
 
        so_ref(so, &rsso->so);
+       so_ref(NULL, &so);
        rsso->pipe = *cso;
        return (void *)rsso;
 }
@@ -422,15 +446,15 @@ nv30_depth_stencil_alpha_state_create(struct pipe_context *pipe,
        so_method(so, rankine, 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));
+       so_data  (so, float_to_ubyte(cso->alpha.ref_value));
 
        if (cso->stencil[0].enabled) {
                so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 8);
                so_data  (so, cso->stencil[0].enabled ? 1 : 0);
-               so_data  (so, cso->stencil[0].write_mask);
+               so_data  (so, cso->stencil[0].writemask);
                so_data  (so, nvgl_comparison_op(cso->stencil[0].func));
                so_data  (so, cso->stencil[0].ref_value);
-               so_data  (so, cso->stencil[0].value_mask);
+               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));
@@ -442,10 +466,10 @@ nv30_depth_stencil_alpha_state_create(struct pipe_context *pipe,
        if (cso->stencil[1].enabled) {
                so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 8);
                so_data  (so, cso->stencil[1].enabled ? 1 : 0);
-               so_data  (so, cso->stencil[1].write_mask);
+               so_data  (so, cso->stencil[1].writemask);
                so_data  (so, nvgl_comparison_op(cso->stencil[1].func));
                so_data  (so, cso->stencil[1].ref_value);
-               so_data  (so, cso->stencil[1].value_mask);
+               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));
@@ -455,6 +479,7 @@ nv30_depth_stencil_alpha_state_create(struct pipe_context *pipe,
        }
 
        so_ref(so, &zsaso->so);
+       so_ref(NULL, &so);
        zsaso->pipe = *cso;
        return (void *)zsaso;
 }
@@ -481,10 +506,12 @@ static void *
 nv30_vp_state_create(struct pipe_context *pipe,
                     const struct pipe_shader_state *cso)
 {
+       /*struct nv30_context *nv30 = nv30_context(pipe);*/
        struct nv30_vertex_program *vp;
 
        vp = CALLOC(1, sizeof(struct nv30_vertex_program));
-       vp->pipe = *cso;
+       vp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+       /*vp->draw = draw_create_vertex_shader(nv30->draw, &vp->pipe);*/
 
        return (void *)vp;
 }
@@ -493,14 +520,10 @@ static void
 nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso)
 {
        struct nv30_context *nv30 = nv30_context(pipe);
-       struct nv30_vertex_program *vp = hwcso;
-
-       if (!hwcso) {
-               return;
-       }
 
-       nv30->vertprog.current = vp;
+       nv30->vertprog = hwcso;
        nv30->dirty |= NV30_NEW_VERTPROG;
+       /*nv30->draw_dirty |= NV30_NEW_VERTPROG;*/
 }
 
 static void
@@ -509,7 +532,9 @@ nv30_vp_state_delete(struct pipe_context *pipe, void *hwcso)
        struct nv30_context *nv30 = nv30_context(pipe);
        struct nv30_vertex_program *vp = hwcso;
 
+       /*draw_delete_vertex_shader(nv30->draw, vp->draw);*/
        nv30_vertprog_destroy(nv30, vp);
+       FREE((void*)vp->pipe.tokens);
        FREE(vp);
 }
 
@@ -520,7 +545,9 @@ nv30_fp_state_create(struct pipe_context *pipe,
        struct nv30_fragment_program *fp;
 
        fp = CALLOC(1, sizeof(struct nv30_fragment_program));
-       fp->pipe = *cso;
+       fp->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+
+       tgsi_scan_shader(fp->pipe.tokens, &fp->info);
 
        return (void *)fp;
 }
@@ -529,13 +556,8 @@ static void
 nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso)
 {
        struct nv30_context *nv30 = nv30_context(pipe);
-       struct nv30_fragment_program *fp = hwcso;
-
-       if (!hwcso) {
-               return;
-       }
 
-       nv30->fragprog.current = fp;
+       nv30->fragprog = hwcso;
        nv30->dirty |= NV30_NEW_FRAGPROG;
 }
 
@@ -546,6 +568,7 @@ nv30_fp_state_delete(struct pipe_context *pipe, void *hwcso)
        struct nv30_fragment_program *fp = hwcso;
 
        nv30_fragprog_destroy(nv30, fp);
+       FREE((void*)fp->pipe.tokens);
        FREE(fp);
 }
 
@@ -571,12 +594,13 @@ nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
 {
        struct nv30_context *nv30 = nv30_context(pipe);
 
+       nv30->constbuf[shader] = buf->buffer;
+       nv30->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float));
+
        if (shader == PIPE_SHADER_VERTEX) {
-               nv30->vertprog.constant_buf = buf->buffer;
                nv30->dirty |= NV30_NEW_VERTPROG;
        } else
        if (shader == PIPE_SHADER_FRAGMENT) {
-               nv30->fragprog.constant_buf = buf->buffer;
                nv30->dirty |= NV30_NEW_FRAGPROG;
        }
 }
@@ -629,7 +653,10 @@ nv30_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
        struct nv30_context *nv30 = nv30_context(pipe);
 
        memcpy(nv30->vtxbuf, vb, sizeof(*vb) * count);
+       nv30->vtxbuf_nr = count;
+
        nv30->dirty |= NV30_NEW_ARRAYS;
+       /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
 }
 
 static void
@@ -639,7 +666,20 @@ nv30_set_vertex_elements(struct pipe_context *pipe, unsigned count,
        struct nv30_context *nv30 = nv30_context(pipe);
 
        memcpy(nv30->vtxelt, ve, sizeof(*ve) * count);
+       nv30->vtxelt_nr = count;
+
+       nv30->dirty |= NV30_NEW_ARRAYS;
+       /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
+}
+
+static void
+nv30_set_edgeflags(struct pipe_context *pipe, const unsigned *bitfield)
+{
+       struct nv30_context *nv30 = nv30_context(pipe);
+
+       nv30->edgeflags = bitfield;
        nv30->dirty |= NV30_NEW_ARRAYS;
+       /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/
 }
 
 void
@@ -681,6 +721,7 @@ nv30_init_state_functions(struct nv30_context *nv30)
        nv30->pipe.set_scissor_state = nv30_set_scissor_state;
        nv30->pipe.set_viewport_state = nv30_set_viewport_state;
 
+       nv30->pipe.set_edgeflags = nv30_set_edgeflags;
        nv30->pipe.set_vertex_buffers = nv30_set_vertex_buffers;
        nv30->pipe.set_vertex_elements = nv30_set_vertex_elements;
 }