From ee3d0617f923cd4bcc8bfdc1ce878648480c2679 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 21 Jan 2007 09:13:27 +1100 Subject: nouveau: shader backend branching support for all cards that support it. --- src/mesa/drivers/dri/nouveau/nouveau_shader.h | 5 +++ src/mesa/drivers/dri/nouveau/nv30_vertprog.c | 7 +++++ src/mesa/drivers/dri/nouveau/nv40_fragprog.c | 45 +++++++++++++++++++++++++++ src/mesa/drivers/dri/nouveau/nv40_vertprog.c | 10 ++++++ 4 files changed, 67 insertions(+) (limited to 'src/mesa/drivers') diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/src/mesa/drivers/dri/nouveau/nouveau_shader.h index 08cb7817cf..dfa53cad95 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.h @@ -275,6 +275,11 @@ struct _nvsFunc { void (*SetSaturate) (nvsFunc *); void (*SetLastInst) (nvsFunc *); + void (*SetBranchTarget) (nvsFunc *, int addr); + void (*SetBranchElse) (nvsFunc *, int addr); + void (*SetBranchEnd) (nvsFunc *, int addr); + void (*SetLoopParams) (nvsFunc *, int cnt, int init, int inc); + int (*HasMergedInst) (nvsFunc *); int (*IsLastInst) (nvsFunc *); int (*GetOffsetNext) (nvsFunc *); diff --git a/src/mesa/drivers/dri/nouveau/nv30_vertprog.c b/src/mesa/drivers/dri/nouveau/nv30_vertprog.c index 6ba8e35d55..0b7678f55d 100644 --- a/src/mesa/drivers/dri/nouveau/nv30_vertprog.c +++ b/src/mesa/drivers/dri/nouveau/nv30_vertprog.c @@ -48,6 +48,12 @@ NV30VPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id) /***************************************************************************** * Assembly routines */ +static void +NV30VPSetBranchTarget(nvsFunc *shader, int addr) +{ + shader->inst[2] &= ~NV30_VP_INST_IADDR_MASK; + shader->inst[2] |= (addr << NV30_VP_INST_IADDR_SHIFT); +} /***************************************************************************** * Disassembly routines @@ -349,5 +355,6 @@ NV30VPInitShaderFuncs(nvsFunc * shader) shader->GetCondRegID = NV30VPGetCondRegID; shader->GetBranch = NV30VPGetBranch; + shader->SetBranchTarget = NV30VPSetBranchTarget; } diff --git a/src/mesa/drivers/dri/nouveau/nv40_fragprog.c b/src/mesa/drivers/dri/nouveau/nv40_fragprog.c index 3d58d6b666..8bca6ae938 100644 --- a/src/mesa/drivers/dri/nouveau/nv40_fragprog.c +++ b/src/mesa/drivers/dri/nouveau/nv40_fragprog.c @@ -5,6 +5,47 @@ unsigned int NVFP_TX_BOP_COUNT = 5; struct _op_xlat NVFP_TX_BOP[64]; + +/***************************************************************************** + * Assembly routines + * - These extend the NV30 routines, which are almost identical. NV40 + * just has branching hacked into the instruction set. + */ +static void +NV40FPSetBranchTarget(nvsFunc *shader, int addr) +{ + shader->inst[2] &= ~NV40_FP_OP_IADDR_MASK; + shader->inst[2] |= (addr << NV40_FP_OP_IADDR_SHIFT); +} + +static void +NV40FPSetBranchElse(nvsFunc *shader, int addr) +{ + shader->inst[2] &= ~NV40_FP_OP_ELSE_ID_MASK; + shader->inst[2] |= (addr << NV40_FP_OP_ELSE_ID_SHIFT); +} + +static void +NV40FPSetBranchEnd(nvsFunc *shader, int addr) +{ + shader->inst[3] &= ~NV40_FP_OP_END_ID_MASK; + shader->inst[3] |= (addr << NV40_FP_OP_END_ID_SHIFT); +} + +static void +NV40FPSetLoopParams(nvsFunc *shader, int count, int initial, int increment) +{ + shader->inst[2] &= ~(NV40_FP_OP_LOOP_COUNT_MASK | + NV40_FP_OP_LOOP_INDEX_MASK | + NV40_FP_OP_LOOP_INCR_MASK); + shader->inst[2] |= ((count << NV40_FP_OP_LOOP_COUNT_SHIFT) | + (initial << NV40_FP_OP_LOOP_INDEX_SHIFT) | + (increment << NV40_FP_OP_LOOP_INCR_SHIFT)); +} + +/***************************************************************************** + * Disassembly routines + */ static struct _op_xlat * NV40FPGetOPTXRec(nvsFunc * shader, int merged) { @@ -149,4 +190,8 @@ NV40FPInitShaderFuncs(nvsFunc * shader) shader->GetLoopCount = NV40FPGetLoopCount; shader->GetLoopInitial = NV40FPGetLoopInitial; shader->GetLoopIncrement = NV40FPGetLoopIncrement; + shader->SetBranchTarget = NV40FPSetBranchTarget; + shader->SetBranchElse = NV40FPSetBranchElse; + shader->SetBranchEnd = NV40FPSetBranchEnd; + shader->SetLoopParams = NV40FPSetLoopParams; } diff --git a/src/mesa/drivers/dri/nouveau/nv40_vertprog.c b/src/mesa/drivers/dri/nouveau/nv40_vertprog.c index 0493e18403..1ba1cfd155 100644 --- a/src/mesa/drivers/dri/nouveau/nv40_vertprog.c +++ b/src/mesa/drivers/dri/nouveau/nv40_vertprog.c @@ -227,6 +227,15 @@ NV40VPSetSource(nvsFunc *shader, nvsRegister * src, int pos) } } +static void +NV40VPSetBranchTarget(nvsFunc *shader, int addr) +{ + shader->inst[2] &= ~NV40_VP_INST_IADDRH_MASK; + shader->inst[2] |= ((addr & 0xf8) >> 3) << NV40_VP_INST_IADDRH_SHIFT; + shader->inst[3] &= ~NV40_VP_INST_IADDRL_MASK; + shader->inst[3] |= ((addr & 0x07) << NV40_VP_INST_IADDRL_SHIFT); +} + static void NV40VPInitInstruction(nvsFunc *shader) { @@ -657,6 +666,7 @@ NV40VPInitShaderFuncs(nvsFunc * shader) shader->SetResult = NV40VPSetResult; shader->SetSource = NV40VPSetSource; shader->SetLastInst = NV40VPSetLastInst; + shader->SetBranchTarget = NV40VPSetBranchTarget; shader->HasMergedInst = NV40VPHasMergedInst; shader->GetOpcodeHW = NV40VPGetOpcodeHW; -- cgit v1.2.3 From 029b81742ad474245e18e0b629d669afe588111c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 21 Jan 2007 09:31:00 +1100 Subject: nouveau: kill off shader pass1. It sucks, and we have someone who can do a much better job than I can starting work on it soon. alloc_temp/free_temp is left in pass2 to workaround fragprog temps/outputs overlapping, but this all belongs in the optimiser. --- src/mesa/drivers/dri/nouveau/nouveau_shader.h | 4 - src/mesa/drivers/dri/nouveau/nouveau_shader_1.c | 304 ------------------------ src/mesa/drivers/dri/nouveau/nouveau_shader_2.c | 16 +- 3 files changed, 1 insertion(+), 323 deletions(-) (limited to 'src/mesa/drivers') diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/src/mesa/drivers/dri/nouveau/nouveau_shader.h index dfa53cad95..4b94625286 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.h @@ -56,10 +56,6 @@ typedef struct _nouveauShader { int hw_index_cnt; } params[NVS_MAX_CONSTS]; - struct { - int last_use; - } temps[NVS_MAX_TEMPS]; - /* Pass-private data */ void *pass_rec; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c index 5de9017f58..90c57d3807 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_1.c @@ -1,316 +1,12 @@ -/* - * Copyright (C) 2006 Ben Skeggs. - * - * All Rights Reserved. - * - * 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 (including the - * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. - * - */ - -/* - * Authors: - * Ben Skeggs - */ - #include "glheader.h" #include "macros.h" #include "enums.h" #include "nouveau_shader.h" -#define PASS1_OK 0 -#define PASS1_KILL 1 -#define PASS1_FAIL 2 - -struct pass1_rec { - unsigned int temp[NVS_MAX_TEMPS]; - unsigned int result[NVS_MAX_ATTRIBS]; - unsigned int address[NVS_MAX_ADDRESS]; - unsigned int cc[2]; -}; - -static void -pass1_remove_fragment(nvsPtr nvs, nvsFragmentList *item) -{ - if (item->prev) item->prev->next = item->next; - if (item->next) item->next->prev = item->prev; - if (nvs->list_head == item) nvs->list_head = item->next; - if (nvs->list_tail == item) nvs->list_tail = item->prev; - - nvs->inst_count--; -} - -static int -pass1_result_needed(struct pass1_rec *rec, nvsInstruction *inst) -{ - if (inst->cond_update && rec->cc[inst->cond_reg]) - return 1; - /* Only write components that are read later */ - if (inst->dest.file == NVS_FILE_TEMP) - return (inst->mask & rec->temp[inst->dest.index]); - if (inst->dest.file == NVS_FILE_ADDRESS) - return (inst->mask & rec->address[inst->dest.index]); - /* No point writing result components that are written later */ - if (inst->dest.file == NVS_FILE_RESULT) - return (inst->mask & ~rec->result[inst->dest.index]); - assert(0); -} - -static void -pass1_track_result(struct pass1_rec *rec, nvsInstruction *inst) -{ - if (inst->cond_test) - rec->cc[inst->cond_reg] = 1; - if (inst->dest.file == NVS_FILE_TEMP) { - inst->mask &= rec->temp[inst->dest.index]; - } else if (inst->dest.file == NVS_FILE_RESULT) { - inst->mask &= ~rec->result[inst->dest.index]; - rec->result[inst->dest.index] |= inst->mask; - } else if (inst->dest.file == NVS_FILE_ADDRESS) { - inst->mask &= rec->address[inst->dest.index]; - } -} - -static void -pass1_track_source(nouveauShader *nvs, nvsInstruction *inst, int pos, - unsigned int read) -{ - struct pass1_rec *rec = nvs->pass_rec; - nvsRegister *src = &inst->src[pos]; - unsigned int really_read = 0; - int i,sc; - - /* Account for swizzling */ - for (i=0; i<4; i++) - if (read & (1<swizzle[i]); - - /* Track register reads */ - if (src->file == NVS_FILE_TEMP) { - if (nvs->temps[src->index].last_use == -1) - nvs->temps[src->index].last_use = inst->header.position; - rec->temp [src->index] |= really_read; - } else if (src->indexed) { - rec->address[src->addr_reg] |= (1<addr_comp); - } - - /* Modify swizzle to only access read components */ - /* Find a component that is used.. */ - for (sc=0;sc<4;sc++) - if (really_read & (1<swizzle[i] = sc; -} - -static int -pass1_check_instruction(nouveauShader *nvs, nvsInstruction *inst) -{ - struct pass1_rec *rec = nvs->pass_rec; - unsigned int read0, read1, read2; - - if (inst->op != NVS_OP_KIL) { - if (!pass1_result_needed(rec, inst)) - return PASS1_KILL; - } - pass1_track_result(rec, inst); - - read0 = read1 = read2 = 0; - - switch (inst->op) { - case NVS_OP_FLR: - case NVS_OP_FRC: - case NVS_OP_MOV: - case NVS_OP_SSG: - case NVS_OP_ARL: - read0 = inst->mask; - break; - case NVS_OP_ADD: - case NVS_OP_MAX: - case NVS_OP_MIN: - case NVS_OP_MUL: - case NVS_OP_SEQ: - case NVS_OP_SFL: - case NVS_OP_SGE: - case NVS_OP_SGT: - case NVS_OP_SLE: - case NVS_OP_SLT: - case NVS_OP_SNE: - case NVS_OP_STR: - case NVS_OP_SUB: - read0 = inst->mask; - read1 = inst->mask; - break; - case NVS_OP_CMP: - case NVS_OP_LRP: - case NVS_OP_MAD: - read0 = inst->mask; - read1 = inst->mask; - read2 = inst->mask; - break; - case NVS_OP_XPD: - if (inst->mask & SMASK_X) read0 |= SMASK_Y|SMASK_Z; - if (inst->mask & SMASK_Y) read0 |= SMASK_X|SMASK_Z; - if (inst->mask & SMASK_Z) read0 |= SMASK_X|SMASK_Y; - read1 = read0; - break; - case NVS_OP_COS: - case NVS_OP_EX2: - case NVS_OP_EXP: - case NVS_OP_LG2: - case NVS_OP_LOG: - case NVS_OP_RCC: - case NVS_OP_RCP: - case NVS_OP_RSQ: - case NVS_OP_SCS: - case NVS_OP_SIN: - read0 = SMASK_X; - break; - case NVS_OP_POW: - read0 = SMASK_X; - read1 = SMASK_X; - break; - case NVS_OP_DIV: - read0 = inst->mask; - read1 = SMASK_X; - break; - case NVS_OP_DP2: - read0 = SMASK_X|SMASK_Y; - read1 = SMASK_X|SMASK_Y; - break; - case NVS_OP_DP3: - case NVS_OP_RFL: - read0 = SMASK_X|SMASK_Y|SMASK_Z; - read1 = SMASK_X|SMASK_Y|SMASK_Z; - break; - case NVS_OP_DP4: - read0 = SMASK_ALL; - read1 = SMASK_ALL; - break; - case NVS_OP_DPH: - read0 = SMASK_X|SMASK_Y|SMASK_Z; - read1 = SMASK_ALL; - break; - case NVS_OP_DST: - if (inst->mask & SMASK_Y) read0 = read1 = SMASK_Y; - if (inst->mask & SMASK_Z) read0 |= SMASK_Z; - if (inst->mask & SMASK_W) read1 |= SMASK_W; - break; - case NVS_OP_NRM: - read0 = SMASK_X|SMASK_Y|SMASK_Z; - break; - case NVS_OP_PK2H: - case NVS_OP_PK2US: - read0 = SMASK_X|SMASK_Y; - break; - case NVS_OP_DDX: - case NVS_OP_DDY: - case NVS_OP_UP2H: - case NVS_OP_UP2US: - case NVS_OP_PK4B: - case NVS_OP_PK4UB: - case NVS_OP_UP4B: - case NVS_OP_UP4UB: - read0 = SMASK_ALL; - break; - case NVS_OP_X2D: - read1 = SMASK_X|SMASK_Y; - if (inst->mask & (SMASK_X|SMASK_Z)) { - read0 |= SMASK_X; - read2 |= SMASK_X|SMASK_Y; - } - if (inst->mask & (SMASK_Y|SMASK_W)) { - read0 |= SMASK_Y; - read2 |= SMASK_Z|SMASK_W; - } - break; - case NVS_OP_LIT: - read0 |= SMASK_X|SMASK_Y|SMASK_W; - break; - case NVS_OP_TEX: - case NVS_OP_TXP: - case NVS_OP_TXL: - case NVS_OP_TXB: - read0 = SMASK_ALL; - break; - case NVS_OP_TXD: - read0 = SMASK_ALL; - read1 = SMASK_ALL; - read2 = SMASK_ALL; - break; - case NVS_OP_KIL: - break; - default: - fprintf(stderr, "Unknown sop=%d", inst->op); - return PASS1_FAIL; - } - - /* Any values that are written by this inst can't have been read further up */ - if (inst->dest.file == NVS_FILE_TEMP) - rec->temp[inst->dest.index] &= ~inst->mask; - - if (read0) pass1_track_source(nvs, inst, 0, read0); - if (read1) pass1_track_source(nvs, inst, 1, read1); - if (read2) pass1_track_source(nvs, inst, 2, read2); - - return PASS1_OK; -} - -/* Some basic dead code elimination - * - Remove unused instructions - * - Don't write unused register components - * - Modify swizzles to not reference unneeded components. - */ GLboolean nouveau_shader_pass1(nvsPtr nvs) { - nvsFragmentList *list = nvs->list_tail; - int i; - - for (i=0; itemps[i].last_use = -1; - - nvs->pass_rec = calloc(1, sizeof(struct pass1_rec)); - - while (list) { - assert(list->fragment->type == NVS_INSTRUCTION); - - switch(pass1_check_instruction(nvs, (nvsInstruction *)list->fragment)) { - case PASS1_OK: - break; - case PASS1_KILL: - pass1_remove_fragment(nvs, list); - break; - case PASS1_FAIL: - default: - free(nvs->pass_rec); - nvs->pass_rec = NULL; - return GL_FALSE; - } - - list = list->prev; - } - - free(nvs->pass_rec); - nvs->pass_rec = NULL; return GL_TRUE; } diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c index 2177413b66..0476b05f58 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_2.c @@ -68,29 +68,15 @@ pass2_alloc_hw_temp(nvsPtr nvs) return -1; } -static void -pass2_free_hw_temp(nvsPtr nvs, int reg) -{ - struct pass2_rec *rec = nvs->pass_rec; - rec->hw_temps[reg] = 0; -} - static nvsRegister pass2_mangle_reg(nvsPtr nvs, nvsInstruction *inst, nvsRegister reg) { struct pass2_rec *rec = nvs->pass_rec; if (reg.file == NVS_FILE_TEMP) { - int hwidx; - if (rec->temps[reg.index] == -1) rec->temps[reg.index] = pass2_alloc_hw_temp(nvs); - hwidx = rec->temps[reg.index]; - - if (nvs->temps[reg.index].last_use <= inst->header.position) - pass2_free_hw_temp(nvs, hwidx); - - reg.index = hwidx; + reg.index = rec->temps[reg.index]; } return reg; -- cgit v1.2.3 From 4f800c5bacb9734d3030fe11144c8003ec4f169a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 21 Jan 2007 09:48:33 +1100 Subject: nouveau: rename pass0_arb to pass0. I was expecting to have 2 frontends for the shader code (asm, glsl). With Brian's work on GLSL this is unnecessary :) --- src/mesa/drivers/dri/nouveau/Makefile | 2 +- src/mesa/drivers/dri/nouveau/nouveau_shader.c | 4 +- src/mesa/drivers/dri/nouveau/nouveau_shader.h | 3 +- src/mesa/drivers/dri/nouveau/nouveau_shader_0.c | 710 +++++++++++++++++++++ .../drivers/dri/nouveau/nouveau_shader_0_arb.c | 710 --------------------- 5 files changed, 714 insertions(+), 715 deletions(-) create mode 100644 src/mesa/drivers/dri/nouveau/nouveau_shader_0.c delete mode 100644 src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c (limited to 'src/mesa/drivers') diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile index 7ffba27bac..9718f3bf46 100644 --- a/src/mesa/drivers/dri/nouveau/Makefile +++ b/src/mesa/drivers/dri/nouveau/Makefile @@ -20,7 +20,7 @@ DRIVER_SOURCES = \ nouveau_span.c \ nouveau_state.c \ nouveau_shader.c \ - nouveau_shader_0_arb.c \ + nouveau_shader_0.c \ nouveau_shader_1.c \ nouveau_shader_2.c \ nouveau_tex.c \ diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.c b/src/mesa/drivers/dri/nouveau/nouveau_shader.c index dc366b36c0..e4db115362 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.c @@ -111,7 +111,7 @@ nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs) /* Translate to HW format now if necessary */ if (!nvs->translated) { /* Mesa ASM shader -> nouveauShader */ - if (!nouveau_shader_pass0_arb(ctx, nvs)) + if (!nouveau_shader_pass0(ctx, nvs)) return GL_FALSE; /* Basic dead code elimination + register usage info */ if (!nouveau_shader_pass1(nvs)) @@ -187,7 +187,7 @@ nvsBuildTextShader(GLcontext *ctx, GLenum target, const char *text) &nvs->mesa.fp); } - nouveau_shader_pass0_arb(ctx, nvs); + nouveau_shader_pass0(ctx, nvs); nouveau_shader_pass1(nvs); nouveau_shader_pass2(nvs); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/src/mesa/drivers/dri/nouveau/nouveau_shader.h index 4b94625286..1a971e56bf 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.h @@ -366,8 +366,7 @@ extern void NV40FPInitShaderFuncs(nvsFunc *); extern void nouveauShaderInitFuncs(GLcontext *ctx); -extern GLboolean nouveau_shader_pass0_arb(GLcontext *ctx, nouveauShader *nvs); -extern GLboolean nouveau_shader_pass0_slang(GLcontext *ctx, nouveauShader *nvs); +extern GLboolean nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs); extern GLboolean nouveau_shader_pass1(nvsPtr nvs); extern GLboolean nouveau_shader_pass2(nvsPtr nvs); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c new file mode 100644 index 0000000000..34475cad03 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_shader_0.c @@ -0,0 +1,710 @@ +/* + * Copyright (C) 2006 Ben Skeggs. + * + * All Rights Reserved. + * + * 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 (including the + * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. + * + */ + +/* + * Authors: + * Ben Skeggs + */ + +#include "glheader.h" +#include "macros.h" +#include "enums.h" + +#include "program.h" +#include "programopt.h" +#include "program_instruction.h" + +#include "nouveau_context.h" +#include "nouveau_shader.h" + +static nvsFixedReg _tx_mesa_vp_dst_reg[VERT_RESULT_MAX] = { + NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD, + NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, + NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7, + NVS_FR_POINTSZ, NVS_FR_BFC0, NVS_FR_BFC1, NVS_FR_UNKNOWN /* EDGE */ +}; + +static nvsFixedReg _tx_mesa_fp_dst_reg[FRAG_RESULT_MAX] = { + NVS_FR_FRAGDATA0 /* COLR */, NVS_FR_FRAGDATA0 /* COLH */, + NVS_FR_UNKNOWN /* DEPR */ +}; + +static nvsFixedReg _tx_mesa_vp_src_reg[VERT_ATTRIB_MAX] = { + NVS_FR_POSITION, NVS_FR_WEIGHT, NVS_FR_NORMAL, NVS_FR_COL0, NVS_FR_COL1, + NVS_FR_FOGCOORD, NVS_FR_UNKNOWN /* COLOR_INDEX */, NVS_FR_UNKNOWN, + NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, + NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7, +/* Generic attribs 0-15, aliased to the above */ + NVS_FR_POSITION, NVS_FR_WEIGHT, NVS_FR_NORMAL, NVS_FR_COL0, NVS_FR_COL1, + NVS_FR_FOGCOORD, NVS_FR_UNKNOWN /* COLOR_INDEX */, NVS_FR_UNKNOWN, + NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, + NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7 +}; + +static nvsFixedReg _tx_mesa_fp_src_reg[FRAG_ATTRIB_MAX] = { + NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD, + NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, + NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7 +}; + +static nvsSwzComp _tx_mesa_swizzle[4] = { + NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W +}; + +static nvsOpcode _tx_mesa_opcode[] = { + [OPCODE_ABS] = NVS_OP_ABS, [OPCODE_ADD] = NVS_OP_ADD, + [OPCODE_ARA] = NVS_OP_ARA, [OPCODE_ARL] = NVS_OP_ARL, + [OPCODE_ARL_NV] = NVS_OP_ARL, [OPCODE_ARR] = NVS_OP_ARR, + [OPCODE_CMP] = NVS_OP_CMP, [OPCODE_COS] = NVS_OP_COS, + [OPCODE_DDX] = NVS_OP_DDX, [OPCODE_DDY] = NVS_OP_DDY, + [OPCODE_DP3] = NVS_OP_DP3, [OPCODE_DP4] = NVS_OP_DP4, + [OPCODE_DPH] = NVS_OP_DPH, [OPCODE_DST] = NVS_OP_DST, + [OPCODE_EX2] = NVS_OP_EX2, [OPCODE_EXP] = NVS_OP_EXP, + [OPCODE_FLR] = NVS_OP_FLR, [OPCODE_FRC] = NVS_OP_FRC, + [OPCODE_KIL] = NVS_OP_EMUL, [OPCODE_KIL_NV] = NVS_OP_KIL, + [OPCODE_LG2] = NVS_OP_LG2, [OPCODE_LIT] = NVS_OP_LIT, + [OPCODE_LOG] = NVS_OP_LOG, + [OPCODE_LRP] = NVS_OP_LRP, + [OPCODE_MAD] = NVS_OP_MAD, [OPCODE_MAX] = NVS_OP_MAX, + [OPCODE_MIN] = NVS_OP_MIN, [OPCODE_MOV] = NVS_OP_MOV, + [OPCODE_MUL] = NVS_OP_MUL, + [OPCODE_PK2H] = NVS_OP_PK2H, [OPCODE_PK2US] = NVS_OP_PK2US, + [OPCODE_PK4B] = NVS_OP_PK4B, [OPCODE_PK4UB] = NVS_OP_PK4UB, + [OPCODE_POW] = NVS_OP_POW, [OPCODE_POPA] = NVS_OP_POPA, + [OPCODE_PUSHA] = NVS_OP_PUSHA, + [OPCODE_RCC] = NVS_OP_RCC, [OPCODE_RCP] = NVS_OP_RCP, + [OPCODE_RFL] = NVS_OP_RFL, [OPCODE_RSQ] = NVS_OP_RSQ, + [OPCODE_SCS] = NVS_OP_SCS, [OPCODE_SEQ] = NVS_OP_SEQ, + [OPCODE_SFL] = NVS_OP_SFL, [OPCODE_SGE] = NVS_OP_SGE, + [OPCODE_SGT] = NVS_OP_SGT, [OPCODE_SIN] = NVS_OP_SIN, + [OPCODE_SLE] = NVS_OP_SLE, [OPCODE_SLT] = NVS_OP_SLT, + [OPCODE_SNE] = NVS_OP_SNE, [OPCODE_SSG] = NVS_OP_SSG, + [OPCODE_STR] = NVS_OP_STR, [OPCODE_SUB] = NVS_OP_SUB, + [OPCODE_SWZ] = NVS_OP_MOV, + [OPCODE_TEX] = NVS_OP_TEX, [OPCODE_TXB] = NVS_OP_TXB, + [OPCODE_TXD] = NVS_OP_TXD, + [OPCODE_TXL] = NVS_OP_TXL, [OPCODE_TXP] = NVS_OP_TXP, + [OPCODE_TXP_NV] = NVS_OP_TXP, + [OPCODE_UP2H] = NVS_OP_UP2H, [OPCODE_UP2US] = NVS_OP_UP2US, + [OPCODE_UP4B] = NVS_OP_UP4B, [OPCODE_UP4UB] = NVS_OP_UP4UB, + [OPCODE_X2D] = NVS_OP_X2D, + [OPCODE_XPD] = NVS_OP_XPD +}; + +static nvsCond _tx_mesa_condmask[] = { + NVS_COND_UNKNOWN, NVS_COND_GT, NVS_COND_LT, NVS_COND_UN, NVS_COND_GE, + NVS_COND_LE, NVS_COND_NE, NVS_COND_NE, NVS_COND_TR, NVS_COND_FL +}; + +struct pass0_rec { + int nvs_ipos; + int next_temp; + int swzconst_done; + int swzconst_id; + nvsRegister const_half; +}; + +#define X NVS_SWZ_X +#define Y NVS_SWZ_Y +#define Z NVS_SWZ_Z +#define W NVS_SWZ_W + +static void +pass0_append_fragment(nouveauShader *nvs, nvsFragmentHeader *fragment) +{ + nvsFragmentList *list = calloc(1, sizeof(nvsFragmentList)); + if (!list) + return; + + list->fragment = fragment; + list->prev = nvs->list_tail; + if ( nvs->list_tail) + nvs->list_tail->next = list; + if (!nvs->list_head) + nvs->list_head = list; + nvs->list_tail = list; + + nvs->inst_count++; +} + +static void +pass0_make_reg(nouveauShader *nvs, nvsRegister *reg, + nvsRegFile file, unsigned int index) +{ + struct pass0_rec *rec = nvs->pass_rec; + + /* defaults */ + *reg = nvr_unused; + /* -1 == quick-and-dirty temp alloc */ + if (file == NVS_FILE_TEMP && index == -1) { + index = rec->next_temp++; + assert(index < NVS_MAX_TEMPS); + } + reg->file = file; + reg->index = index; +} + +static void +pass0_make_swizzle(nvsSwzComp *swz, unsigned int mesa) +{ + int i; + + for (i=0;i<4;i++) + swz[i] = _tx_mesa_swizzle[GET_SWZ(mesa, i)]; +} + +static nvsOpcode +pass0_make_opcode(enum prog_opcode op) +{ + if (op > MAX_OPCODE) + return NVS_OP_UNKNOWN; + return _tx_mesa_opcode[op]; +} + +static nvsCond +pass0_make_condmask(GLuint mesa) +{ + if (mesa > COND_FL) + return NVS_COND_UNKNOWN; + return _tx_mesa_condmask[mesa]; +} + +static unsigned int +pass0_make_mask(GLuint mesa_mask) +{ + unsigned int mask = 0; + + if (mesa_mask & WRITEMASK_X) mask |= SMASK_X; + if (mesa_mask & WRITEMASK_Y) mask |= SMASK_Y; + if (mesa_mask & WRITEMASK_Z) mask |= SMASK_Z; + if (mesa_mask & WRITEMASK_W) mask |= SMASK_W; + + return mask; +} + +static nvsTexTarget +pass0_make_tex_target(GLuint mesa) +{ + switch (mesa) { + case TEXTURE_1D_INDEX: return NVS_TEX_TARGET_1D; + case TEXTURE_2D_INDEX: return NVS_TEX_TARGET_2D; + case TEXTURE_3D_INDEX: return NVS_TEX_TARGET_3D; + case TEXTURE_CUBE_INDEX: return NVS_TEX_TARGET_CUBE; + case TEXTURE_RECT_INDEX: return NVS_TEX_TARGET_RECT; + default: + return NVS_TEX_TARGET_UNKNOWN; + } +} + +static void +pass0_make_dst_reg(nvsPtr nvs, nvsRegister *reg, + struct prog_dst_register *dst) +{ + struct gl_program *mesa = (struct gl_program*)&nvs->mesa.vp; + nvsFixedReg sfr; + + switch (dst->File) { + case PROGRAM_OUTPUT: + if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { + sfr = (dst->Index < VERT_RESULT_MAX) ? + _tx_mesa_vp_dst_reg[dst->Index] : NVS_FR_UNKNOWN; + } else { + sfr = (dst->Index < FRAG_RESULT_MAX) ? + _tx_mesa_fp_dst_reg[dst->Index] : NVS_FR_UNKNOWN; + } + pass0_make_reg(nvs, reg, NVS_FILE_RESULT, sfr); + break; + case PROGRAM_TEMPORARY: + pass0_make_reg(nvs, reg, NVS_FILE_TEMP, dst->Index); + break; + case PROGRAM_ADDRESS: + pass0_make_reg(nvs, reg, NVS_FILE_ADDRESS, dst->Index); + break; + default: + fprintf(stderr, "Unknown dest file %d\n", dst->File); + assert(0); + } +} + +static void +pass0_make_src_reg(nvsPtr nvs, nvsRegister *reg, struct prog_src_register *src) +{ + struct gl_program *mesa = (struct gl_program *)&nvs->mesa.vp.Base; + struct gl_program_parameter_list *p = mesa->Parameters; + + *reg = nvr_unused; + + switch (src->File) { + case PROGRAM_INPUT: + reg->file = NVS_FILE_ATTRIB; + if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { + reg->index = (src->Index < VERT_ATTRIB_MAX) ? + _tx_mesa_vp_src_reg[src->Index] : NVS_FR_UNKNOWN; + } else { + reg->index = (src->Index < FRAG_ATTRIB_MAX) ? + _tx_mesa_fp_src_reg[src->Index] : NVS_FR_UNKNOWN; + } + break; + /* All const types seem to get shoved into here, not really sure why */ + case PROGRAM_STATE_VAR: + switch (p->Parameters[src->Index].Type) { + case PROGRAM_NAMED_PARAM: + case PROGRAM_CONSTANT: + nvs->params[src->Index].source_val = NULL; + COPY_4V(nvs->params[src->Index].val, p->ParameterValues[src->Index]); + break; + case PROGRAM_STATE_VAR: + nvs->params[src->Index].source_val = p->ParameterValues[src->Index]; + break; + default: + fprintf(stderr, "Unknown parameter type %d\n", + p->Parameters[src->Index].Type); + assert(0); + break; + } + + if (src->RelAddr) { + reg->indexed = 1; + reg->addr_reg = 0; + reg->addr_comp = NVS_SWZ_X; + } else + reg->indexed = 0; + reg->file = NVS_FILE_CONST; + reg->index = src->Index; + break; + case PROGRAM_TEMPORARY: + reg->file = NVS_FILE_TEMP; + reg->index = src->Index; + break; + default: + fprintf(stderr, "Unknown source type %d\n", src->File); + assert(0); + } + + /* per-component negate handled elsewhere */ + reg->negate = src->NegateBase != 0; + reg->abs = src->Abs; + pass0_make_swizzle(reg->swizzle, src->Swizzle); +} + +static nvsInstruction * +pass0_emit(nouveauShader *nvs, nvsOpcode op, nvsRegister dst, + unsigned int mask, int saturate, + nvsRegister src0, nvsRegister src1, nvsRegister src2) +{ + struct pass0_rec *rec = nvs->pass_rec; + nvsInstruction *sif = NULL; + + /* Seems mesa doesn't explicitly 0 this.. */ + if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB) + saturate = 0; + + sif = calloc(1, sizeof(nvsInstruction)); + if (sif) { + sif->header.type = NVS_INSTRUCTION; + sif->header.position = rec->nvs_ipos++; + sif->op = op; + sif->saturate = saturate; + sif->dest = dst; + sif->mask = mask; + sif->src[0] = src0; + sif->src[1] = src1; + sif->src[2] = src2; + sif->cond = COND_TR; + sif->cond_reg = 0; + sif->cond_test = 0; + sif->cond_update = 0; + pass0_make_swizzle(sif->cond_swizzle, SWIZZLE_NOOP); + pass0_append_fragment(nvs, (nvsFragmentHeader *)sif); + } + + return sif; +} + +static void +pass0_fixup_swizzle(nvsPtr nvs, + struct prog_src_register *src, + unsigned int sm1, + unsigned int sm2) +{ + static const float sc[4] = { 1.0, 0.0, -1.0, 0.0 }; + struct pass0_rec *rec = nvs->pass_rec; + int fixup_1, fixup_2; + nvsRegister sr, dr = nvr_unused; + nvsRegister sm1const, sm2const; + + if (!rec->swzconst_done) { + struct gl_program *prog = &nvs->mesa.vp.Base; + rec->swzconst_id = _mesa_add_unnamed_constant(prog->Parameters, sc, 4); + rec->swzconst_done = 1; + COPY_4V(nvs->params[rec->swzconst_id].val, sc); + } + + fixup_1 = (sm1 != MAKE_SWIZZLE4(0,0,0,0) && sm2 != MAKE_SWIZZLE4(2,2,2,2)); + fixup_2 = (sm2 != MAKE_SWIZZLE4(2,2,2,2)); + + if (src->File != PROGRAM_TEMPORARY && src->File != PROGRAM_INPUT) { + /* We can't use more than one const in an instruction, so move the const + * into a temp, and swizzle from there. + *TODO: should just emit the swizzled const, instead of swizzling it + * in the shader.. would need to reswizzle any state params when they + * change however.. + */ + pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); + pass0_make_src_reg(nvs, &sr, src); + pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0, sr, nvr_unused, nvr_unused); + pass0_make_reg(nvs, &sr, NVS_FILE_TEMP, dr.index); + } else { + if (fixup_1) + src->NegateBase = 0; + pass0_make_src_reg(nvs, &sr, src); + pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); + } + + pass0_make_reg(nvs, &sm1const, NVS_FILE_CONST, rec->swzconst_id); + pass0_make_swizzle(sm1const.swizzle, sm1); + if (fixup_1 && fixup_2) { + /* Any combination with SWIZZLE_ONE */ + pass0_make_reg(nvs, &sm2const, NVS_FILE_CONST, rec->swzconst_id); + pass0_make_swizzle(sm2const.swizzle, sm2); + pass0_emit(nvs, NVS_OP_MAD, dr, SMASK_ALL, 0, sr, sm1const, sm2const); + } else { + /* SWIZZLE_ZERO || arbitrary negate */ + pass0_emit(nvs, NVS_OP_MUL, dr, SMASK_ALL, 0, sr, sm1const, nvr_unused); + } + + src->File = PROGRAM_TEMPORARY; + src->Index = dr.index; + src->Swizzle = SWIZZLE_NOOP; +} + +#define SET_SWZ(fs, cp, c) fs = (fs & ~(0x7<<(cp*3))) | (c<<(cp*3)) +static void +pass0_check_sources(nvsPtr nvs, struct prog_instruction *inst) +{ + unsigned int insrc = -1, constsrc = -1; + int i; + + for (i=0;i<_mesa_num_inst_src_regs(inst->Opcode);i++) { + struct prog_src_register *src = &inst->SrcReg[i]; + unsigned int sm_1 = 0, sm_2 = 0; + nvsRegister sr, dr; + int do_mov = 0, c; + + /* Build up swizzle masks as if we were going to use + * "MAD new, src, const1, const2" to support arbitrary negation + * and SWIZZLE_ZERO/SWIZZLE_ONE. + */ + for (c=0;c<4;c++) { + if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ZERO) { + SET_SWZ(sm_1, c, SWIZZLE_Y); /* 0.0 */ + SET_SWZ(sm_2, c, SWIZZLE_Y); + SET_SWZ(src->Swizzle, c, SWIZZLE_X); + } else if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ONE) { + SET_SWZ(sm_1, c, SWIZZLE_Y); + if (src->NegateBase & (1<Swizzle, c, SWIZZLE_X); + } else { + if (src->NegateBase & (1<File) { + case PROGRAM_INPUT: + if (insrc != -1 && insrc != src->Index) + do_mov = 1; + else insrc = src->Index; + break; + case PROGRAM_STATE_VAR: + if (constsrc != -1 && constsrc != src->Index) + do_mov = 1; + else constsrc = src->Index; + break; + default: + break; + } + + /* Emit any extra ATTRIB/CONST to a temp, and modify the Mesa instruction + * to point at the temp. + */ + if (do_mov) { + pass0_make_src_reg(nvs, &sr, src); + pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); + pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0, + sr, nvr_unused, nvr_unused); + + src->File = PROGRAM_TEMPORARY; + src->Index = dr.index; + src->Swizzle= SWIZZLE_NOOP; + } + } +} + +static GLboolean +pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst) +{ + nvsFunc *shader = nvs->func; + nvsRegister src[3], dest, temp; + nvsInstruction *nvsinst; + struct pass0_rec *rec = nvs->pass_rec; + unsigned int mask = pass0_make_mask(inst->DstReg.WriteMask); + int i, sat; + + sat = (inst->SaturateMode == SATURATE_ZERO_ONE); + + /* Build all the "real" regs for the instruction */ + for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) + pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); + if (inst->Opcode != OPCODE_KIL) + pass0_make_dst_reg(nvs, &dest, &inst->DstReg); + + switch (inst->Opcode) { + case OPCODE_ABS: + if (shader->caps & SCAP_SRC_ABS) + pass0_emit(nvs, NVS_OP_MOV, dest, mask, sat, + nvsAbs(src[0]), nvr_unused, nvr_unused); + else + pass0_emit(nvs, NVS_OP_MAX, dest, mask, sat, + src[0], nvsNegate(src[0]), nvr_unused); + break; + case OPCODE_KIL: + /* This is only in ARB shaders, so we don't have to worry + * about clobbering a CC reg as they aren't supported anyway. + */ + /* MOVC0 temp, src */ + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + nvsinst = pass0_emit(nvs, NVS_OP_MOV, temp, SMASK_ALL, 0, + src[0], nvr_unused, nvr_unused); + nvsinst->cond_update = 1; + nvsinst->cond_reg = 0; + /* KIL_NV (LT0.xyzw) temp */ + nvsinst = pass0_emit(nvs, NVS_OP_KIL, nvr_unused, 0, 0, + nvr_unused, nvr_unused, nvr_unused); + nvsinst->cond = COND_LT; + nvsinst->cond_reg = 0; + nvsinst->cond_test = 1; + pass0_make_swizzle(nvsinst->cond_swizzle, MAKE_SWIZZLE4(0,1,2,3)); + break; + case OPCODE_LIT: + break; + case OPCODE_LRP: + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + pass0_emit(nvs, NVS_OP_MAD, temp, mask, 0, + nvsNegate(src[0]), src[2], src[2]); + pass0_emit(nvs, NVS_OP_MAD, dest, mask, sat, + src[0], src[1], temp); + break; + case OPCODE_POW: + if (shader->SupportsOpcode(shader, NVS_OP_LG2) && + shader->SupportsOpcode(shader, NVS_OP_EX2)) { + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + /* LG2 temp.x, src0.c */ + pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0, + nvsSwizzle(src[0], X, X, X, X), + nvr_unused, + nvr_unused); + /* MUL temp.x, temp.x, src1.c */ + pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0, + nvsSwizzle(temp, X, X, X, X), + nvsSwizzle(src[1], X, X, X, X), + nvr_unused); + /* EX2 dest, temp.x */ + pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat, + nvsSwizzle(temp, X, X, X, X), + nvr_unused, + nvr_unused); + } else { + /* can we use EXP/LOG instead of EX2/LG2?? */ + fprintf(stderr, "Implement POW for NV20 vtxprog!\n"); + return GL_FALSE; + } + break; + case OPCODE_RSQ: + if (rec->const_half.file != NVS_FILE_CONST) { + GLfloat const_half[4] = { 0.5, 0.0, 0.0, 0.0 }; + pass0_make_reg(nvs, &rec->const_half, NVS_FILE_CONST, + _mesa_add_unnamed_constant(nvs->mesa.vp.Base.Parameters, + const_half, 4)); + COPY_4V(nvs->params[rec->const_half.index].val, const_half); + } + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0, + nvsAbs(nvsSwizzle(src[0], X, X, X, X)), + nvr_unused, + nvr_unused); + pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0, + nvsSwizzle(temp, X, X, X, X), + nvsNegate(rec->const_half), + nvr_unused); + pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat, + nvsSwizzle(temp, X, X, X, X), + nvr_unused, + nvr_unused); + break; + case OPCODE_SCS: + if (mask & SMASK_X) + pass0_emit(nvs, NVS_OP_COS, dest, SMASK_X, sat, + nvsSwizzle(src[0], X, X, X, X), + nvr_unused, + nvr_unused); + if (mask & SMASK_Y) + pass0_emit(nvs, NVS_OP_SIN, dest, SMASK_Y, sat, + nvsSwizzle(src[0], X, X, X, X), + nvr_unused, + nvr_unused); + break; + case OPCODE_SUB: + pass0_emit(nvs, NVS_OP_ADD, dest, mask, sat, + src[0], nvsNegate(src[1]), nvr_unused); + break; + case OPCODE_XPD: + pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); + pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_ALL, 0, + nvsSwizzle(src[0], Z, X, Y, Y), + nvsSwizzle(src[1], Y, Z, X, X), + nvr_unused); + pass0_emit(nvs, NVS_OP_MAD, dest, (mask & ~SMASK_W), sat, + nvsSwizzle(src[0], Y, Z, X, X), + nvsSwizzle(src[1], Z, X, Y, Y), + nvsNegate(temp)); + break; + default: + fprintf(stderr, "hw doesn't support opcode \"%s\", and no emulation found\n", + _mesa_opcode_string(inst->Opcode)); + return GL_FALSE; + } + + return GL_TRUE; +} + +static GLboolean +pass0_translate_instructions(nouveauShader *nvs) +{ + struct gl_program *prog = (struct gl_program *)&nvs->mesa.vp; + nvsFunc *shader = nvs->func; + int ipos; + + for (ipos=0; iposNumInstructions; ipos++) { + struct prog_instruction *inst = &prog->Instructions[ipos]; + + if (inst->Opcode == OPCODE_END) + break; + + /* Deal with multiple ATTRIB/PARAM in a single instruction */ + pass0_check_sources(nvs, inst); + + /* Now it's safe to do the prog_instruction->nvsInstruction conversion */ + if (shader->SupportsOpcode(shader, pass0_make_opcode(inst->Opcode))) { + nvsInstruction *nvsinst; + nvsRegister src[3], dest; + int i; + + for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) + pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); + pass0_make_dst_reg(nvs, &dest, &inst->DstReg); + + nvsinst = pass0_emit(nvs, + pass0_make_opcode(inst->Opcode), + dest, + pass0_make_mask(inst->DstReg.WriteMask), + (inst->SaturateMode != SATURATE_OFF), + src[0], src[1], src[2]); + nvsinst->tex_unit = inst->TexSrcUnit; + nvsinst->tex_target = pass0_make_tex_target(inst->TexSrcTarget); + /* TODO when NV_fp/vp is implemented */ + nvsinst->cond = COND_TR; + } else { + if (!pass0_emulate_instruction(nvs, inst)) + return GL_FALSE; + } + } + + return GL_TRUE; +} + +GLboolean +nouveau_shader_pass0(GLcontext *ctx, nouveauShader *nvs) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + struct gl_program *prog = (struct gl_program*)nvs; + struct gl_vertex_program *vp = (struct gl_vertex_program *)prog; + struct gl_fragment_program *fp = (struct gl_fragment_program *)prog; + struct pass0_rec *rec; + int ret; + + switch (prog->Target) { + case GL_VERTEX_PROGRAM_ARB: + nvs->func = &nmesa->VPfunc; + if (vp->IsPositionInvariant) + _mesa_insert_mvp_code(ctx, vp); +#if 0 + if (IS_FIXEDFUNCTION_PROG && CLIP_PLANES_USED) + pass0_insert_ff_clip_planes(); +#endif + break; + case GL_FRAGMENT_PROGRAM_ARB: + nvs->func = &nmesa->FPfunc; + if (fp->FogOption != GL_NONE) + _mesa_append_fog_code(ctx, fp); + break; + default: + fprintf(stderr, "Unknown program type %d", prog->Target); + return GL_FALSE; + } + + rec = calloc(1, sizeof(struct pass0_rec)); + rec->next_temp = prog->NumTemporaries; + nvs->pass_rec = rec; + + ret = pass0_translate_instructions(nvs); + if (!ret) { + /* DESTROY list */ + } + + free(nvs->pass_rec); + return ret; +} + diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c b/src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c deleted file mode 100644 index afb889d421..0000000000 --- a/src/mesa/drivers/dri/nouveau/nouveau_shader_0_arb.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Copyright (C) 2006 Ben Skeggs. - * - * All Rights Reserved. - * - * 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 (including the - * next paragraph) 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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS 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. - * - */ - -/* - * Authors: - * Ben Skeggs - */ - -#include "glheader.h" -#include "macros.h" -#include "enums.h" - -#include "program.h" -#include "programopt.h" -#include "program_instruction.h" - -#include "nouveau_context.h" -#include "nouveau_shader.h" - -static nvsFixedReg _tx_mesa_vp_dst_reg[VERT_RESULT_MAX] = { - NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD, - NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, - NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7, - NVS_FR_POINTSZ, NVS_FR_BFC0, NVS_FR_BFC1, NVS_FR_UNKNOWN /* EDGE */ -}; - -static nvsFixedReg _tx_mesa_fp_dst_reg[FRAG_RESULT_MAX] = { - NVS_FR_FRAGDATA0 /* COLR */, NVS_FR_FRAGDATA0 /* COLH */, - NVS_FR_UNKNOWN /* DEPR */ -}; - -static nvsFixedReg _tx_mesa_vp_src_reg[VERT_ATTRIB_MAX] = { - NVS_FR_POSITION, NVS_FR_WEIGHT, NVS_FR_NORMAL, NVS_FR_COL0, NVS_FR_COL1, - NVS_FR_FOGCOORD, NVS_FR_UNKNOWN /* COLOR_INDEX */, NVS_FR_UNKNOWN, - NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, - NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7, -/* Generic attribs 0-15, aliased to the above */ - NVS_FR_POSITION, NVS_FR_WEIGHT, NVS_FR_NORMAL, NVS_FR_COL0, NVS_FR_COL1, - NVS_FR_FOGCOORD, NVS_FR_UNKNOWN /* COLOR_INDEX */, NVS_FR_UNKNOWN, - NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, - NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7 -}; - -static nvsFixedReg _tx_mesa_fp_src_reg[FRAG_ATTRIB_MAX] = { - NVS_FR_POSITION, NVS_FR_COL0, NVS_FR_COL1, NVS_FR_FOGCOORD, - NVS_FR_TEXCOORD0, NVS_FR_TEXCOORD1, NVS_FR_TEXCOORD2, NVS_FR_TEXCOORD3, - NVS_FR_TEXCOORD4, NVS_FR_TEXCOORD5, NVS_FR_TEXCOORD6, NVS_FR_TEXCOORD7 -}; - -static nvsSwzComp _tx_mesa_swizzle[4] = { - NVS_SWZ_X, NVS_SWZ_Y, NVS_SWZ_Z, NVS_SWZ_W -}; - -static nvsOpcode _tx_mesa_opcode[] = { - [OPCODE_ABS] = NVS_OP_ABS, [OPCODE_ADD] = NVS_OP_ADD, - [OPCODE_ARA] = NVS_OP_ARA, [OPCODE_ARL] = NVS_OP_ARL, - [OPCODE_ARL_NV] = NVS_OP_ARL, [OPCODE_ARR] = NVS_OP_ARR, - [OPCODE_CMP] = NVS_OP_CMP, [OPCODE_COS] = NVS_OP_COS, - [OPCODE_DDX] = NVS_OP_DDX, [OPCODE_DDY] = NVS_OP_DDY, - [OPCODE_DP3] = NVS_OP_DP3, [OPCODE_DP4] = NVS_OP_DP4, - [OPCODE_DPH] = NVS_OP_DPH, [OPCODE_DST] = NVS_OP_DST, - [OPCODE_EX2] = NVS_OP_EX2, [OPCODE_EXP] = NVS_OP_EXP, - [OPCODE_FLR] = NVS_OP_FLR, [OPCODE_FRC] = NVS_OP_FRC, - [OPCODE_KIL] = NVS_OP_EMUL, [OPCODE_KIL_NV] = NVS_OP_KIL, - [OPCODE_LG2] = NVS_OP_LG2, [OPCODE_LIT] = NVS_OP_LIT, - [OPCODE_LOG] = NVS_OP_LOG, - [OPCODE_LRP] = NVS_OP_LRP, - [OPCODE_MAD] = NVS_OP_MAD, [OPCODE_MAX] = NVS_OP_MAX, - [OPCODE_MIN] = NVS_OP_MIN, [OPCODE_MOV] = NVS_OP_MOV, - [OPCODE_MUL] = NVS_OP_MUL, - [OPCODE_PK2H] = NVS_OP_PK2H, [OPCODE_PK2US] = NVS_OP_PK2US, - [OPCODE_PK4B] = NVS_OP_PK4B, [OPCODE_PK4UB] = NVS_OP_PK4UB, - [OPCODE_POW] = NVS_OP_POW, [OPCODE_POPA] = NVS_OP_POPA, - [OPCODE_PUSHA] = NVS_OP_PUSHA, - [OPCODE_RCC] = NVS_OP_RCC, [OPCODE_RCP] = NVS_OP_RCP, - [OPCODE_RFL] = NVS_OP_RFL, [OPCODE_RSQ] = NVS_OP_RSQ, - [OPCODE_SCS] = NVS_OP_SCS, [OPCODE_SEQ] = NVS_OP_SEQ, - [OPCODE_SFL] = NVS_OP_SFL, [OPCODE_SGE] = NVS_OP_SGE, - [OPCODE_SGT] = NVS_OP_SGT, [OPCODE_SIN] = NVS_OP_SIN, - [OPCODE_SLE] = NVS_OP_SLE, [OPCODE_SLT] = NVS_OP_SLT, - [OPCODE_SNE] = NVS_OP_SNE, [OPCODE_SSG] = NVS_OP_SSG, - [OPCODE_STR] = NVS_OP_STR, [OPCODE_SUB] = NVS_OP_SUB, - [OPCODE_SWZ] = NVS_OP_MOV, - [OPCODE_TEX] = NVS_OP_TEX, [OPCODE_TXB] = NVS_OP_TXB, - [OPCODE_TXD] = NVS_OP_TXD, - [OPCODE_TXL] = NVS_OP_TXL, [OPCODE_TXP] = NVS_OP_TXP, - [OPCODE_TXP_NV] = NVS_OP_TXP, - [OPCODE_UP2H] = NVS_OP_UP2H, [OPCODE_UP2US] = NVS_OP_UP2US, - [OPCODE_UP4B] = NVS_OP_UP4B, [OPCODE_UP4UB] = NVS_OP_UP4UB, - [OPCODE_X2D] = NVS_OP_X2D, - [OPCODE_XPD] = NVS_OP_XPD -}; - -static nvsCond _tx_mesa_condmask[] = { - NVS_COND_UNKNOWN, NVS_COND_GT, NVS_COND_LT, NVS_COND_UN, NVS_COND_GE, - NVS_COND_LE, NVS_COND_NE, NVS_COND_NE, NVS_COND_TR, NVS_COND_FL -}; - -struct pass0_rec { - int nvs_ipos; - int next_temp; - int swzconst_done; - int swzconst_id; - nvsRegister const_half; -}; - -#define X NVS_SWZ_X -#define Y NVS_SWZ_Y -#define Z NVS_SWZ_Z -#define W NVS_SWZ_W - -static void -pass0_append_fragment(nouveauShader *nvs, nvsFragmentHeader *fragment) -{ - nvsFragmentList *list = calloc(1, sizeof(nvsFragmentList)); - if (!list) - return; - - list->fragment = fragment; - list->prev = nvs->list_tail; - if ( nvs->list_tail) - nvs->list_tail->next = list; - if (!nvs->list_head) - nvs->list_head = list; - nvs->list_tail = list; - - nvs->inst_count++; -} - -static void -pass0_make_reg(nouveauShader *nvs, nvsRegister *reg, - nvsRegFile file, unsigned int index) -{ - struct pass0_rec *rec = nvs->pass_rec; - - /* defaults */ - *reg = nvr_unused; - /* -1 == quick-and-dirty temp alloc */ - if (file == NVS_FILE_TEMP && index == -1) { - index = rec->next_temp++; - assert(index < NVS_MAX_TEMPS); - } - reg->file = file; - reg->index = index; -} - -static void -pass0_make_swizzle(nvsSwzComp *swz, unsigned int mesa) -{ - int i; - - for (i=0;i<4;i++) - swz[i] = _tx_mesa_swizzle[GET_SWZ(mesa, i)]; -} - -static nvsOpcode -pass0_make_opcode(enum prog_opcode op) -{ - if (op > MAX_OPCODE) - return NVS_OP_UNKNOWN; - return _tx_mesa_opcode[op]; -} - -static nvsCond -pass0_make_condmask(GLuint mesa) -{ - if (mesa > COND_FL) - return NVS_COND_UNKNOWN; - return _tx_mesa_condmask[mesa]; -} - -static unsigned int -pass0_make_mask(GLuint mesa_mask) -{ - unsigned int mask = 0; - - if (mesa_mask & WRITEMASK_X) mask |= SMASK_X; - if (mesa_mask & WRITEMASK_Y) mask |= SMASK_Y; - if (mesa_mask & WRITEMASK_Z) mask |= SMASK_Z; - if (mesa_mask & WRITEMASK_W) mask |= SMASK_W; - - return mask; -} - -static nvsTexTarget -pass0_make_tex_target(GLuint mesa) -{ - switch (mesa) { - case TEXTURE_1D_INDEX: return NVS_TEX_TARGET_1D; - case TEXTURE_2D_INDEX: return NVS_TEX_TARGET_2D; - case TEXTURE_3D_INDEX: return NVS_TEX_TARGET_3D; - case TEXTURE_CUBE_INDEX: return NVS_TEX_TARGET_CUBE; - case TEXTURE_RECT_INDEX: return NVS_TEX_TARGET_RECT; - default: - return NVS_TEX_TARGET_UNKNOWN; - } -} - -static void -pass0_make_dst_reg(nvsPtr nvs, nvsRegister *reg, - struct prog_dst_register *dst) -{ - struct gl_program *mesa = (struct gl_program*)&nvs->mesa.vp; - nvsFixedReg sfr; - - switch (dst->File) { - case PROGRAM_OUTPUT: - if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { - sfr = (dst->Index < VERT_RESULT_MAX) ? - _tx_mesa_vp_dst_reg[dst->Index] : NVS_FR_UNKNOWN; - } else { - sfr = (dst->Index < FRAG_RESULT_MAX) ? - _tx_mesa_fp_dst_reg[dst->Index] : NVS_FR_UNKNOWN; - } - pass0_make_reg(nvs, reg, NVS_FILE_RESULT, sfr); - break; - case PROGRAM_TEMPORARY: - pass0_make_reg(nvs, reg, NVS_FILE_TEMP, dst->Index); - break; - case PROGRAM_ADDRESS: - pass0_make_reg(nvs, reg, NVS_FILE_ADDRESS, dst->Index); - break; - default: - fprintf(stderr, "Unknown dest file %d\n", dst->File); - assert(0); - } -} - -static void -pass0_make_src_reg(nvsPtr nvs, nvsRegister *reg, struct prog_src_register *src) -{ - struct gl_program *mesa = (struct gl_program *)&nvs->mesa.vp.Base; - struct gl_program_parameter_list *p = mesa->Parameters; - - *reg = nvr_unused; - - switch (src->File) { - case PROGRAM_INPUT: - reg->file = NVS_FILE_ATTRIB; - if (mesa->Target == GL_VERTEX_PROGRAM_ARB) { - reg->index = (src->Index < VERT_ATTRIB_MAX) ? - _tx_mesa_vp_src_reg[src->Index] : NVS_FR_UNKNOWN; - } else { - reg->index = (src->Index < FRAG_ATTRIB_MAX) ? - _tx_mesa_fp_src_reg[src->Index] : NVS_FR_UNKNOWN; - } - break; - /* All const types seem to get shoved into here, not really sure why */ - case PROGRAM_STATE_VAR: - switch (p->Parameters[src->Index].Type) { - case PROGRAM_NAMED_PARAM: - case PROGRAM_CONSTANT: - nvs->params[src->Index].source_val = NULL; - COPY_4V(nvs->params[src->Index].val, p->ParameterValues[src->Index]); - break; - case PROGRAM_STATE_VAR: - nvs->params[src->Index].source_val = p->ParameterValues[src->Index]; - break; - default: - fprintf(stderr, "Unknown parameter type %d\n", - p->Parameters[src->Index].Type); - assert(0); - break; - } - - if (src->RelAddr) { - reg->indexed = 1; - reg->addr_reg = 0; - reg->addr_comp = NVS_SWZ_X; - } else - reg->indexed = 0; - reg->file = NVS_FILE_CONST; - reg->index = src->Index; - break; - case PROGRAM_TEMPORARY: - reg->file = NVS_FILE_TEMP; - reg->index = src->Index; - break; - default: - fprintf(stderr, "Unknown source type %d\n", src->File); - assert(0); - } - - /* per-component negate handled elsewhere */ - reg->negate = src->NegateBase != 0; - reg->abs = src->Abs; - pass0_make_swizzle(reg->swizzle, src->Swizzle); -} - -static nvsInstruction * -pass0_emit(nouveauShader *nvs, nvsOpcode op, nvsRegister dst, - unsigned int mask, int saturate, - nvsRegister src0, nvsRegister src1, nvsRegister src2) -{ - struct pass0_rec *rec = nvs->pass_rec; - nvsInstruction *sif = NULL; - - /* Seems mesa doesn't explicitly 0 this.. */ - if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB) - saturate = 0; - - sif = calloc(1, sizeof(nvsInstruction)); - if (sif) { - sif->header.type = NVS_INSTRUCTION; - sif->header.position = rec->nvs_ipos++; - sif->op = op; - sif->saturate = saturate; - sif->dest = dst; - sif->mask = mask; - sif->src[0] = src0; - sif->src[1] = src1; - sif->src[2] = src2; - sif->cond = COND_TR; - sif->cond_reg = 0; - sif->cond_test = 0; - sif->cond_update = 0; - pass0_make_swizzle(sif->cond_swizzle, SWIZZLE_NOOP); - pass0_append_fragment(nvs, (nvsFragmentHeader *)sif); - } - - return sif; -} - -static void -pass0_fixup_swizzle(nvsPtr nvs, - struct prog_src_register *src, - unsigned int sm1, - unsigned int sm2) -{ - static const float sc[4] = { 1.0, 0.0, -1.0, 0.0 }; - struct pass0_rec *rec = nvs->pass_rec; - int fixup_1, fixup_2; - nvsRegister sr, dr = nvr_unused; - nvsRegister sm1const, sm2const; - - if (!rec->swzconst_done) { - struct gl_program *prog = &nvs->mesa.vp.Base; - rec->swzconst_id = _mesa_add_unnamed_constant(prog->Parameters, sc, 4); - rec->swzconst_done = 1; - COPY_4V(nvs->params[rec->swzconst_id].val, sc); - } - - fixup_1 = (sm1 != MAKE_SWIZZLE4(0,0,0,0) && sm2 != MAKE_SWIZZLE4(2,2,2,2)); - fixup_2 = (sm2 != MAKE_SWIZZLE4(2,2,2,2)); - - if (src->File != PROGRAM_TEMPORARY && src->File != PROGRAM_INPUT) { - /* We can't use more than one const in an instruction, so move the const - * into a temp, and swizzle from there. - *TODO: should just emit the swizzled const, instead of swizzling it - * in the shader.. would need to reswizzle any state params when they - * change however.. - */ - pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); - pass0_make_src_reg(nvs, &sr, src); - pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0, sr, nvr_unused, nvr_unused); - pass0_make_reg(nvs, &sr, NVS_FILE_TEMP, dr.index); - } else { - if (fixup_1) - src->NegateBase = 0; - pass0_make_src_reg(nvs, &sr, src); - pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); - } - - pass0_make_reg(nvs, &sm1const, NVS_FILE_CONST, rec->swzconst_id); - pass0_make_swizzle(sm1const.swizzle, sm1); - if (fixup_1 && fixup_2) { - /* Any combination with SWIZZLE_ONE */ - pass0_make_reg(nvs, &sm2const, NVS_FILE_CONST, rec->swzconst_id); - pass0_make_swizzle(sm2const.swizzle, sm2); - pass0_emit(nvs, NVS_OP_MAD, dr, SMASK_ALL, 0, sr, sm1const, sm2const); - } else { - /* SWIZZLE_ZERO || arbitrary negate */ - pass0_emit(nvs, NVS_OP_MUL, dr, SMASK_ALL, 0, sr, sm1const, nvr_unused); - } - - src->File = PROGRAM_TEMPORARY; - src->Index = dr.index; - src->Swizzle = SWIZZLE_NOOP; -} - -#define SET_SWZ(fs, cp, c) fs = (fs & ~(0x7<<(cp*3))) | (c<<(cp*3)) -static void -pass0_check_sources(nvsPtr nvs, struct prog_instruction *inst) -{ - unsigned int insrc = -1, constsrc = -1; - int i; - - for (i=0;i<_mesa_num_inst_src_regs(inst->Opcode);i++) { - struct prog_src_register *src = &inst->SrcReg[i]; - unsigned int sm_1 = 0, sm_2 = 0; - nvsRegister sr, dr; - int do_mov = 0, c; - - /* Build up swizzle masks as if we were going to use - * "MAD new, src, const1, const2" to support arbitrary negation - * and SWIZZLE_ZERO/SWIZZLE_ONE. - */ - for (c=0;c<4;c++) { - if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ZERO) { - SET_SWZ(sm_1, c, SWIZZLE_Y); /* 0.0 */ - SET_SWZ(sm_2, c, SWIZZLE_Y); - SET_SWZ(src->Swizzle, c, SWIZZLE_X); - } else if (GET_SWZ(src->Swizzle, c) == SWIZZLE_ONE) { - SET_SWZ(sm_1, c, SWIZZLE_Y); - if (src->NegateBase & (1<Swizzle, c, SWIZZLE_X); - } else { - if (src->NegateBase & (1<File) { - case PROGRAM_INPUT: - if (insrc != -1 && insrc != src->Index) - do_mov = 1; - else insrc = src->Index; - break; - case PROGRAM_STATE_VAR: - if (constsrc != -1 && constsrc != src->Index) - do_mov = 1; - else constsrc = src->Index; - break; - default: - break; - } - - /* Emit any extra ATTRIB/CONST to a temp, and modify the Mesa instruction - * to point at the temp. - */ - if (do_mov) { - pass0_make_src_reg(nvs, &sr, src); - pass0_make_reg(nvs, &dr, NVS_FILE_TEMP, -1); - pass0_emit(nvs, NVS_OP_MOV, dr, SMASK_ALL, 0, - sr, nvr_unused, nvr_unused); - - src->File = PROGRAM_TEMPORARY; - src->Index = dr.index; - src->Swizzle= SWIZZLE_NOOP; - } - } -} - -static GLboolean -pass0_emulate_instruction(nouveauShader *nvs, struct prog_instruction *inst) -{ - nvsFunc *shader = nvs->func; - nvsRegister src[3], dest, temp; - nvsInstruction *nvsinst; - struct pass0_rec *rec = nvs->pass_rec; - unsigned int mask = pass0_make_mask(inst->DstReg.WriteMask); - int i, sat; - - sat = (inst->SaturateMode == SATURATE_ZERO_ONE); - - /* Build all the "real" regs for the instruction */ - for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) - pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); - if (inst->Opcode != OPCODE_KIL) - pass0_make_dst_reg(nvs, &dest, &inst->DstReg); - - switch (inst->Opcode) { - case OPCODE_ABS: - if (shader->caps & SCAP_SRC_ABS) - pass0_emit(nvs, NVS_OP_MOV, dest, mask, sat, - nvsAbs(src[0]), nvr_unused, nvr_unused); - else - pass0_emit(nvs, NVS_OP_MAX, dest, mask, sat, - src[0], nvsNegate(src[0]), nvr_unused); - break; - case OPCODE_KIL: - /* This is only in ARB shaders, so we don't have to worry - * about clobbering a CC reg as they aren't supported anyway. - */ - /* MOVC0 temp, src */ - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - nvsinst = pass0_emit(nvs, NVS_OP_MOV, temp, SMASK_ALL, 0, - src[0], nvr_unused, nvr_unused); - nvsinst->cond_update = 1; - nvsinst->cond_reg = 0; - /* KIL_NV (LT0.xyzw) temp */ - nvsinst = pass0_emit(nvs, NVS_OP_KIL, nvr_unused, 0, 0, - nvr_unused, nvr_unused, nvr_unused); - nvsinst->cond = COND_LT; - nvsinst->cond_reg = 0; - nvsinst->cond_test = 1; - pass0_make_swizzle(nvsinst->cond_swizzle, MAKE_SWIZZLE4(0,1,2,3)); - break; - case OPCODE_LIT: - break; - case OPCODE_LRP: - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - pass0_emit(nvs, NVS_OP_MAD, temp, mask, 0, - nvsNegate(src[0]), src[2], src[2]); - pass0_emit(nvs, NVS_OP_MAD, dest, mask, sat, - src[0], src[1], temp); - break; - case OPCODE_POW: - if (shader->SupportsOpcode(shader, NVS_OP_LG2) && - shader->SupportsOpcode(shader, NVS_OP_EX2)) { - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - /* LG2 temp.x, src0.c */ - pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0, - nvsSwizzle(src[0], X, X, X, X), - nvr_unused, - nvr_unused); - /* MUL temp.x, temp.x, src1.c */ - pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0, - nvsSwizzle(temp, X, X, X, X), - nvsSwizzle(src[1], X, X, X, X), - nvr_unused); - /* EX2 dest, temp.x */ - pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat, - nvsSwizzle(temp, X, X, X, X), - nvr_unused, - nvr_unused); - } else { - /* can we use EXP/LOG instead of EX2/LG2?? */ - fprintf(stderr, "Implement POW for NV20 vtxprog!\n"); - return GL_FALSE; - } - break; - case OPCODE_RSQ: - if (rec->const_half.file != NVS_FILE_CONST) { - GLfloat const_half[4] = { 0.5, 0.0, 0.0, 0.0 }; - pass0_make_reg(nvs, &rec->const_half, NVS_FILE_CONST, - _mesa_add_unnamed_constant(nvs->mesa.vp.Base.Parameters, - const_half, 4)); - COPY_4V(nvs->params[rec->const_half.index].val, const_half); - } - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - pass0_emit(nvs, NVS_OP_LG2, temp, SMASK_X, 0, - nvsAbs(nvsSwizzle(src[0], X, X, X, X)), - nvr_unused, - nvr_unused); - pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_X, 0, - nvsSwizzle(temp, X, X, X, X), - nvsNegate(rec->const_half), - nvr_unused); - pass0_emit(nvs, NVS_OP_EX2, dest, mask, sat, - nvsSwizzle(temp, X, X, X, X), - nvr_unused, - nvr_unused); - break; - case OPCODE_SCS: - if (mask & SMASK_X) - pass0_emit(nvs, NVS_OP_COS, dest, SMASK_X, sat, - nvsSwizzle(src[0], X, X, X, X), - nvr_unused, - nvr_unused); - if (mask & SMASK_Y) - pass0_emit(nvs, NVS_OP_SIN, dest, SMASK_Y, sat, - nvsSwizzle(src[0], X, X, X, X), - nvr_unused, - nvr_unused); - break; - case OPCODE_SUB: - pass0_emit(nvs, NVS_OP_ADD, dest, mask, sat, - src[0], nvsNegate(src[1]), nvr_unused); - break; - case OPCODE_XPD: - pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1); - pass0_emit(nvs, NVS_OP_MUL, temp, SMASK_ALL, 0, - nvsSwizzle(src[0], Z, X, Y, Y), - nvsSwizzle(src[1], Y, Z, X, X), - nvr_unused); - pass0_emit(nvs, NVS_OP_MAD, dest, (mask & ~SMASK_W), sat, - nvsSwizzle(src[0], Y, Z, X, X), - nvsSwizzle(src[1], Z, X, Y, Y), - nvsNegate(temp)); - break; - default: - fprintf(stderr, "hw doesn't support opcode \"%s\", and no emulation found\n", - _mesa_opcode_string(inst->Opcode)); - return GL_FALSE; - } - - return GL_TRUE; -} - -static GLboolean -pass0_translate_instructions(nouveauShader *nvs) -{ - struct gl_program *prog = (struct gl_program *)&nvs->mesa.vp; - nvsFunc *shader = nvs->func; - int ipos; - - for (ipos=0; iposNumInstructions; ipos++) { - struct prog_instruction *inst = &prog->Instructions[ipos]; - - if (inst->Opcode == OPCODE_END) - break; - - /* Deal with multiple ATTRIB/PARAM in a single instruction */ - pass0_check_sources(nvs, inst); - - /* Now it's safe to do the prog_instruction->nvsInstruction conversion */ - if (shader->SupportsOpcode(shader, pass0_make_opcode(inst->Opcode))) { - nvsInstruction *nvsinst; - nvsRegister src[3], dest; - int i; - - for (i=0; i<_mesa_num_inst_src_regs(inst->Opcode); i++) - pass0_make_src_reg(nvs, &src[i], &inst->SrcReg[i]); - pass0_make_dst_reg(nvs, &dest, &inst->DstReg); - - nvsinst = pass0_emit(nvs, - pass0_make_opcode(inst->Opcode), - dest, - pass0_make_mask(inst->DstReg.WriteMask), - (inst->SaturateMode != SATURATE_OFF), - src[0], src[1], src[2]); - nvsinst->tex_unit = inst->TexSrcUnit; - nvsinst->tex_target = pass0_make_tex_target(inst->TexSrcTarget); - /* TODO when NV_fp/vp is implemented */ - nvsinst->cond = COND_TR; - } else { - if (!pass0_emulate_instruction(nvs, inst)) - return GL_FALSE; - } - } - - return GL_TRUE; -} - -GLboolean -nouveau_shader_pass0_arb(GLcontext *ctx, nouveauShader *nvs) -{ - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - struct gl_program *prog = (struct gl_program*)nvs; - struct gl_vertex_program *vp = (struct gl_vertex_program *)prog; - struct gl_fragment_program *fp = (struct gl_fragment_program *)prog; - struct pass0_rec *rec; - int ret; - - switch (prog->Target) { - case GL_VERTEX_PROGRAM_ARB: - nvs->func = &nmesa->VPfunc; - if (vp->IsPositionInvariant) - _mesa_insert_mvp_code(ctx, vp); -#if 0 - if (IS_FIXEDFUNCTION_PROG && CLIP_PLANES_USED) - pass0_insert_ff_clip_planes(); -#endif - break; - case GL_FRAGMENT_PROGRAM_ARB: - nvs->func = &nmesa->FPfunc; - if (fp->FogOption != GL_NONE) - _mesa_append_fog_code(ctx, fp); - break; - default: - fprintf(stderr, "Unknown program type %d", prog->Target); - return GL_FALSE; - } - - rec = calloc(1, sizeof(struct pass0_rec)); - rec->next_temp = prog->NumTemporaries; - nvs->pass_rec = rec; - - ret = pass0_translate_instructions(nvs); - if (!ret) { - /* DESTROY list */ - } - - free(nvs->pass_rec); - return ret; -} - -- cgit v1.2.3 From 3c0961d29993a2203323b4c308ae6d7e418ac5aa Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Sun, 21 Jan 2007 04:06:57 +0100 Subject: nouveau: add nv04 state support, and small nv04 fixes. --- src/mesa/drivers/dri/nouveau/Makefile | 11 +- src/mesa/drivers/dri/nouveau/nouveau_context.c | 3 +- src/mesa/drivers/dri/nouveau/nouveau_context.h | 18 +- src/mesa/drivers/dri/nouveau/nouveau_object.c | 11 +- src/mesa/drivers/dri/nouveau/nouveau_state.c | 4 +- src/mesa/drivers/dri/nouveau/nouveau_state.h | 1 + src/mesa/drivers/dri/nouveau/nv04_state.c | 497 +++++++++++++++++++++++++ 7 files changed, 527 insertions(+), 18 deletions(-) create mode 100644 src/mesa/drivers/dri/nouveau/nv04_state.c (limited to 'src/mesa/drivers') diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile index 9718f3bf46..492e743360 100644 --- a/src/mesa/drivers/dri/nouveau/Makefile +++ b/src/mesa/drivers/dri/nouveau/Makefile @@ -19,6 +19,7 @@ DRIVER_SOURCES = \ nouveau_screen.c \ nouveau_span.c \ nouveau_state.c \ + nouveau_state_cache.c \ nouveau_shader.c \ nouveau_shader_0.c \ nouveau_shader_1.c \ @@ -26,18 +27,18 @@ DRIVER_SOURCES = \ nouveau_tex.c \ nouveau_swtcl.c \ nouveau_sync.c \ + nv04_state.c \ nv04_swtcl.c \ - nv10_swtcl.c \ nv10_state.c \ + nv10_swtcl.c \ nv20_state.c \ - nv30_state.c \ - nv50_state.c \ - nouveau_state_cache.c \ nv20_vertprog.c \ + nv30_state.c \ nv30_fragprog.c \ nv30_vertprog.c \ nv40_fragprog.c \ - nv40_vertprog.c + nv40_vertprog.c \ + nv50_state.c C_SOURCES = \ $(COMMON_SOURCES) \ diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index 79da46fc0b..5db93eb012 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -50,6 +50,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "nouveau_msg.h" #include "nouveau_reg.h" #include "nouveau_lock.h" +#include "nv04_swtcl.h" #include "nv10_swtcl.h" #include "vblank.h" @@ -212,7 +213,7 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual, break; case NV_04: case NV_05: - //nv04TriInitFunctions( ctx ); + nv04TriInitFunctions( ctx ); break; case NV_10: case NV_20: diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h index c7bf387210..bcfbb9fb8d 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h @@ -170,15 +170,15 @@ typedef struct nouveau_context { /* Configuration cache */ driOptionCache optionCache; - /* vblank stuff */ - uint32_t vblank_flags; - uint32_t vblank_seq; - - GLuint new_state; - GLuint new_render_state; - GLuint render_index; - GLmatrix viewport; - GLfloat depth_scale; + /* vblank stuff */ + uint32_t vblank_flags; + uint32_t vblank_seq; + + GLuint new_state; + GLuint new_render_state; + GLuint render_index; + GLmatrix viewport; + GLfloat depth_scale; }nouveauContextRec, *nouveauContextPtr; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.c b/src/mesa/drivers/dri/nouveau/nouveau_object.c index 1558f2963d..26086e16e4 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_object.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_object.c @@ -62,10 +62,17 @@ void nouveauObjectInit(nouveauContextPtr nmesa) nouveauCreateContextObject(nmesa, Nv3D, nmesa->screen->card->class_3d, 0, 0, 0, 0); - nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV10_CONTEXT_SURFACES_2D, + if (nmesa->screen->card->type>=NV_10) { + nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV10_CONTEXT_SURFACES_2D, 0, 0, 0, 0); - nouveauCreateContextObject(nmesa, NvImageBlit, NV10_IMAGE_BLIT, + nouveauCreateContextObject(nmesa, NvImageBlit, NV10_IMAGE_BLIT, NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY, 0, 0, 0); + } else { + nouveauCreateContextObject(nmesa, NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D, + 0, 0, 0, 0); + nouveauCreateContextObject(nmesa, NvImageBlit, NV_IMAGE_BLIT, + NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY, 0, 0, 0); + } nouveauCreateContextObject(nmesa, NvMemFormat, NV_MEMORY_TO_MEMORY_FORMAT, 0, 0, 0, 0); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c index 1ff881f054..18f6ffb2ad 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_state.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_state.c @@ -156,9 +156,11 @@ void nouveauDDInitState(nouveauContextPtr nmesa) switch(type) { case NV_03: + /* Unimplemented */ + break; case NV_04: case NV_05: - /* No TCL engines for these ones */ + nv04InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver); break; case NV_10: nv10InitStateFuncs(nmesa->glCtx, &nmesa->glCtx->Driver); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.h b/src/mesa/drivers/dri/nouveau/nouveau_state.h index 16d63a6ac2..5b85287445 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_state.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_state.h @@ -32,6 +32,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. extern void nouveauDDInitState(nouveauContextPtr nmesa); extern void nouveauDDInitStateFuncs(GLcontext *ctx); +extern void nv04InitStateFuncs(GLcontext *ctx, struct dd_function_table *func); extern void nv10InitStateFuncs(GLcontext *ctx, struct dd_function_table *func); extern void nv20InitStateFuncs(GLcontext *ctx, struct dd_function_table *func); extern void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func); diff --git a/src/mesa/drivers/dri/nouveau/nv04_state.c b/src/mesa/drivers/dri/nouveau/nv04_state.c new file mode 100644 index 0000000000..83ad8ae432 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nv04_state.c @@ -0,0 +1,497 @@ +/************************************************************************** + +Copyright 2007 Stephane Marchesin +All Rights Reserved. + +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 +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 "nouveau_context.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" +#include "nouveau_msg.h" + +#include "tnl/t_pipeline.h" + +#include "mtypes.h" +#include "colormac.h" + +static uint32_t nv04_compare_func(GLcontext *ctx,GLuint f) +{ + switch ( ctx->Color.AlphaFunc ) { + case GL_NEVER: return 1; + case GL_LESS: return 2; + case GL_EQUAL: return 3; + case GL_LEQUAL: return 4; + case GL_GREATER: return 5; + case GL_NOTEQUAL: return 6; + case GL_GEQUAL: return 7; + case GL_ALWAYS: return 8; + } + WARN_ONCE("Unable to find the function\n"); + return 0; +} + +static uint32_t nv04_blend_func(GLcontext *ctx,GLuint f) +{ + switch ( ctx->Color.AlphaFunc ) { + case GL_ZERO: return 0x1; + case GL_ONE: return 0x2; + case GL_SRC_COLOR: return 0x3; + case GL_ONE_MINUS_SRC_COLOR: return 0x4; + case GL_SRC_ALPHA: return 0x5; + case GL_ONE_MINUS_SRC_ALPHA: return 0x6; + case GL_DST_ALPHA: return 0x7; + case GL_ONE_MINUS_DST_ALPHA: return 0x8; + case GL_DST_COLOR: return 0x9; + case GL_ONE_MINUS_DST_COLOR: return 0xA; + case GL_SRC_ALPHA_SATURATE: return 0xB; + } + WARN_ONCE("Unable to find the function\n"); + return 0; +} + +static void nv04_emit_control(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + uint32_t control,cull; + GLubyte alpha_ref; + + CLAMPED_FLOAT_TO_UBYTE(alpha_ref, ctx->Color.AlphaRef); + control=alpha_ref; + control|=(nv04_compare_func(ctx,ctx->Color.AlphaFunc)<<8); + control|=(ctx->Color.AlphaEnabled<<12); + control|=(1<<13); + control|=(ctx->Depth.Test<<14); + control|=(nv04_compare_func(ctx,ctx->Depth.Func)<<16); + if ((ctx->Polygon.CullFlag)&&(ctx->Polygon.CullFaceMode!=GL_FRONT_AND_BACK)) + { + if ((ctx->Polygon.FrontFace==GL_CW)&&(ctx->Polygon.CullFaceMode==GL_FRONT)) + cull=2; + if ((ctx->Polygon.FrontFace==GL_CW)&&(ctx->Polygon.CullFaceMode==GL_BACK)) + cull=3; + if ((ctx->Polygon.FrontFace==GL_CCW)&&(ctx->Polygon.CullFaceMode==GL_FRONT)) + cull=3; + if ((ctx->Polygon.FrontFace==GL_CCW)&&(ctx->Polygon.CullFaceMode==GL_BACK)) + cull=2; + } + else + if (ctx->Polygon.CullFaceMode==GL_FRONT_AND_BACK) + cull=0; + else + cull=1; + control|=(cull<<20); + control|=(ctx->Color.DitherFlag<<22); + if ((ctx->Depth.Test)&&(ctx->Depth.Mask)) + control|=(1<<24); + + control|=(1<<30); // integer zbuffer format + + BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_CONTROL, 1); + OUT_RING_CACHE(control); +} + +static void nv04_emit_blend(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + uint32_t blend; + + blend=0x4; // texture MODULATE_ALPHA + blend|=0x20; // alpha is MSB + switch(ctx->Light.ShadeModel) { + case GL_SMOOTH:blend|=(1<<6);break; + case GL_FLAT: blend|=(2<<6);break; + default:break; + } + if (ctx->Hint.PerspectiveCorrection!=GL_FASTEST) + blend|=(1<<8); + blend|=(ctx->Fog.Enabled<<16); + blend|=(ctx->Color.BlendEnabled<<20); + blend|=(nv04_blend_func(ctx,ctx->Color.BlendSrcRGB)<<24); + blend|=(nv04_blend_func(ctx,ctx->Color.BlendDstRGB)<<28); + + BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_BLEND, 1); + OUT_RING_CACHE(blend); +} + +static void nv04_emit_fog_color(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLubyte c[4]; + c[0] = FLOAT_TO_UBYTE( ctx->Fog.Color[0] ); + c[1] = FLOAT_TO_UBYTE( ctx->Fog.Color[1] ); + c[2] = FLOAT_TO_UBYTE( ctx->Fog.Color[2] ); + c[3] = FLOAT_TO_UBYTE( ctx->Fog.Color[3] ); + BEGIN_RING_CACHE(NvSub3D, NV04_DX5_TEXTURED_TRIANGLE_FOG_COLOR, 1); + OUT_RING_CACHE(PACK_COLOR_8888_REV(c[0],c[1],c[2],c[3])); +} + +static void nv04AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) +{ + nv04_emit_control(ctx); +} + +static void nv04BlendColor(GLcontext *ctx, const GLfloat color[4]) +{ + nv04_emit_blend(ctx); +} + +static void nv04BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA) +{ + nv04_emit_blend(ctx); +} + + +static void nv04BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + nv04_emit_blend(ctx); +} + +static void nv04Clear(GLcontext *ctx, GLbitfield mask) +{ + /* TODO */ +} + +static void nv04ClearColor(GLcontext *ctx, const GLfloat color[4]) +{ + /* TODO */ +} + +static void nv04ClearDepth(GLcontext *ctx, GLclampd d) +{ + /* TODO */ +} + +static void nv04ClearStencil(GLcontext *ctx, GLint s) +{ + /* TODO */ +} + +static void nv04ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation) +{ + /* TODO */ +} + +static void nv04ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask, + GLboolean bmask, GLboolean amask ) +{ + /* TODO */ +} + +static void nv04ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode) +{ + /* TODO I need love */ +} + +static void nv04CullFace(GLcontext *ctx, GLenum mode) +{ + nv04_emit_control(ctx); +} + +static void nv04FrontFace(GLcontext *ctx, GLenum mode) +{ + /* TODO */ +} + +static void nv04DepthFunc(GLcontext *ctx, GLenum func) +{ + nv04_emit_control(ctx); +} + +static void nv04DepthMask(GLcontext *ctx, GLboolean flag) +{ + /* TODO */ +} + +static void nv04DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval) +{ + /* TODO */ +} + +/** Specify the current buffer for writing */ +//void (*DrawBuffer)( GLcontext *ctx, GLenum buffer ); +/** Specify the buffers for writing for fragment programs*/ +//void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers ); + +static void nv04Enable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + switch(cap) + { + case GL_ALPHA_TEST: + nv04_emit_control(ctx); + break; +// case GL_AUTO_NORMAL: + case GL_BLEND: + nv04_emit_blend(ctx); + break; +// case GL_CLIP_PLANE0: +// case GL_CLIP_PLANE1: +// case GL_CLIP_PLANE2: +// case GL_CLIP_PLANE3: +// case GL_CLIP_PLANE4: +// case GL_CLIP_PLANE5: +// case GL_COLOR_LOGIC_OP: +// case GL_COLOR_MATERIAL: +// case GL_COLOR_SUM_EXT: +// case GL_COLOR_TABLE: +// case GL_CONVOLUTION_1D: +// case GL_CONVOLUTION_2D: + case GL_CULL_FACE: + nv04_emit_control(ctx); + break; + case GL_DEPTH_TEST: + nv04_emit_control(ctx); + break; + case GL_DITHER: + nv04_emit_control(ctx); + break; + case GL_FOG: + nv04_emit_blend(ctx); + break; +// case GL_HISTOGRAM: +// case GL_INDEX_LOGIC_OP: +// case GL_LIGHT0: +// case GL_LIGHT1: +// case GL_LIGHT2: +// case GL_LIGHT3: +// case GL_LIGHT4: +// case GL_LIGHT5: +// case GL_LIGHT6: +// case GL_LIGHT7: +// case GL_LIGHTING: +// case GL_LINE_SMOOTH: +// case GL_LINE_STIPPLE: +// case GL_MAP1_COLOR_4: +// case GL_MAP1_INDEX: +// case GL_MAP1_NORMAL: +// case GL_MAP1_TEXTURE_COORD_1: +// case GL_MAP1_TEXTURE_COORD_2: +// case GL_MAP1_TEXTURE_COORD_3: +// case GL_MAP1_TEXTURE_COORD_4: +// case GL_MAP1_VERTEX_3: +// case GL_MAP1_VERTEX_4: +// case GL_MAP2_COLOR_4: +// case GL_MAP2_INDEX: +// case GL_MAP2_NORMAL: +// case GL_MAP2_TEXTURE_COORD_1: +// case GL_MAP2_TEXTURE_COORD_2: +// case GL_MAP2_TEXTURE_COORD_3: +// case GL_MAP2_TEXTURE_COORD_4: +// case GL_MAP2_VERTEX_3: +// case GL_MAP2_VERTEX_4: +// case GL_MINMAX: +// case GL_NORMALIZE: +// case GL_POINT_SMOOTH: +// case GL_POLYGON_OFFSET_POINT: +// case GL_POLYGON_OFFSET_LINE: +// case GL_POLYGON_OFFSET_FILL: +// case GL_POLYGON_SMOOTH: +// case GL_POLYGON_STIPPLE: +// case GL_POST_COLOR_MATRIX_COLOR_TABLE: +// case GL_POST_CONVOLUTION_COLOR_TABLE: +// case GL_RESCALE_NORMAL: +// case GL_SCISSOR_TEST: +// case GL_SEPARABLE_2D: +// case GL_STENCIL_TEST: +// case GL_TEXTURE_GEN_Q: +// case GL_TEXTURE_GEN_R: +// case GL_TEXTURE_GEN_S: +// case GL_TEXTURE_GEN_T: +// case GL_TEXTURE_1D: +// case GL_TEXTURE_2D: +// case GL_TEXTURE_3D: + } +} + +static void nv04Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + nv04_emit_blend(ctx); + nv04_emit_fog_color(ctx); +} + +static void nv04Hint(GLcontext *ctx, GLenum target, GLenum mode) +{ + switch(target) + { + case GL_PERSPECTIVE_CORRECTION_HINT:nv04_emit_blend(ctx);break; + default:break; + } +} + +static void nv04LineStipple(GLcontext *ctx, GLint factor, GLushort pattern ) +{ + /* TODO not even in your dreams */ +} + +static void nv04LineWidth(GLcontext *ctx, GLfloat width) +{ + /* TODO */ +} + +static void nv04LogicOpcode(GLcontext *ctx, GLenum opcode) +{ + /* TODO */ +} + +static void nv04PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params) +{ + /* TODO */ +} + +static void nv04PointSize(GLcontext *ctx, GLfloat size) +{ + /* TODO */ +} + +static void nv04PolygonMode(GLcontext *ctx, GLenum face, GLenum mode) +{ + /* TODO */ +} + +/** Set the scale and units used to calculate depth values */ +static void nv04PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units) +{ + /* TODO */ +} + +/** Set the polygon stippling pattern */ +static void nv04PolygonStipple(GLcontext *ctx, const GLubyte *mask ) +{ + /* TODO */ +} + +/* Specifies the current buffer for reading */ +void (*ReadBuffer)( GLcontext *ctx, GLenum buffer ); +/** Set rasterization mode */ +void (*RenderMode)(GLcontext *ctx, GLenum mode ); + +/** Define the scissor box */ +static void nv04Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + /* TODO */ +} + +/** Select flat or smooth shading */ +static void nv04ShadeModel(GLcontext *ctx, GLenum mode) +{ + nv04_emit_blend(ctx); +} + +/** OpenGL 2.0 two-sided StencilFunc */ +static void nv04StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, + GLint ref, GLuint mask) +{ + /* TODO */ +} + +/** OpenGL 2.0 two-sided StencilMask */ +static void nv04StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) +{ + /* TODO */ +} + +/** OpenGL 2.0 two-sided StencilOp */ +static void nv04StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, + GLenum zfail, GLenum zpass) +{ + /* TODO */ +} + +/** Control the generation of texture coordinates */ +void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname, + const GLfloat *params); +/** Set texture environment parameters */ +void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname, + const GLfloat *param); +/** Set texture parameters */ +void (*TexParameter)(GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat *params); + +/* Update anything that depends on the window position/size */ +static void nv04WindowMoved(nouveauContextPtr nmesa) +{ +} + +/* Initialise any card-specific non-GL related state */ +static GLboolean nv04InitCard(nouveauContextPtr nmesa) +{ + return GL_TRUE; +} + +/* Update buffer offset/pitch/format */ +static GLboolean nv04BindBuffers(nouveauContextPtr nmesa, int num_color, + nouveau_renderbuffer **color, + nouveau_renderbuffer *depth) +{ + return GL_TRUE; +} + +void nv04InitStateFuncs(GLcontext *ctx, struct dd_function_table *func) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + func->AlphaFunc = nv04AlphaFunc; + func->BlendColor = nv04BlendColor; + func->BlendEquationSeparate = nv04BlendEquationSeparate; + func->BlendFuncSeparate = nv04BlendFuncSeparate; + func->Clear = nv04Clear; + func->ClearColor = nv04ClearColor; + func->ClearDepth = nv04ClearDepth; + func->ClearStencil = nv04ClearStencil; + func->ClipPlane = nv04ClipPlane; + func->ColorMask = nv04ColorMask; + func->ColorMaterial = nv04ColorMaterial; + func->CullFace = nv04CullFace; + func->FrontFace = nv04FrontFace; + func->DepthFunc = nv04DepthFunc; + func->DepthMask = nv04DepthMask; + func->DepthRange = nv04DepthRange; + func->Enable = nv04Enable; + func->Fogfv = nv04Fogfv; + func->Hint = nv04Hint; +/* func->Lightfv = nv04Lightfv;*/ +/* func->LightModelfv = nv04LightModelfv; */ + func->LineStipple = nv04LineStipple; /* Not for NV04 */ + func->LineWidth = nv04LineWidth; + func->LogicOpcode = nv04LogicOpcode; + func->PointParameterfv = nv04PointParameterfv; + func->PointSize = nv04PointSize; + func->PolygonMode = nv04PolygonMode; + func->PolygonOffset = nv04PolygonOffset; + func->PolygonStipple = nv04PolygonStipple; /* Not for NV04 */ +/* func->ReadBuffer = nv04ReadBuffer;*/ +/* func->RenderMode = nv04RenderMode;*/ + func->Scissor = nv04Scissor; + func->ShadeModel = nv04ShadeModel; + func->StencilFuncSeparate = nv04StencilFuncSeparate; + func->StencilMaskSeparate = nv04StencilMaskSeparate; + func->StencilOpSeparate = nv04StencilOpSeparate; +/* func->TexGen = nv04TexGen;*/ +/* func->TexParameter = nv04TexParameter;*/ +/* func->TextureMatrix = nv04TextureMatrix;*/ + + nmesa->hw_func.InitCard = nv04InitCard; + nmesa->hw_func.BindBuffers = nv04BindBuffers; + nmesa->hw_func.WindowMoved = nv04WindowMoved; +} -- cgit v1.2.3 From d1f0a55af42c8a34c2d59ca003e7d7a8263665fb Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Mon, 22 Jan 2007 00:12:05 +0100 Subject: nouveau: fix some bugs in the nv10 swtcl. --- src/mesa/drivers/dri/nouveau/nv10_swtcl.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'src/mesa/drivers') diff --git a/src/mesa/drivers/dri/nouveau/nv10_swtcl.c b/src/mesa/drivers/dri/nouveau/nv10_swtcl.c index 12b277de45..f916912c7e 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_swtcl.c +++ b/src/mesa/drivers/dri/nouveau/nv10_swtcl.c @@ -23,7 +23,7 @@ * DEALINGS IN THE SOFTWARE. */ -/* Software TCL for NV10, NV20, NV30, NV40, G70 */ +/* Software TCL for NV10, NV20, NV30, NV40, NV50 */ #include #include @@ -288,6 +288,20 @@ do { \ nmesa->vertex_attr_count++; \ } while (0) +static void nv10_render_clipped_line(GLcontext *ctx,GLuint ii,GLuint jj) +{ + +} + +static void nv10_render_clipped_poly(GLcontext *ctx,const GLuint *elts,GLuint n) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint *tmp = VB->Elts; + VB->Elts = (GLuint *)elts; + nv10_render_generic_primitive_elts( ctx, 0, n, PRIM_BEGIN|PRIM_END,GL_POLYGON ); + VB->Elts = tmp; +} static void nv10ChooseRenderState(GLcontext *ctx) { @@ -296,8 +310,8 @@ static void nv10ChooseRenderState(GLcontext *ctx) tnl->Driver.Render.PrimTabVerts = nv10_render_tab_verts; tnl->Driver.Render.PrimTabElts = nv10_render_tab_elts; - tnl->Driver.Render.ClippedLine = NULL; - tnl->Driver.Render.ClippedPolygon = NULL; + tnl->Driver.Render.ClippedLine = nv10_render_clipped_line; + tnl->Driver.Render.ClippedPolygon = nv10_render_clipped_poly; } @@ -323,6 +337,7 @@ static inline void nv10OutputVertexFormat(struct nouveau_context* nmesa) 0.0, 0.0, 0.0, 1.0 }; + nmesa->vertex_attr_count = 0; RENDERINPUTS_COPY(index, nmesa->render_inputs_bitset); /* -- cgit v1.2.3