gallium: simplify tgsi_full_immediate struct
[mesa.git] / src / gallium / drivers / nv30 / nv30_fragprog.c
index 740d3ab430de451711a224f9e081e53eb8d66f3a..a48ba9782b329e47e32431f5fb48379ed36ef1c3 100644 (file)
@@ -1,11 +1,11 @@
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_state.h"
-#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
 
 #include "pipe/p_shader_tokens.h"
-#include "tgsi/util/tgsi_parse.h"
-#include "tgsi/util/tgsi_util.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_util.h"
 
 #include "nv30_context.h"
 
@@ -495,10 +495,10 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
        case TGSI_OPCODE_FRC:
                arith(fpc, sat, FRC, dst, mask, src[0], none, none);
                break;
-       case TGSI_OPCODE_KIL:
+       case TGSI_OPCODE_KILP:
                arith(fpc, 0, KIL, none, 0, none, none, none);
                break;
-       case TGSI_OPCODE_KILP:
+       case TGSI_OPCODE_KIL:
                dst = nv30_sr(NV30SR_NONE, 0);
                dst.cc_update = 1;
                arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none);
@@ -527,6 +527,12 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
        case TGSI_OPCODE_MUL:
                arith(fpc, sat, MUL, dst, mask, src[0], src[1], none);
                break;
+       case TGSI_OPCODE_NOISE1:
+       case TGSI_OPCODE_NOISE2:
+       case TGSI_OPCODE_NOISE3:
+       case TGSI_OPCODE_NOISE4:
+               arith(fpc, sat, SFL, dst, mask, none, none, none);
+               break;
        case TGSI_OPCODE_POW:
                arith(fpc, sat, POW, dst, mask, src[0], src[1], none);
                break;
