diff options
author | Dave Airlie <airliedfreedesktop.org> | 2004-12-19 03:06:59 +0000 |
---|---|---|
committer | Dave Airlie <airliedfreedesktop.org> | 2004-12-19 03:06:59 +0000 |
commit | 7f752fed993e5e9423abac200dd59141edbada56 (patch) | |
tree | 06eba28f01c81dfbd8c4a9104206765f8731528c /src/mesa/shader/atifragshader.c | |
parent | a803b0c891404dcd7c376e91f6a033cd4e42abc3 (diff) |
Implement software ATI_fragment_shader
no error detection, slow, may not be 100% correct but a good start
Diffstat (limited to 'src/mesa/shader/atifragshader.c')
-rw-r--r-- | src/mesa/shader/atifragshader.c | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/src/mesa/shader/atifragshader.c b/src/mesa/shader/atifragshader.c new file mode 100644 index 00000000000..dbffa37f4f6 --- /dev/null +++ b/src/mesa/shader/atifragshader.c @@ -0,0 +1,419 @@ +/** + * \file atifragshader.c + * \author David Airlie + * Copyright (C) 2004 David Airlie 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 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 + * DAVID AIRLIE 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 "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "enums.h" +#include "mtypes.h" +#include "atifragshader.h" + +#define MESA_DEBUG_ATI_FS 0 + +extern struct program _mesa_DummyProgram; + +static void +new_inst(struct ati_fragment_shader *prog) +{ + prog->Base.NumInstructions++; +} + +#if MESA_DEBUG_ATI_FS +static char * +create_dst_mod_str(GLuint mod) +{ + static char ret_str[1024]; + + _mesa_memset(ret_str, 0, 1024); + if (mod & GL_2X_BIT_ATI) + _mesa_strncat(ret_str, "|2X", 1024); + + if (mod & GL_4X_BIT_ATI) + _mesa_strncat(ret_str, "|4X", 1024); + + if (mod & GL_8X_BIT_ATI) + _mesa_strncat(ret_str, "|8X", 1024); + if (mod & GL_HALF_BIT_ATI) + _mesa_strncat(ret_str, "|HA", 1024); + if (mod & GL_QUARTER_BIT_ATI) + _mesa_strncat(ret_str, "|QU", 1024); + if (mod & GL_EIGHTH_BIT_ATI) + _mesa_strncat(ret_str, "|EI", 1024); + + if (mod & GL_SATURATE_BIT_ATI) + _mesa_strncat(ret_str, "|SAT", 1024); + + if (_mesa_strlen(ret_str) == 0) + _mesa_strncat(ret_str, "NONE", 1024); + return ret_str; +} + +static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI", + "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" }; + +static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, + GLuint dstMask, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, + GLuint arg3Rep, GLuint arg3Mod) +{ + char *op_name; + + op_name = atifs_ops[(arg_count-1)+(optype?3:0)]; + + fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op), + _mesa_lookup_enum_by_nr(dst)); + if (!optype) + fprintf(stderr, ", %d", dstMask); + + fprintf(stderr, ", %s", create_dst_mod_str(dstMod)); + + fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1), + _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod); + if (arg_count>1) + fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2), + _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod); + if (arg_count>2) + fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3), + _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod); + + fprintf(stderr,")\n"); + +} +#endif + +GLuint GLAPIENTRY +_mesa_GenFragmentShadersATI(GLuint range) +{ + GLuint first; + GLuint i; + GET_CURRENT_CONTEXT(ctx); + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, range); + for (i = 0; i < range; i++) { + _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram); + } + + return first; +} + +void GLAPIENTRY +_mesa_BindFragmentShaderATI(GLuint id) +{ + struct program *prog; + GET_CURRENT_CONTEXT(ctx); + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + + if (curProg->Base.Id == id) { + return; + } + + if (curProg->Base.Id != 0) { + curProg->Base.RefCount--; + if (curProg->Base.RefCount <= 0) { + _mesa_HashRemove(ctx->Shared->Programs, id); + } + } + + /* Go bind */ + if (id == 0) { + prog = ctx->Shared->DefaultFragmentShader; + } + else { + prog = (struct program *) _mesa_HashLookup(ctx->Shared->Programs, id); + if (!prog || prog == &_mesa_DummyProgram) { + /* allocate a new program now */ + prog = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_SHADER_ATI, id); + if (!prog) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI"); + return; + } + _mesa_HashInsert(ctx->Shared->Programs, id, prog); + } + + } + + /* do actual bind */ + ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) prog; + + ASSERT(ctx->ATIFragmentShader.Current); + if (prog) + prog->RefCount++; + + /*if (ctx->Driver.BindProgram) + ctx->Driver.BindProgram(ctx, target, prog); */ +} + +void GLAPIENTRY +_mesa_DeleteFragmentShaderATI(GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + + if (id != 0) { + struct program *prog = (struct program *) + _mesa_HashLookup(ctx->Shared->Programs, id); + if (prog == &_mesa_DummyProgram) { + _mesa_HashRemove(ctx->Shared->Programs, id); + } + else if (prog) { + if (ctx->ATIFragmentShader.Current && + ctx->ATIFragmentShader.Current->Base.Id == id) { + _mesa_BindFragmentShaderATI(0); + } + } + if (!prog->DeletePending) { + prog->DeletePending = GL_TRUE; + prog->RefCount--; + } + if (prog->RefCount <= 0) { + _mesa_HashRemove(ctx->Shared->Programs, id); + ctx->Driver.DeleteProgram(ctx, prog); + } + } +} + +void GLAPIENTRY +_mesa_BeginFragmentShaderATI(void) +{ + GET_CURRENT_CONTEXT(ctx); + + /* malloc the instructions here - not sure if the best place but its + a start */ + ctx->ATIFragmentShader.Current->Instructions = + (struct atifs_instruction *) + _mesa_calloc(sizeof(struct atifs_instruction) * MAX_NUM_PASSES_ATI * + MAX_NUM_INSTRUCTIONS_PER_PASS_ATI * 2); + + ctx->ATIFragmentShader.Current->cur_pass = 0; + ctx->ATIFragmentShader.Compiling = 1; +} + +void GLAPIENTRY +_mesa_EndFragmentShaderATI(void) +{ + GET_CURRENT_CONTEXT(ctx); +#if MESA_DEBUG_ATI_FS + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + GLint i; +#endif + + ctx->ATIFragmentShader.Compiling = 0; + +#if MESA_DEBUG_ATI_FS + for (i = 0; i < curProg->Base.NumInstructions; i++) { + GLuint op0 = curProg->Instructions[i].Opcode[0]; + GLuint op1 = curProg->Instructions[i].Opcode[1]; + const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0"; + const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0"; + GLuint count0 = curProg->Instructions[i].ArgCount[0]; + GLuint count1 = curProg->Instructions[i].ArgCount[1]; + + fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0, + op1, op1_enum, count1); + } +#endif +} + +void GLAPIENTRY +_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) +{ + GET_CURRENT_CONTEXT(ctx); + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + GLint ci; + struct atifs_instruction *curI; + + new_inst(curProg); + ci = curProg->Base.NumInstructions - 1; + /* some validation + if ((swizzle != GL_SWIZZLE_STR_ATI) || + (swizzle != GL_SWIZZLE_STQ_ATI) || + (swizzle != GL_SWIZZLE_STR_DR_ATI) || + (swizzle != GL_SWIZZLE_STQ_DQ_ATI)) + */ + + /* add the instructions */ + curI = &curProg->Instructions[ci]; + + curI->Opcode[0] = ATI_FRAGMENT_SHADER_PASS_OP; + curI->DstReg[0].Index = dst; + curI->SrcReg[0][0].Index = coord; + curI->DstReg[0].Swizzle = swizzle; + +#if MESA_DEBUG_ATI_FS + _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord), + _mesa_lookup_enum_by_nr(swizzle)); +#endif +} + +void GLAPIENTRY +_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) +{ + GET_CURRENT_CONTEXT(ctx); + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + GLint ci; + struct atifs_instruction *curI; + + new_inst(curProg); + + ci = curProg->Base.NumInstructions - 1; + /* add the instructions */ + curI = &curProg->Instructions[ci]; + + curI->Opcode[0] = ATI_FRAGMENT_SHADER_SAMPLE_OP; + curI->DstReg[0].Index = dst; + curI->DstReg[0].Swizzle = swizzle; + + curI->SrcReg[0][0].Index = interp; + +#if MESA_DEBUG_ATI_FS + _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp), + _mesa_lookup_enum_by_nr(swizzle)); +#endif +} + +static void +_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, + GLuint dstMask, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, + GLuint arg3Rep, GLuint arg3Mod) +{ + GET_CURRENT_CONTEXT(ctx); + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + GLint ci; + struct atifs_instruction *curI; + + /* decide whether this is a new instruction or not ... all color instructions are new */ + if (optype == 0) + new_inst(curProg); + + ci = curProg->Base.NumInstructions - 1; + + /* add the instructions */ + curI = &curProg->Instructions[ci]; + + curI->Opcode[optype] = op; + + curI->SrcReg[optype][0].Index = arg1; + curI->SrcReg[optype][0].argRep = arg1Rep; + curI->SrcReg[optype][0].argMod = arg1Mod; + curI->ArgCount[optype] = arg_count; + + if (arg2) { + curI->SrcReg[optype][1].Index = arg2; + curI->SrcReg[optype][1].argRep = arg2Rep; + curI->SrcReg[optype][1].argMod = arg2Mod; + } + + if (arg3) { + curI->SrcReg[optype][2].Index = arg3; + curI->SrcReg[optype][2].argRep = arg3Rep; + curI->SrcReg[optype][2].argMod = arg3Mod; + } + + curI->DstReg[optype].Index = dst; + curI->DstReg[optype].dstMod = dstMod; + curI->DstReg[optype].dstMask = dstMask; + +#if MESA_DEBUG_ATI_FS + debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod); +#endif + +} + +void GLAPIENTRY +_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask, + dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0); +} + +void GLAPIENTRY +_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, + GLuint arg2Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask, + dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, + arg2Mod, 0, 0, 0); +} + +void GLAPIENTRY +_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask, + GLuint dstMod, GLuint arg1, GLuint arg1Rep, + GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, + GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, + GLuint arg3Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask, + dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, + arg2Mod, arg3, arg3Rep, arg3Mod); +} + +void GLAPIENTRY +_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod, + arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0); +} + +void GLAPIENTRY +_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod, + arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0, + 0); +} + +void GLAPIENTRY +_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, + GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, + GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, + GLuint arg3Rep, GLuint arg3Mod) +{ + _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod, + arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, + arg3Rep, arg3Mod); +} + +void GLAPIENTRY +_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint dstindex = dst - GL_CON_0_ATI; + struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; + + COPY_4V(curProg->Constants[dstindex], value); +} |