gallium: standardize naming of masks
[mesa.git] / src / gallium / drivers / nv50 / nv50_state.c
index a614ea033587bd63ca6ae168688f3cfd290f2d28..ac236db29834cf3e26333f9b57a88469661ce075 100644 (file)
@@ -1,9 +1,33 @@
+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
 #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 "nv50_context.h"
-#include "nv50_state.h"
+#include "nv50_texture.h"
 
 #include "nouveau/nouveau_stateobj.h"
 
@@ -30,12 +54,12 @@ nv50_blend_state_create(struct pipe_context *pipe,
                        so_data(so, 1);
                so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
                so_data  (so, nvgl_blend_eqn(cso->rgb_func));
-               so_data  (so, nvgl_blend_func(cso->rgb_src_factor));
-               so_data  (so, nvgl_blend_func(cso->rgb_dst_factor));
+               so_data  (so, 0x4000 | nvgl_blend_func(cso->rgb_src_factor));
+               so_data  (so, 0x4000 | nvgl_blend_func(cso->rgb_dst_factor));
                so_data  (so, nvgl_blend_eqn(cso->alpha_func));
-               so_data  (so, nvgl_blend_func(cso->alpha_src_factor));
+               so_data  (so, 0x4000 | nvgl_blend_func(cso->alpha_src_factor));
                so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
-               so_data  (so, nvgl_blend_func(cso->alpha_dst_factor));
+               so_data  (so, 0x4000 | nvgl_blend_func(cso->alpha_dst_factor));
        }
 
        if (cso->logicop_enable == 0 ) {
@@ -82,27 +106,137 @@ nv50_blend_state_delete(struct pipe_context *pipe, void *hwcso)
        FREE(bso);
 }
 
+static INLINE unsigned
+wrap_mode(unsigned wrap)
+{
+       switch (wrap) {
+       case PIPE_TEX_WRAP_REPEAT:
+               return NV50TSC_1_0_WRAPS_REPEAT;
+       case PIPE_TEX_WRAP_MIRROR_REPEAT:
+               return NV50TSC_1_0_WRAPS_MIRROR_REPEAT;
+       case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+               return NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE;
+       case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+               return NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER;
+       case PIPE_TEX_WRAP_CLAMP:
+               return NV50TSC_1_0_WRAPS_CLAMP;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+               return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+               return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER;
+       case PIPE_TEX_WRAP_MIRROR_CLAMP:
+               return NV50TSC_1_0_WRAPS_MIRROR_CLAMP;
+       default:
+               NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+               return NV50TSC_1_0_WRAPS_REPEAT;
+       }
+}
 static void *
 nv50_sampler_state_create(struct pipe_context *pipe,
                          const struct pipe_sampler_state *cso)
 {
-       return NULL;
+       unsigned *tsc = CALLOC(8, sizeof(unsigned));
+
+       tsc[0] = (0x00024000 |
+                 (wrap_mode(cso->wrap_s) << 0) |
+                 (wrap_mode(cso->wrap_t) << 3) |
+                 (wrap_mode(cso->wrap_r) << 6));
+
+       switch (cso->mag_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               tsc[1] |= NV50TSC_1_1_MAGF_LINEAR;
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               tsc[1] |= NV50TSC_1_1_MAGF_NEAREST;
+               break;
+       }
+
+       switch (cso->min_img_filter) {
+       case PIPE_TEX_FILTER_LINEAR:
+               tsc[1] |= NV50TSC_1_1_MINF_LINEAR;
+               break;
+       case PIPE_TEX_FILTER_NEAREST:
+       default:
+               tsc[1] |= NV50TSC_1_1_MINF_NEAREST;
+               break;
+       }
+
+       switch (cso->min_mip_filter) {
+       case PIPE_TEX_MIPFILTER_LINEAR:
+               tsc[1] |= NV50TSC_1_1_MIPF_LINEAR;
+               break;
+       case PIPE_TEX_MIPFILTER_NEAREST:
+               tsc[1] |= NV50TSC_1_1_MIPF_NEAREST;
+               break;
+       case PIPE_TEX_MIPFILTER_NONE:
+       default:
+               tsc[1] |= NV50TSC_1_1_MIPF_NONE;
+               break;
+       }
+
+       if (cso->max_anisotropy >= 16.0)
+               tsc[0] |= (7 << 20);
+       else
+       if (cso->max_anisotropy >= 12.0)
+               tsc[0] |= (6 << 20);
+       else
+       if (cso->max_anisotropy >= 10.0)
+               tsc[0] |= (5 << 20);
+       else
+       if (cso->max_anisotropy >= 8.0)
+               tsc[0] |= (4 << 20);
+       else
+       if (cso->max_anisotropy >= 6.0)
+               tsc[0] |= (3 << 20);
+       else
+       if (cso->max_anisotropy >= 4.0)
+               tsc[0] |= (2 << 20);
+       else
+       if (cso->max_anisotropy >= 2.0)
+               tsc[0] |= (1 << 20);
+
+       if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+               tsc[0] |= (1 << 8);
+               tsc[0] |= (nvgl_comparison_op(cso->compare_func) & 0x7);
+       }
+
+       return (void *)tsc;
 }
 
 static void
 nv50_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+       int i;