@@ -558,6 +564,9 @@ nv30_fragprog_parse_instruction(struct nv30_fpc *fpc,
        case TGSI_OPCODE_SGE:
                arith(fpc, sat, SGE, dst, mask, src[0], src[1], none);
                break;
+       case TGSI_OPCODE_SGT:
+               arith(fpc, sat, SGT, dst, mask, src[0], src[1], none);
+               break;
        case TGSI_OPCODE_SLT:
                arith(fpc, sat, SLT, dst, mask, src[0], src[1], none);
                break;
@@ -650,30 +659,22 @@ nv30_fragprog_parse_decl_output(struct nv30_fpc *fpc,
        return TRUE;
 }
 
-void
-nv30_fragprog_translate(struct nv30_context *nv30,
-                       struct nv30_fragment_program *fp)
+static boolean
+nv30_fragprog_prepare(struct nv30_fpc *fpc)
 {
-       struct tgsi_parse_context parse;
-       struct nv30_fpc *fpc = NULL;
+       struct tgsi_parse_context p;
+       /*int high_temp = -1, i;*/
 
-       fpc = CALLOC(1, sizeof(struct nv30_fpc));
-       if (!fpc)
-               return;
-       fpc->fp = fp;
-       fpc->high_temp = -1;
-       fpc->num_regs = 2;
-
-       tgsi_parse_init(&parse, fp->pipe.tokens);
-
-       while (!tgsi_parse_end_of_tokens(&parse)) {
-               tgsi_parse_token(&parse);
+       tgsi_parse_init(&p, fpc->fp->pipe.tokens);
+       while (!tgsi_parse_end_of_tokens(&p)) {
+               const union tgsi_full_token *tok = &p.FullToken;
 
-               switch (parse.FullToken.Token.Type) {
+               tgsi_parse_token(&p);
+               switch(tok->Token.Type) {
                case TGSI_TOKEN_TYPE_DECLARATION:
                {
                        const struct tgsi_full_declaration *fdec;
-                       fdec = &parse.FullToken.FullDeclaration;
+                       fdec = &p.FullToken.FullDeclaration;
                        switch (fdec->Declaration.File) {
                        case TGSI_FILE_INPUT:
                                if (!nv30_fragprog_parse_decl_attrib(fpc, fdec))
@@ -683,6 +684,12 @@ nv30_fragprog_translate(struct nv30_context *nv30,
                                if (!nv30_fragprog_parse_decl_output(fpc, fdec))
                                        goto out_err;
                                break;
+                       /*case TGSI_FILE_TEMPORARY:
+                               if (fdec->DeclarationRange.Last > high_temp) {
+                                       high_temp =
+                                               fdec->DeclarationRange.Last;
+                               }
+                               break;*/
                        default:
                                break;
                        }
@@ -692,17 +699,67 @@ nv30_fragprog_translate(struct nv30_context *nv30,
                {
                        struct tgsi_full_immediate *imm;
                        float vals[4];
-                       int i;
                        
-                       imm = &parse.FullToken.FullImmediate;
+                       imm = &p.FullToken.FullImmediate;
                        assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
                        assert(fpc->nr_imm < MAX_IMM);
 
-                       for (i = 0; i < 4; i++)
-                               vals[i] = imm->u.ImmediateFloat32[i].Float;
+                       vals[0] = imm->u[0].Float;
+                       vals[1] = imm->u[1].Float;
+                       vals[2] = imm->u[2].Float;
+                       vals[3] = imm->u[3].Float;
                        fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals);
                }
                        break;
+               default:
+                       break;
+               }
+       }
+       tgsi_parse_free(&p);
+
+       /*if (++high_temp) {
+               fpc->r_temp = CALLOC(high_temp, sizeof(struct nv30_sreg));
+               for (i = 0; i < high_temp; i++)
+                       fpc->r_temp[i] = temp(fpc);
+               fpc->r_temps_discard = 0;
+       }*/
+
+       return TRUE;
+
+out_err:
+       /*if (fpc->r_temp)
+               FREE(fpc->r_temp);*/
+       tgsi_parse_free(&p);
+       return FALSE;
+}
+
+static void
+nv30_fragprog_translate(struct nv30_context *nv30,
+                       struct nv30_fragment_program *fp)
+{
+       struct tgsi_parse_context parse;
+       struct nv30_fpc *fpc = NULL;
+
+       tgsi_dump(fp->pipe.tokens,0);
+
+       fpc = CALLOC(1, sizeof(struct nv30_fpc));
+       if (!fpc)
+               return;
+       fpc->fp = fp;
+       fpc->high_temp = -1;
+       fpc->num_regs = 2;
+
+       if (!nv30_fragprog_prepare(fpc)) {
+               FREE(fpc);
+               return;
+       }
+
+       tgsi_parse_init(&parse, fp->pipe.tokens);
+
+       while (!tgsi_parse_end_of_tokens(&parse)) {
+               tgsi_parse_token(&parse);
+
+               switch (parse.FullToken.Token.Type) {
                case TGSI_TOKEN_TYPE_INSTRUCTION:
                {
                        const struct tgsi_full_instruction *finst;
@@ -738,21 +795,85 @@ out_err:
        FREE(fpc);
 }
 
-void
-nv30_fragprog_bind(struct nv30_context *nv30, struct nv30_fragment_program *fp)
+static void
+nv30_fragprog_upload(struct nv30_context *nv30,
+                    struct nv30_fragment_program *fp)
+{
+       struct pipe_screen *pscreen = nv30->pipe.screen;
+       const uint32_t le = 1;
+       uint32_t *map;
+       int i;
+
+       map = pipe_buffer_map(pscreen, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+#if 0
+       for (i = 0; i < fp->insn_len; i++) {
+               fflush(stdout); fflush(stderr);
+               NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
+               fflush(stdout); fflush(stderr);
+       }
+#endif
+
+       if ((*(const uint8_t *)&le)) {
+               for (i = 0; i < fp->insn_len; i++) {
+                       map[i] = fp->insn[i];
+               }
+       } else {
+               /* Weird swapping for big-endian chips */
+               for (i = 0; i < fp->insn_len; i++) {
+                       map[i] = ((fp->insn[i] & 0xffff) << 16) |
+                                 ((fp->insn[i] >> 16) & 0xffff);
+               }
+       }
+
+       pipe_buffer_unmap(pscreen, fp->buffer);
+}
+
+static boolean
+nv30_fragprog_validate(struct nv30_context *nv30)
 {
-       struct pipe_winsys *ws = nv30->pipe.winsys;
+       struct nv30_fragment_program *fp = nv30->fragprog;
+       struct pipe_buffer *constbuf =
+               nv30->constbuf[PIPE_SHADER_FRAGMENT];
+       struct pipe_screen *pscreen = nv30->pipe.screen;
+       struct nouveau_stateobj *so;
+       boolean new_consts = FALSE;
        int i;
 
+       if (fp->translated)
+               goto update_constants;
+
+       /*nv30->fallback_swrast &= ~NV30_NEW_FRAGPROG;*/
+       nv30_fragprog_translate(nv30, fp);
        if (!fp->translated) {
-               nv30_fragprog_translate(nv30, fp);
-               if (!fp->translated)
-                       assert(0);
+               /*nv30->fallback_swrast |= NV30_NEW_FRAGPROG;*/
+               return FALSE;
        }
 
+       fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4);
+       nv30_fragprog_upload(nv30, fp);
+
+       so = so_new(8, 1);
+       so_method(so, nv30->screen->rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1);
+       so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM |
+                     NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW |
+                     NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0,
+                     NV34TCL_FP_ACTIVE_PROGRAM_DMA1);
+       so_method(so, nv30->screen->rankine, NV34TCL_FP_CONTROL, 1);
+       so_data  (so, fp->fp_control);
+       so_method(so, nv30->screen->rankine, NV34TCL_FP_REG_CONTROL, 1);
+       so_data  (so, fp->fp_reg_control);
+       so_method(so, nv30->screen->rankine, NV34TCL_TX_UNITS_ENABLE, 1);
+       so_data  (so, fp->samplers);
+       so_ref(so, &fp->so);
+       so_ref(NULL, &so);
+
+update_constants:
        if (fp->nr_consts) {
-               float *map = ws->buffer_map(ws, nv30->fragprog.constant_buf,
-                                           PIPE_BUFFER_USAGE_CPU_READ);
+               float *map;
+               
+               map = pipe_buffer_map(pscreen, constbuf,
+                                     PIPE_BUFFER_USAGE_CPU_READ);
                for (i = 0; i < fp->nr_consts; i++) {
                        struct nv30_fragment_program_data *fpd = &fp->consts[i];
                        uint32_t *p = &fp->insn[fpd->offset];
@@ -761,49 +882,20 @@ nv30_fragprog_bind(struct nv30_context *nv30, struct nv30_fragment_program *fp)
                        if (!memcmp(p, cb, 4 * sizeof(float)))
                                continue;
                        memcpy(p, cb, 4 * sizeof(float));
-                       fp->on_hw = 0;
+                       new_consts = TRUE;
                }
-               ws->buffer_unmap(ws, nv30->fragprog.constant_buf);
-       }
-
-       if (!fp->on_hw) {
-               const uint32_t le = 1;
-               uint32_t *map;
-
-               if (!fp->buffer)
-                       fp->buffer = ws->buffer_create(ws, 0x100, 0,
-                                                      fp->insn_len * 4);
-               map = ws->buffer_map(ws, fp->buffer,
-                                    PIPE_BUFFER_USAGE_CPU_WRITE);
+               pipe_buffer_unmap(pscreen, constbuf);
 
-#if 0
-               for (i = 0; i < fp->insn_len; i++) {
-                       NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
-               }
-#endif
-
-               if ((*(const uint8_t *)&le)) {
-                       for (i = 0; i < fp->insn_len; i++) {
-                               map[i] = fp->insn[i];
-                       }
-               } else {
-                       /* Weird swapping for big-endian chips */
-                       for (i = 0; i < fp->insn_len; i++) {
-                               map[i] = ((fp->insn[i] & 0xffff) << 16) |
-                                         ((fp->insn[i] >> 16) & 0xffff);
-                       }
-               }
-
-               ws->buffer_unmap(ws, fp->buffer);
-               fp->on_hw = TRUE;
+               if (new_consts)
+                       nv30_fragprog_upload(nv30, fp);
        }
 
-       BEGIN_RING(rankine, NV34TCL_FP_CONTROL, 1);
-       OUT_RING  (fp->fp_control);
-       BEGIN_RING(rankine, NV34TCL_FP_REG_CONTROL, 1);
-       OUT_RING  (fp->fp_reg_control);
+       if (new_consts || fp->so != nv30->state.hw[NV30_STATE_FRAGPROG]) {
+               so_ref(fp->so, &nv30->state.hw[NV30_STATE_FRAGPROG]);
+               return TRUE;
+       }
 
-       nv30->fragprog.active = fp;
+       return FALSE;
 }
 
 void
@@ -814,3 +906,10 @@ nv30_fragprog_destroy(struct nv30_context *nv30,
                FREE(fp->insn);
 }
 
+struct nv30_state_entry nv30_state_fragprog = {
+       .validate = nv30_fragprog_validate,
+       .dirty = {
+               .pipe = NV30_NEW_FRAGPROG,
+               .hw = NV30_STATE_FRAGPROG
+       }
+};