nvfx: support both sprite coord origins
authorLuca Barbieri <luca@luca-barbieri.com>
Sun, 22 Aug 2010 21:29:34 +0000 (23:29 +0200)
committerLuca Barbieri <luca@luca-barbieri.com>
Sun, 22 Aug 2010 22:15:03 +0000 (00:15 +0200)
Now we lie less when claiming OpenGL 2 support.

Also, first piglit result group is now all green, except for
fdo25614-genmipmap, which seems mesa/st's fault.

src/gallium/drivers/nvfx/nvfx_fragprog.c
src/gallium/drivers/nvfx/nvfx_state.c
src/gallium/drivers/nvfx/nvfx_state.h

index 47df71f2325ab385d116cb82ead5832517e5018e..12b002a8198a3eedc2c8c9c5a3d77dad0eedbf32 100644 (file)
@@ -25,6 +25,7 @@ struct nvfx_fpc {
        unsigned long long r_temps_discard;
        struct nvfx_reg r_result[PIPE_MAX_SHADER_OUTPUTS];
        struct nvfx_reg *r_temp;
+       unsigned sprite_coord_temp;
 
        int num_regs;
 
@@ -114,9 +115,10 @@ emit_src(struct nvfx_fpc *fpc, int pos, struct nvfx_src src)
                sr |= (src.reg.index << NVFX_FP_REG_SRC_SHIFT);
                break;
        case NVFXSR_RELOCATED:
-               sr |= (NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT);
+               sr |= (NVFX_FP_REG_TYPE_TEMP << NVFX_FP_REG_TYPE_SHIFT);
+               sr |= (fpc->sprite_coord_temp << NVFX_FP_REG_SRC_SHIFT);
                //printf("adding relocation at %x for %x\n", fpc->inst_offset, src.index);
-               util_dynarray_append(&fpc->fp->slot_relocations[src.reg.index], unsigned, fpc->inst_offset);
+               util_dynarray_append(&fpc->fp->slot_relocations[src.reg.index], unsigned, fpc->inst_offset + pos + 1);
                break;
        case NVFXSR_CONST:
                if (!fpc->have_const) {
@@ -1003,7 +1005,8 @@ DEBUG_GET_ONCE_BOOL_OPTION(nvfx_dump_fp, "NVFX_DUMP_FP", FALSE)
 
 static struct nvfx_fragment_program*
 nvfx_fragprog_translate(struct nvfx_context *nvfx,
-                       struct nvfx_pipe_fragment_program *pfp)
+                       struct nvfx_pipe_fragment_program *pfp,
+                       boolean emulate_sprite_flipping)
 {
        struct tgsi_parse_context parse;
        struct nvfx_fpc *fpc = NULL;
@@ -1027,8 +1030,20 @@ nvfx_fragprog_translate(struct nvfx_context *nvfx,
                goto out_err;
 
        tgsi_parse_init(&parse, pfp->pipe.tokens);
-
        util_dynarray_init(&insns);
+
+       if(emulate_sprite_flipping)
+       {
+               struct nvfx_reg reg = temp(fpc);
+               struct nvfx_src sprite_input = nvfx_src(nvfx_reg(NVFXSR_RELOCATED, fp->num_slots));
+               float v[4] = {1, -1, 0, 0};
+               struct nvfx_src imm = nvfx_src(constant(fpc, -1, v));
+
+               fpc->sprite_coord_temp = reg.index;
+               fpc->r_temps_discard = 0ULL;
+               nvfx_fp_emit(fpc, arith(0, MAD, reg, NVFX_FP_MASK_ALL, sprite_input, swz(imm, X, Y, X, X), swz(imm, Z, X, Z, Z)));
+       }
+
        while (!tgsi_parse_end_of_tokens(&parse)) {
                tgsi_parse_token(&parse);
 
@@ -1166,14 +1181,16 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
        struct nouveau_channel* chan = nvfx->screen->base.channel;
        struct nvfx_pipe_fragment_program *pfp = nvfx->fragprog;
        struct nvfx_vertex_program* vp;
-       unsigned sprite_coord_enable;
-       unsigned key = 0;
+       unsigned sprite_coord_enable = nvfx->rasterizer->pipe.point_quad_rasterization * nvfx->rasterizer->pipe.sprite_coord_enable;
+       // TODO: correct or flipped?
+       boolean emulate_sprite_flipping = sprite_coord_enable && nvfx->rasterizer->pipe.sprite_coord_mode;
+       unsigned key = emulate_sprite_flipping;
        struct nvfx_fragment_program* fp;
 
        fp = pfp->fps[key];
        if (!fp)
        {
-               fp = nvfx_fragprog_translate(nvfx, pfp);
+               fp = nvfx_fragprog_translate(nvfx, pfp, emulate_sprite_flipping);
 
                if(!fp)
                {
@@ -1193,7 +1210,8 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
                                }
                        }
 
-                       fp = nvfx_fragprog_translate(nvfx, nvfx->dummy_fs);
+                       fp = nvfx_fragprog_translate(nvfx, nvfx->dummy_fs, FALSE);
+                       emulate_sprite_flipping = FALSE;
 
                        if(!fp)
                        {
@@ -1205,21 +1223,19 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
                pfp->fps[key] = fp;
        }
 
-       nvfx->hw_fragprog = fp;
-
        vp = nvfx->render_mode == HW ? nvfx->vertprog : nvfx->swtnl.vertprog;
-        sprite_coord_enable = nvfx->rasterizer->pipe.point_quad_rasterization * nvfx->rasterizer->pipe.sprite_coord_enable;
 
        if (fp->last_vp_id != vp->id || fp->last_sprite_coord_enable != sprite_coord_enable) {
-               int sprite_input = -1;
+               int sprite_real_input = -1;
+               int sprite_reloc_input;
                unsigned i;
                fp->last_vp_id = vp->id;
                fp->last_sprite_coord_enable = sprite_coord_enable;
 
                if(sprite_coord_enable)
                {
-                       sprite_input = vp->sprite_fp_input;
-                       if(sprite_input < 0)
+                       sprite_real_input = vp->sprite_fp_input;
+                       if(sprite_real_input < 0)
                        {
                                unsigned used_texcoords = 0;
                                for(unsigned i = 0; i < fp->num_slots; ++i) {
@@ -1232,19 +1248,24 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
                                        }
                                }
 
-                               sprite_input = NVFX_FP_OP_INPUT_SRC_TC(__builtin_ctz(~used_texcoords));
+                               sprite_real_input = NVFX_FP_OP_INPUT_SRC_TC(__builtin_ctz(~used_texcoords));
                        }
 
-                       fp->point_sprite_control |= (1 << (sprite_input - NVFX_FP_OP_INPUT_SRC_TC0 + 8));
+                       fp->point_sprite_control |= (1 << (sprite_real_input - NVFX_FP_OP_INPUT_SRC_TC0 + 8));
                }
                else
                        fp->point_sprite_control = 0;
 
+               if(emulate_sprite_flipping)
+                  sprite_reloc_input = 0;
+               else
+                  sprite_reloc_input = sprite_real_input;
+
                for(i = 0; i < fp->num_slots; ++i) {
                        unsigned generic = fp->slot_to_generic[i];
                        if((1 << generic) & sprite_coord_enable)
                        {
-                               if(fp->slot_to_fp_input[i] != sprite_input)
+                               if(fp->slot_to_fp_input[i] != sprite_reloc_input)
                                        goto update_slots;
                        }
                        else
@@ -1255,6 +1276,12 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx)
                        }
                }
 
+               if(emulate_sprite_flipping)
+               {
+                       if(fp->slot_to_fp_input[fp->num_slots] != sprite_real_input)
+                               goto update_slots;
+               }
+
                if(0)
                {
 update_slots:
@@ -1263,21 +1290,23 @@ update_slots:
                        {
                                unsigned generic = fp->slot_to_generic[i];
                                if((1 << generic) & sprite_coord_enable)
-                                       fp->slot_to_fp_input[i] = sprite_input;
+                                       fp->slot_to_fp_input[i] = sprite_reloc_input;
                                else
                                        fp->slot_to_fp_input[i] = vp->generic_to_fp_input[generic] & 0xf;
                        }
 
+                       fp->slot_to_fp_input[fp->num_slots] = sprite_real_input;
+
                        if(nvfx->is_nv4x)
                        {
                                fp->or = 0;
-                               for(i = 0; i < fp->num_slots; ++i) {
+                               for(i = 0; i <= fp->num_slots; ++i) {
                                        unsigned fp_input = fp->slot_to_fp_input[i];
                                        if(fp_input == NVFX_FP_OP_INPUT_SRC_TC(8))
                                                fp->or |= (1 << 12);
                                        else if(fp_input == NVFX_FP_OP_INPUT_SRC_TC(9))
                                                fp->or |= (1 << 13);
-                                       else if(fp_input != 0xf)
+                                       else if(fp_input >= NVFX_FP_OP_INPUT_SRC_TC(0) && fp_input <= NVFX_FP_OP_INPUT_SRC_TC(7))
                                                fp->or |= (1 << (fp_input - NVFX_FP_OP_INPUT_SRC_TC0 + 14));
                                }
                        }
@@ -1292,7 +1321,7 @@ update_slots:
          * one bound to this fragment program.
          * Doing such a check would likely be a pessimization.
          */
-       if (nvfx->dirty & (NVFX_NEW_FRAGCONST | NVFX_NEW_FRAGPROG)) {
+       if ((nvfx->hw_fragprog != fp) || (nvfx->dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST))) {
                int offset;
                uint32_t* fpmap;
 
@@ -1365,16 +1394,45 @@ update:
                 */
                if(fp->progs_left_with_obsolete_slot_assignments) {
                        unsigned char* fpbo_slots = &fp->fpbo->slots[fp->bo_prog_idx * 8];
-                       for(unsigned i = 0; i < fp->num_slots; ++i) {
+                       /* also relocate sprite coord slot, if any */
+                       for(unsigned i = 0; i <= fp->num_slots; ++i) {
                                unsigned value = fp->slot_to_fp_input[i];;
                                if(value != fpbo_slots[i]) {
-                                       unsigned* p = (unsigned*)fp->slot_relocations[i].data;
-                                       unsigned* pend = (unsigned*)((char*)fp->slot_relocations[i].data + fp->slot_relocations[i].size);
-                                       for(; p != pend; ++p) {
-                                               unsigned off = *p;
-                                               unsigned dw = fp->insn[off];
-                                               dw = (dw & ~NVFX_FP_OP_INPUT_SRC_MASK) | (value << NVFX_FP_OP_INPUT_SRC_SHIFT);
-                                               nvfx_fp_memcpy(&fpmap[*p], &dw, sizeof(dw));
+                                       unsigned* p;
+                                       unsigned* begin = (unsigned*)fp->slot_relocations[i].data;
+                                       unsigned* end = (unsigned*)((char*)fp->slot_relocations[i].data + fp->slot_relocations[i].size);
+                                       //printf("fp %p reloc slot %u/%u: %u -> %u\n", fp, i, fp->num_slots, fpbo_slots[i], value);
+                                       if(value == 0)
+                                       {
+                                               /* was relocated to an input, switch type to temporary */
+                                               for(p = begin; p != end; ++p) {
+                                                       unsigned off = *p;
+                                                       unsigned dw = fp->insn[off];
+                                                       dw &=~ NVFX_FP_REG_TYPE_MASK;
+                                                       //printf("reloc_tmp at %x\n", off);
+                                                       nvfx_fp_memcpy(&fpmap[off], &dw, sizeof(dw));
+                                               }
+                                       } else {
+                                               if(!fpbo_slots[i])
+                                               {
+                                                       /* was relocated to a temporary, switch type to input */
+                                                       for(p= begin; p != end; ++p) {
+                                                               unsigned off = *p;
+                                                               unsigned dw = fp->insn[off];
+                                                               //printf("reloc_in at %x\n", off);
+                                                               dw |= NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT;
+                                                               nvfx_fp_memcpy(&fpmap[off], &dw, sizeof(dw));
+                                                       }
+                                               }
+
+                                               /* set the correct input index */
+                                               for(p = begin; p != end; ++p) {
+                                                       unsigned off = *p & ~3;
+                                                       unsigned dw = fp->insn[off];
+                                                       //printf("reloc&~3 at %x\n", off);
+                                                       dw = (dw & ~NVFX_FP_OP_INPUT_SRC_MASK) | (value << NVFX_FP_OP_INPUT_SRC_SHIFT);
+                                                       nvfx_fp_memcpy(&fpmap[off], &dw, sizeof(dw));
+                                               }
                                        }
                                        fpbo_slots[i] = value;
                                }
@@ -1382,6 +1440,8 @@ update:
                        --fp->progs_left_with_obsolete_slot_assignments;
                }
 
+               nvfx->hw_fragprog = fp;
+
                MARK_RING(chan, 8, 1);
                OUT_RING(chan, RING_3D(NV34TCL_FP_ACTIVE_PROGRAM, 1));
                OUT_RELOC(chan, fp->fpbo->bo, offset, NOUVEAU_BO_VRAM |
@@ -1491,15 +1551,18 @@ nvfx_fp_state_bind(struct pipe_context *pipe, void *hwcso)
 static void
 nvfx_fp_state_delete(struct pipe_context *pipe, void *hwcso)
 {
-        struct nvfx_context *nvfx = nvfx_context(pipe);
-        struct nvfx_pipe_fragment_program *pfp = hwcso;
-        unsigned i;
-
-        for(i = 0; i < Elements(pfp->fps); ++i)
-        {
-               nvfx_fragprog_destroy(nvfx, pfp->fps[i]);
-               FREE(pfp->fps[i]);
-        }
+       struct nvfx_context *nvfx = nvfx_context(pipe);
+       struct nvfx_pipe_fragment_program *pfp = hwcso;
+       unsigned i;
+
+       for(i = 0; i < Elements(pfp->fps); ++i)
+       {
+               if(pfp->fps[i])
+               {
+                       nvfx_fragprog_destroy(nvfx, pfp->fps[i]);
+                       FREE(pfp->fps[i]);
+               }
+       }
 
         FREE((void*)pfp->pipe.tokens);
         FREE(pfp);
index cb32e503c8f4c2c68a51c7299bffd2d58fea11b7..5bd7dc07f02ac16f56020c6459ddbd3936f566bd 100644 (file)
@@ -174,7 +174,8 @@ nvfx_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
                }
 
                if(((struct nvfx_rasterizer_state*)hwcso)->pipe.point_quad_rasterization != nvfx->rasterizer->pipe.point_quad_rasterization
-                               || ((struct nvfx_rasterizer_state*)hwcso)->pipe.sprite_coord_enable != nvfx->rasterizer->pipe.sprite_coord_enable)
+                               || ((struct nvfx_rasterizer_state*)hwcso)->pipe.sprite_coord_enable != nvfx->rasterizer->pipe.sprite_coord_enable
+                               || ((struct nvfx_rasterizer_state*)hwcso)->pipe.sprite_coord_mode != nvfx->rasterizer->pipe.sprite_coord_mode)
                {
                        nvfx->dirty |= NVFX_NEW_SPRITE;
                }
index fd2174ed69045d9748d7957fd5726e1fc843f301..37951919182f99fd81eff575a0dd522d3875d0f9 100644 (file)
@@ -71,10 +71,11 @@ struct nvfx_fragment_program {
        struct nvfx_fragment_program_data *consts;
        unsigned nr_consts;
 
+       /* the slot at num_slots is for the sprite coordinate, if any */
        unsigned num_slots; /* how many input semantics? */
-       unsigned char slot_to_generic[8]; /* semantics */
-       unsigned char slot_to_fp_input[8]; /* current assignment of slots for each used semantic */
-       struct util_dynarray slot_relocations[8];
+       unsigned char slot_to_generic[10]; /* semantics */
+       unsigned char slot_to_fp_input[11]; /* current assignment of slots for each used semantic */
+       struct util_dynarray slot_relocations[11];
 
        /* This is reset to progs on any relocation update, and decreases every time we
         * move to a new prog due to a constant update
@@ -99,7 +100,7 @@ struct nvfx_pipe_fragment_program {
         struct pipe_shader_state pipe;
         struct tgsi_shader_info info;
 
-        struct nvfx_fragment_program* fps[1];
+        struct nvfx_fragment_program* fps[2];
 };
 
 #endif