+
+       nv50->sampler_nr = nr;
+       for (i = 0; i < nv50->sampler_nr; i++)
+               nv50->sampler[i] = sampler[i];
+
+       nv50->dirty |= NV50_NEW_SAMPLER;
 }
 
 static void
 nv50_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
 {
+       FREE(hwcso);
 }
 
 static void
 nv50_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
                         struct pipe_texture **pt)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+       int i;
+
+       for (i = 0; i < nr; i++)
+               pipe_texture_reference((void *)&nv50->miptree[i], pt[i]);
+       for (i = nr; i < nv50->miptree_nr; i++)
+               pipe_texture_reference((void *)&nv50->miptree[i], NULL);
+
+       nv50->miptree_nr = nr;
+       nv50->dirty |= NV50_NEW_TEXTURE;
 }
 
 static void *
@@ -113,7 +247,6 @@ nv50_rasterizer_state_create(struct pipe_context *pipe,
        struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
        struct nv50_rasterizer_stateobj *rso =
                CALLOC_STRUCT(nv50_rasterizer_stateobj);
-       unsigned i;
 
        /*XXX: ignored
         *      - light_twosize
@@ -134,7 +267,7 @@ nv50_rasterizer_state_create(struct pipe_context *pipe,
                so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
                so_data  (so, 1);
                so_method(so, tesla, NV50TCL_LINE_STIPPLE_PATTERN, 1);
-               so_data  (so, (cso->line_stipple_pattern << 16) |
+               so_data  (so, (cso->line_stipple_pattern << 8) |
                               cso->line_stipple_factor);
        } else {
                so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
@@ -214,7 +347,7 @@ nv50_rasterizer_state_create(struct pipe_context *pipe,
                so_method(so, tesla, NV50TCL_POLYGON_OFFSET_FACTOR, 1);
                so_data  (so, fui(cso->offset_scale));
                so_method(so, tesla, NV50TCL_POLYGON_OFFSET_UNITS, 1);
-               so_data  (so, fui(cso->offset_units * 2));
+               so_data  (so, fui(cso->offset_units));
        }
 
        rso->pipe = *cso;
@@ -260,34 +393,35 @@ nv50_depth_stencil_alpha_state_create(struct pipe_context *pipe,
                so_data  (so, 0);
        }
 
+       /*XXX: yes, I know they're backwards.. header needs fixing */
        if (cso->stencil[0].enabled) {
-               so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 5);
+               so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 5);
                so_data  (so, 1);
                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));
                so_data  (so, nvgl_comparison_op(cso->stencil[0].func));
-               so_method(so, tesla, NV50TCL_STENCIL_FRONT_FUNC_REF, 3);
+               so_method(so, tesla, NV50TCL_STENCIL_BACK_FUNC_REF, 3);
                so_data  (so, cso->stencil[0].ref_value);
