X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fatifragshader.c;h=44f6bb46484293c5f44fed89b52e09593ccf1a9d;hb=9037005d6034d6bcbeb508e0f783622e2351b957;hp=8fcbff6a7a4db5a4d881e54f8cec03e38fcb813d;hpb=83c86e09a8d7610022eae49731ac1ed03ee4f67b;p=mesa.git diff --git a/src/mesa/main/atifragshader.c b/src/mesa/main/atifragshader.c index 8fcbff6a7a4..44f6bb46484 100644 --- a/src/mesa/main/atifragshader.c +++ b/src/mesa/main/atifragshader.c @@ -24,12 +24,13 @@ #include "main/glheader.h" #include "main/context.h" #include "main/hash.h" -#include "main/imports.h" + #include "main/macros.h" #include "main/enums.h" #include "main/mtypes.h" -#include "main/dispatch.h" #include "main/atifragshader.h" +#include "program/program.h" +#include "util/u_memory.h" #define MESA_DEBUG_ATI_FS 0 @@ -59,33 +60,23 @@ void _mesa_delete_ati_fragment_shader(struct gl_context *ctx, struct ati_fragment_shader *s) { GLuint i; + + if (s == &DummyShader) + return; + for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { free(s->Instructions[i]); free(s->SetupInst[i]); } + _mesa_reference_program(ctx, &s->Program, NULL); free(s); } - -static void -new_arith_inst(struct ati_fragment_shader *prog) -{ -/* set "default" instruction as not all may get defined. - there is no specified way to express a nop with ati fragment shaders we use - GL_NONE as the op enum and just set some params to 0 - so nothing to do here */ - prog->numArithInstr[prog->cur_pass >> 1]++; -} - -static void -new_tex_inst(struct ati_fragment_shader *prog) -{ -} - static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype) { if (optype == curProg->last_optype) { - curProg->last_optype = 1; + curProg->last_optype = ATI_FRAGMENT_SHADER_ALPHA_OP; } } @@ -119,7 +110,7 @@ create_dst_mod_str(GLuint mod) return ret_str; } -static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI", +static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI", "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" }; static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, @@ -131,14 +122,14 @@ static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, char *op_name; op_name = atifs_ops[(arg_count-1)+(optype?3:0)]; - + fprintf(stderr, "%s(%s, %s", op_name, _mesa_enum_to_string(op), _mesa_enum_to_string(dst)); - if (!optype) + if (optype == ATI_FRAGMENT_SHADER_COLOR_OP) fprintf(stderr, ", %d", dstMask); - + fprintf(stderr, ", %s", create_dst_mod_str(dstMod)); - + fprintf(stderr, ", %s, %s, %d", _mesa_enum_to_string(arg1), _mesa_enum_to_string(arg1Rep), arg1Mod); if (arg_count>1) @@ -153,8 +144,8 @@ static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, } #endif -static int check_arith_arg(struct ati_fragment_shader *curProg, - GLuint optype, GLuint arg, GLuint argRep) +static int +check_arith_arg(GLuint optype, GLuint arg, GLuint argRep) { GET_CURRENT_CONTEXT(ctx); @@ -165,23 +156,34 @@ static int check_arith_arg(struct ati_fragment_shader *curProg, _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)"); return 0; } - if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) || - ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) { - _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); - return 0; - } - if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) || - ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) { - _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); - return 0; - } - if ((curProg->cur_pass == 1) && - ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) { - curProg->interpinp1 = GL_TRUE; + /* The ATI_fragment_shader spec says: + * + * The error INVALID_OPERATION is generated by + * ColorFragmentOp[1..3]ATI if is SECONDARY_INTERPOLATOR_ATI + * and is ALPHA, or by AlphaFragmentOp[1..3]ATI if + * is SECONDARY_INTERPOLATOR_ATI and is ALPHA or NONE, ... + */ + if (arg == GL_SECONDARY_INTERPOLATOR_ATI) { + if (optype == ATI_FRAGMENT_SHADER_COLOR_OP && argRep == GL_ALPHA) { + _mesa_error(ctx, GL_INVALID_OPERATION, "CFragmentOpATI(sec_interp)"); + return 0; + } else if (optype == ATI_FRAGMENT_SHADER_ALPHA_OP && + (argRep == GL_ALPHA || argRep == GL_NONE)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(sec_interp)"); + return 0; + } } return 1; } +static GLboolean +check_arg_color(GLubyte pass, GLuint arg) +{ + if (pass == 1 && (arg == GL_PRIMARY_COLOR_ARB || arg == GL_SECONDARY_INTERPOLATOR_ATI)) + return GL_TRUE; + return GL_FALSE; +} + GLuint GLAPIENTRY _mesa_GenFragmentShadersATI(GLuint range) { @@ -199,11 +201,15 @@ _mesa_GenFragmentShadersATI(GLuint range) return 0; } + _mesa_HashLockMutex(ctx->Shared->ATIShaders); + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range); for (i = 0; i < range; i++) { - _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader); + _mesa_HashInsertLocked(ctx->Shared->ATIShaders, first + i, &DummyShader); } + _mesa_HashUnlockMutex(ctx->Shared->ATIShaders); + return first; } @@ -258,9 +264,6 @@ _mesa_BindFragmentShaderATI(GLuint id) assert(ctx->ATIFragmentShader.Current); if (newProg) newProg->RefCount++; - - /*if (ctx->Driver.BindProgram) - ctx->Driver.BindProgram(ctx, target, prog); */ } void GLAPIENTRY @@ -292,7 +295,6 @@ _mesa_DeleteFragmentShaderATI(GLuint id) if (prog) { prog->RefCount--; if (prog->RefCount <= 0) { - assert(prog != &DummyShader); _mesa_delete_ati_fragment_shader(ctx, prog); } } @@ -321,6 +323,8 @@ _mesa_BeginFragmentShaderATI(void) free(ctx->ATIFragmentShader.Current->SetupInst[i]); } + _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, NULL); + /* malloc the instructions here - not sure if the best place but its a start */ for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { @@ -405,7 +409,17 @@ _mesa_EndFragmentShaderATI(void) } #endif - if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) { + if (ctx->Driver.NewATIfs) { + struct gl_program *prog = ctx->Driver.NewATIfs(ctx, + ctx->ATIFragmentShader.Current); + _mesa_reference_program(ctx, &ctx->ATIFragmentShader.Current->Program, + NULL); + /* Don't use _mesa_reference_program(), just take ownership */ + ctx->ATIFragmentShader.Current->Program = prog; + } + + if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, + curProg->Program)) { ctx->ATIFragmentShader.Current->isValid = GL_FALSE; /* XXX is this the right error? */ _mesa_error(ctx, GL_INVALID_OPERATION, @@ -419,18 +433,17 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) GET_CURRENT_CONTEXT(ctx); struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; struct atifs_setupinst *curI; + GLubyte new_pass = curProg->cur_pass; if (!ctx->ATIFragmentShader.Compiling) { _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)"); return; } - if (curProg->cur_pass == 1) { - match_pair_inst(curProg, 0); - curProg->cur_pass = 2; - } - if ((curProg->cur_pass > 2) || - ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) { + if (curProg->cur_pass == 1) + new_pass = 2; + if ((new_pass > 2) || + ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[new_pass >> 1])) { _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)"); return; } @@ -445,7 +458,7 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)"); return; } - if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) { + if ((new_pass == 0) && (coord >= GL_REG_0_ATI)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)"); return; } @@ -468,8 +481,10 @@ _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) } } + if (curProg->cur_pass == 1) + match_pair_inst(curProg, 0); + curProg->cur_pass = new_pass; curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); - new_tex_inst(curProg); /* add the instructions */ curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI]; @@ -491,18 +506,17 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) GET_CURRENT_CONTEXT(ctx); struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; struct atifs_setupinst *curI; + GLubyte new_pass = curProg->cur_pass; if (!ctx->ATIFragmentShader.Compiling) { _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)"); return; } - if (curProg->cur_pass == 1) { - match_pair_inst(curProg, 0); - curProg->cur_pass = 2; - } - if ((curProg->cur_pass > 2) || - ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) { + if (curProg->cur_pass == 1) + new_pass = 2; + if ((new_pass > 2) || + ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[new_pass >> 1])) { _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)"); return; } @@ -518,7 +532,7 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)"); return; } - if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) { + if ((new_pass == 0) && (interp >= GL_REG_0_ATI)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)"); return; } @@ -541,8 +555,10 @@ _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) } } + if (curProg->cur_pass == 1) + match_pair_inst(curProg, 0); + curProg->cur_pass = new_pass; curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); - new_tex_inst(curProg); /* add the instructions */ curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI]; @@ -570,34 +586,36 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, GLint ci; struct atifs_instruction *curI; GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI; + GLubyte new_pass = curProg->cur_pass; + GLubyte numArithInstr; if (!ctx->ATIFragmentShader.Compiling) { _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)"); return; } - if (curProg->cur_pass==0) - curProg->cur_pass=1; + if (curProg->cur_pass == 0) + new_pass = 1; + else if (curProg->cur_pass == 2) + new_pass = 3; - else if (curProg->cur_pass==2) - curProg->cur_pass=3; + numArithInstr = curProg->numArithInstr[new_pass >> 1]; - /* decide whether this is a new instruction or not ... all color instructions are new, - and alpha instructions might also be new if there was no preceding color inst */ - if ((optype == 0) || (curProg->last_optype == optype)) { - if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) { + /* Decide whether this is a new instruction or not. All color instructions + * are new, and alpha instructions might also be new if there was no + * preceding color inst. This may also be the first inst of the pass + */ + if (optype == ATI_FRAGMENT_SHADER_COLOR_OP || + curProg->last_optype == optype || + curProg->numArithInstr[new_pass >> 1] == 0) { + if (curProg->numArithInstr[new_pass >> 1] > 7) { _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)"); return; } - /* easier to do that here slight side effect invalid instr will still be inserted as nops */ - match_pair_inst(curProg, optype); - new_arith_inst(curProg); + numArithInstr++; } - curProg->last_optype = optype; - ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1; - - /* add the instructions */ - curI = &curProg->Instructions[curProg->cur_pass >> 1][ci]; + ci = numArithInstr - 1; + curI = &curProg->Instructions[new_pass >> 1][ci]; /* error checking */ if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) { @@ -606,7 +624,7 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, } if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) && (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) && - (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) && + (modtemp != GL_HALF_BIT_ATI) && (modtemp != GL_QUARTER_BIT_ATI) && (modtemp != GL_EIGHTH_BIT_ATI)) { _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp); return; @@ -616,7 +634,7 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)"); return; } - if (optype == 1) { + if (optype == ATI_FRAGMENT_SHADER_ALPHA_OP) { if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) || ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) || ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) || @@ -625,22 +643,29 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, return; } } - if ((op == GL_DOT4_ATI) && - (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) || - (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) { - _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); + /* The ATI_fragment_shader spec says: + * + * The error INVALID_OPERATION is generated by... ColorFragmentOp2ATI + * if is DOT4_ATI and is SECONDARY_INTERPOLATOR_ATI and + * is ALPHA or NONE. + */ + if (optype == ATI_FRAGMENT_SHADER_COLOR_OP && op == GL_DOT4_ATI && + ((arg1 == GL_SECONDARY_INTERPOLATOR_ATI && (arg1Rep == GL_ALPHA || arg1Rep == GL_NONE)) || + (arg2 == GL_SECONDARY_INTERPOLATOR_ATI && (arg2Rep == GL_ALPHA || arg2Rep == GL_NONE)))) { + _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interpDOT4)"); + return; } - if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) { + if (!check_arith_arg(optype, arg1, arg1Rep)) { return; } if (arg2) { - if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) { + if (!check_arith_arg(optype, arg2, arg2Rep)) { return; } } if (arg3) { - if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) { + if (!check_arith_arg(optype, arg3, arg3Rep)) { return; } if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) && @@ -654,6 +679,16 @@ _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */ + curProg->interpinp1 |= check_arg_color(new_pass, arg1); + if (arg2) + curProg->interpinp1 |= check_arg_color(new_pass, arg2); + if (arg3) + curProg->interpinp1 |= check_arg_color(new_pass, arg3); + + curProg->numArithInstr[new_pass >> 1] = numArithInstr; + curProg->last_optype = optype; + curProg->cur_pass = new_pass; + curI->Opcode[optype] = op; curI->SrcReg[optype][0].Index = arg1; curI->SrcReg[optype][0].argRep = arg1Rep;