summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader/atifragshader.c
diff options
context:
space:
mode:
authorDave Airlie <airliedfreedesktop.org>2004-12-19 03:06:59 +0000
committerDave Airlie <airliedfreedesktop.org>2004-12-19 03:06:59 +0000
commit7f752fed993e5e9423abac200dd59141edbada56 (patch)
tree06eba28f01c81dfbd8c4a9104206765f8731528c /src/mesa/shader/atifragshader.c
parenta803b0c891404dcd7c376e91f6a033cd4e42abc3 (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.c419
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);
+}