-               so_data  (so, cso->stencil[0].write_mask);
-               so_data  (so, cso->stencil[0].value_mask);
+               so_data  (so, cso->stencil[0].writemask);
+               so_data  (so, cso->stencil[0].valuemask);
        } else {
-               so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 1);
+               so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 1);
                so_data  (so, 0);
        }
 
        if (cso->stencil[1].enabled) {
-               so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 8);
+               so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 8);
                so_data  (so, 1);
                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));
                so_data  (so, nvgl_comparison_op(cso->stencil[1].func));
                so_data  (so, cso->stencil[1].ref_value);
-               so_data  (so, cso->stencil[1].write_mask);
-               so_data  (so, cso->stencil[1].value_mask);
+               so_data  (so, cso->stencil[1].writemask);
+               so_data  (so, cso->stencil[1].valuemask);
        } else {
-               so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 1);
+               so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 1);
                so_data  (so, 0);
        }
 
@@ -329,34 +463,64 @@ static void *
 nv50_vp_state_create(struct pipe_context *pipe,
                     const struct pipe_shader_state *cso)
 {
-       return NULL;
+       struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+       p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+       p->type = PIPE_SHADER_VERTEX;
+       tgsi_scan_shader(p->pipe.tokens, &p->info);
+       return (void *)p;
 }
 
 static void
 nv50_vp_state_bind(struct pipe_context *pipe, void *hwcso)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->vertprog = hwcso;
+       nv50->dirty |= NV50_NEW_VERTPROG;
 }
 
 static void
 nv50_vp_state_delete(struct pipe_context *pipe, void *hwcso)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+       struct nv50_program *p = hwcso;
+
+       nv50_program_destroy(nv50, p);
+       FREE((void*)p->pipe.tokens);
+       FREE(p);
 }
 
 static void *
 nv50_fp_state_create(struct pipe_context *pipe,
                     const struct pipe_shader_state *cso)
 {
-       return NULL;
+       struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+       p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+       p->type = PIPE_SHADER_FRAGMENT;
+       tgsi_scan_shader(p->pipe.tokens, &p->info);
+       return (void *)p;
 }
 
 static void
 nv50_fp_state_bind(struct pipe_context *pipe, void *hwcso)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       nv50->fragprog = hwcso;
+       nv50->dirty |= NV50_NEW_FRAGPROG;
 }
 
 static void
 nv50_fp_state_delete(struct pipe_context *pipe, void *hwcso)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+       struct nv50_program *p = hwcso;
+
+       nv50_program_destroy(nv50, p);
+       FREE((void*)p->pipe.tokens);
+       FREE(p);
 }
 
 static void
@@ -379,6 +543,16 @@ static void
 nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
                         const struct pipe_constant_buffer *buf )
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       if (shader == PIPE_SHADER_VERTEX) {
+               nv50->constbuf[PIPE_SHADER_VERTEX] = buf->buffer;
+               nv50->dirty |= NV50_NEW_VERTPROG_CB;
+       } else
+       if (shader == PIPE_SHADER_FRAGMENT) {
+               nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
+               nv50->dirty |= NV50_NEW_FRAGPROG_CB;
+       }
 }
 
 static void
@@ -425,12 +599,24 @@ static void
 nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
                        const struct pipe_vertex_buffer *vb)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       memcpy(nv50->vtxbuf, vb, sizeof(*vb) * count);
+       nv50->vtxbuf_nr = count;
+
+       nv50->dirty |= NV50_NEW_ARRAYS;
 }
 
 static void
 nv50_set_vertex_elements(struct pipe_context *pipe, unsigned count,
                         const struct pipe_vertex_element *ve)
 {
+       struct nv50_context *nv50 = nv50_context(pipe);
+
+       memcpy(nv50->vtxelt, ve, sizeof(*ve) * count);
+       nv50->vtxelt_nr = count;
+
+       nv50->dirty |= NV50_NEW_ARRAYS;
 }
 
 void