Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**
  2.  * \file atifragshader.c
  3.  * \author David Airlie
  4.  * Copyright (C) 2004  David Airlie   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  20.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22.  */
  23.  
  24. #include "main/glheader.h"
  25. #include "main/context.h"
  26. #include "main/hash.h"
  27. #include "main/imports.h"
  28. #include "main/macros.h"
  29. #include "main/enums.h"
  30. #include "main/mtypes.h"
  31. #include "main/dispatch.h"
  32. #include "main/atifragshader.h"
  33.  
  34. #define MESA_DEBUG_ATI_FS 0
  35.  
  36. static struct ati_fragment_shader DummyShader;
  37.  
  38.  
  39. /**
  40.  * Allocate and initialize a new ATI fragment shader object.
  41.  */
  42. struct ati_fragment_shader *
  43. _mesa_new_ati_fragment_shader(struct gl_context *ctx, GLuint id)
  44. {
  45.    struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader);
  46.    (void) ctx;
  47.    if (s) {
  48.       s->Id = id;
  49.       s->RefCount = 1;
  50.    }
  51.    return s;
  52. }
  53.  
  54.  
  55. /**
  56.  * Delete the given ati fragment shader
  57.  */
  58. void
  59. _mesa_delete_ati_fragment_shader(struct gl_context *ctx, struct ati_fragment_shader *s)
  60. {
  61.    GLuint i;
  62.    for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
  63.       free(s->Instructions[i]);
  64.       free(s->SetupInst[i]);
  65.    }
  66.    free(s);
  67. }
  68.  
  69.  
  70.  
  71. static void
  72. new_arith_inst(struct ati_fragment_shader *prog)
  73. {
  74. /* set "default" instruction as not all may get defined.
  75.    there is no specified way to express a nop with ati fragment shaders we use
  76.    GL_NONE as the op enum and just set some params to 0 - so nothing to do here */
  77.    prog->numArithInstr[prog->cur_pass >> 1]++;
  78. }
  79.  
  80. static void
  81. new_tex_inst(struct ati_fragment_shader *prog)
  82. {
  83. }
  84.  
  85. static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype)
  86. {
  87.    if (optype == curProg->last_optype) {
  88.       curProg->last_optype = 1;
  89.    }
  90. }
  91.  
  92. #if MESA_DEBUG_ATI_FS
  93. static char *
  94. create_dst_mod_str(GLuint mod)
  95. {
  96.    static char ret_str[1024];
  97.  
  98.    memset(ret_str, 0, 1024);
  99.    if (mod & GL_2X_BIT_ATI)
  100.       strncat(ret_str, "|2X", 1024);
  101.  
  102.    if (mod & GL_4X_BIT_ATI)
  103.       strncat(ret_str, "|4X", 1024);
  104.  
  105.    if (mod & GL_8X_BIT_ATI)
  106.       strncat(ret_str, "|8X", 1024);
  107.    if (mod & GL_HALF_BIT_ATI)
  108.       strncat(ret_str, "|HA", 1024);
  109.    if (mod & GL_QUARTER_BIT_ATI)
  110.       strncat(ret_str, "|QU", 1024);
  111.    if (mod & GL_EIGHTH_BIT_ATI)
  112.       strncat(ret_str, "|EI", 1024);
  113.  
  114.    if (mod & GL_SATURATE_BIT_ATI)
  115.       strncat(ret_str, "|SAT", 1024);
  116.  
  117.    if (strlen(ret_str) == 0)
  118.       strncat(ret_str, "NONE", 1024);
  119.    return ret_str;
  120. }
  121.  
  122. static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI",
  123.                             "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" };
  124.  
  125. static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
  126.                      GLuint dstMask, GLuint dstMod, GLuint arg1,
  127.                      GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
  128.                      GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
  129.                      GLuint arg3Rep, GLuint arg3Mod)
  130. {
  131.   char *op_name;
  132.  
  133.   op_name = atifs_ops[(arg_count-1)+(optype?3:0)];
  134.  
  135.   fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op),
  136.               _mesa_lookup_enum_by_nr(dst));
  137.   if (!optype)
  138.     fprintf(stderr, ", %d", dstMask);
  139.  
  140.   fprintf(stderr, ", %s", create_dst_mod_str(dstMod));
  141.  
  142.   fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1),
  143.               _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod);
  144.   if (arg_count>1)
  145.     fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2),
  146.               _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod);
  147.   if (arg_count>2)
  148.     fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3),
  149.               _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod);
  150.  
  151.   fprintf(stderr,")\n");
  152.  
  153. }
  154. #endif
  155.  
  156. static int check_arith_arg(struct ati_fragment_shader *curProg,
  157.                         GLuint optype, GLuint arg, GLuint argRep)
  158. {
  159.    GET_CURRENT_CONTEXT(ctx);
  160.  
  161.    if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) &&
  162.       ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) &&
  163.       (arg != GL_ZERO) && (arg != GL_ONE) &&
  164.       (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) {
  165.       _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)");
  166.       return 0;
  167.    }
  168.    if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
  169.       ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
  170.       _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
  171.       return 0;
  172.    }
  173.    if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) ||
  174.       ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) {
  175.       _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
  176.       return 0;
  177.    }
  178.    if ((curProg->cur_pass == 1) &&
  179.       ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) {
  180.       curProg->interpinp1 = GL_TRUE;
  181.    }
  182.    return 1;
  183. }
  184.  
  185. GLuint GLAPIENTRY
  186. _mesa_GenFragmentShadersATI(GLuint range)
  187. {
  188.    GLuint first;
  189.    GLuint i;
  190.    GET_CURRENT_CONTEXT(ctx);
  191.  
  192.    if (range == 0) {
  193.       _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)");
  194.       return 0;
  195.    }
  196.  
  197.    if (ctx->ATIFragmentShader.Compiling) {
  198.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)");
  199.       return 0;
  200.    }
  201.  
  202.    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range);
  203.    for (i = 0; i < range; i++) {
  204.       _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader);
  205.    }
  206.  
  207.    return first;
  208. }
  209.  
  210. void GLAPIENTRY
  211. _mesa_BindFragmentShaderATI(GLuint id)
  212. {
  213.    GET_CURRENT_CONTEXT(ctx);
  214.    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
  215.    struct ati_fragment_shader *newProg;
  216.  
  217.    if (ctx->ATIFragmentShader.Compiling) {
  218.       _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)");
  219.       return;
  220.    }
  221.  
  222.    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
  223.  
  224.    if (curProg->Id == id) {
  225.       return;
  226.    }
  227.  
  228.    /* unbind current */
  229.    if (curProg->Id != 0) {
  230.       curProg->RefCount--;
  231.       if (curProg->RefCount <= 0) {
  232.          _mesa_HashRemove(ctx->Shared->ATIShaders, id);
  233.       }
  234.    }
  235.  
  236.    /* find new shader */
  237.    if (id == 0) {
  238.       newProg = ctx->Shared->DefaultFragmentShader;
  239.    }
  240.    else {
  241.       newProg = (struct ati_fragment_shader *)
  242.          _mesa_HashLookup(ctx->Shared->ATIShaders, id);
  243.       if (!newProg || newProg == &DummyShader) {
  244.          /* allocate a new program now */
  245.          newProg = _mesa_new_ati_fragment_shader(ctx, id);
  246.          if (!newProg) {
  247.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI");
  248.             return;
  249.          }
  250.          _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg);
  251.       }
  252.  
  253.    }
  254.  
  255.    /* do actual bind */
  256.    ctx->ATIFragmentShader.Current = newProg;
  257.  
  258.    ASSERT(ctx->ATIFragmentShader.Current);
  259.    if (newProg)
  260.       newProg->RefCount++;
  261.  
  262.    /*if (ctx->Driver.BindProgram)
  263.       ctx->Driver.BindProgram(ctx, target, prog); */
  264. }
  265.  
  266. void GLAPIENTRY
  267. _mesa_DeleteFragmentShaderATI(GLuint id)
  268. {
  269.    GET_CURRENT_CONTEXT(ctx);
  270.  
  271.    if (ctx->ATIFragmentShader.Compiling) {
  272.       _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)");
  273.       return;
  274.    }
  275.  
  276.    if (id != 0) {
  277.       struct ati_fragment_shader *prog = (struct ati_fragment_shader *)
  278.          _mesa_HashLookup(ctx->Shared->ATIShaders, id);
  279.       if (prog == &DummyShader) {
  280.          _mesa_HashRemove(ctx->Shared->ATIShaders, id);
  281.       }
  282.       else if (prog) {
  283.          if (ctx->ATIFragmentShader.Current &&
  284.              ctx->ATIFragmentShader.Current->Id == id) {
  285.              FLUSH_VERTICES(ctx, _NEW_PROGRAM);
  286.             _mesa_BindFragmentShaderATI(0);
  287.          }
  288.       }
  289.  
  290.       /* The ID is immediately available for re-use now */
  291.       _mesa_HashRemove(ctx->Shared->ATIShaders, id);
  292.       if (prog) {
  293.          prog->RefCount--;
  294.          if (prog->RefCount <= 0) {
  295.             assert(prog != &DummyShader);
  296.             free(prog);
  297.          }
  298.       }
  299.    }
  300. }
  301.  
  302.  
  303. void GLAPIENTRY
  304. _mesa_BeginFragmentShaderATI(void)
  305. {
  306.    GLint i;
  307.    GET_CURRENT_CONTEXT(ctx);
  308.  
  309.    if (ctx->ATIFragmentShader.Compiling) {
  310.       _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)");
  311.       return;
  312.    }
  313.  
  314.    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
  315.  
  316.    /* if the shader was already defined free instructions and get new ones
  317.       (or, could use the same mem but would need to reinitialize) */
  318.    /* no idea if it's allowed to redefine a shader */
  319.    for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
  320.          free(ctx->ATIFragmentShader.Current->Instructions[i]);
  321.          free(ctx->ATIFragmentShader.Current->SetupInst[i]);
  322.    }
  323.  
  324.    /* malloc the instructions here - not sure if the best place but its
  325.       a start */
  326.    for (i = 0; i < MAX_NUM_PASSES_ATI; i++) {
  327.       ctx->ATIFragmentShader.Current->Instructions[i] =
  328.          calloc(1, sizeof(struct atifs_instruction) *
  329.                    (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI));
  330.       ctx->ATIFragmentShader.Current->SetupInst[i] =
  331.          calloc(1, sizeof(struct atifs_setupinst) *
  332.                    (MAX_NUM_FRAGMENT_REGISTERS_ATI));
  333.    }
  334.  
  335. /* can't rely on calloc for initialization as it's possible to redefine a shader (?) */
  336.    ctx->ATIFragmentShader.Current->LocalConstDef = 0;
  337.    ctx->ATIFragmentShader.Current->numArithInstr[0] = 0;
  338.    ctx->ATIFragmentShader.Current->numArithInstr[1] = 0;
  339.    ctx->ATIFragmentShader.Current->regsAssigned[0] = 0;
  340.    ctx->ATIFragmentShader.Current->regsAssigned[1] = 0;
  341.    ctx->ATIFragmentShader.Current->NumPasses = 0;
  342.    ctx->ATIFragmentShader.Current->cur_pass = 0;
  343.    ctx->ATIFragmentShader.Current->last_optype = 0;
  344.    ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE;
  345.    ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
  346.    ctx->ATIFragmentShader.Current->swizzlerq = 0;
  347.    ctx->ATIFragmentShader.Compiling = 1;
  348. }
  349.  
  350. void GLAPIENTRY
  351. _mesa_EndFragmentShaderATI(void)
  352. {
  353.    GET_CURRENT_CONTEXT(ctx);
  354.    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
  355. #if MESA_DEBUG_ATI_FS
  356.    GLint i, j;
  357. #endif
  358.  
  359.    if (!ctx->ATIFragmentShader.Compiling) {
  360.       _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)");
  361.       return;
  362.    }
  363.    if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) {
  364.       _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)");
  365.    /* according to spec, DON'T return here */
  366.    }
  367.  
  368.    match_pair_inst(curProg, 0);
  369.    ctx->ATIFragmentShader.Compiling = 0;
  370.    ctx->ATIFragmentShader.Current->isValid = GL_TRUE;
  371.    if ((ctx->ATIFragmentShader.Current->cur_pass == 0) ||
  372.       (ctx->ATIFragmentShader.Current->cur_pass == 2)) {
  373.       _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)");
  374.    }
  375.    if (ctx->ATIFragmentShader.Current->cur_pass > 1)
  376.       ctx->ATIFragmentShader.Current->NumPasses = 2;
  377.    else
  378.       ctx->ATIFragmentShader.Current->NumPasses = 1;
  379.  
  380.    ctx->ATIFragmentShader.Current->cur_pass = 0;
  381.  
  382. #if MESA_DEBUG_ATI_FS
  383.    for (j = 0; j < MAX_NUM_PASSES_ATI; j++) {
  384.       for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) {
  385.          GLuint op = curProg->SetupInst[j][i].Opcode;
  386.          const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0";
  387.          GLuint src = curProg->SetupInst[j][i].src;
  388.          GLuint swizzle = curProg->SetupInst[j][i].swizzle;
  389.          fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src,
  390.               swizzle);
  391.       }
  392.       for (i = 0; i < curProg->numArithInstr[j]; i++) {
  393.          GLuint op0 = curProg->Instructions[j][i].Opcode[0];
  394.          GLuint op1 = curProg->Instructions[j][i].Opcode[1];
  395.          const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0";
  396.          const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0";
  397.          GLuint count0 = curProg->Instructions[j][i].ArgCount[0];
  398.          GLuint count1 = curProg->Instructions[j][i].ArgCount[1];
  399.          fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0,
  400.               op1, op1_enum, count1);
  401.       }
  402.    }
  403. #endif
  404.  
  405.    if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) {
  406.       ctx->ATIFragmentShader.Current->isValid = GL_FALSE;
  407.       /* XXX is this the right error? */
  408.       _mesa_error(ctx, GL_INVALID_OPERATION,
  409.                   "glEndFragmentShaderATI(driver rejected shader)");
  410.    }
  411. }
  412.  
  413. void GLAPIENTRY
  414. _mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle)
  415. {
  416.    GET_CURRENT_CONTEXT(ctx);
  417.    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
  418.    struct atifs_setupinst *curI;
  419.  
  420.    if (!ctx->ATIFragmentShader.Compiling) {
  421.       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)");
  422.       return;
  423.    }
  424.  
  425.    if (curProg->cur_pass == 1) {
  426.       match_pair_inst(curProg, 0);
  427.       curProg->cur_pass = 2;
  428.    }
  429.    if ((curProg->cur_pass > 2) ||
  430.       ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
  431.       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)");
  432.       return;
  433.    }
  434.    if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
  435.       ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
  436.       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)");
  437.       return;
  438.    }
  439.    if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) &&
  440.        ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) ||
  441.        ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
  442.       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)");
  443.       return;
  444.    }
  445.    if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) {
  446.       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)");
  447.       return;
  448.    }
  449.    if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
  450.       _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)");
  451.       return;
  452.    }
  453.    if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) {
  454.       _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
  455.       return;
  456.    }
  457.    if (coord <= GL_TEXTURE7_ARB) {
  458.       GLuint tmp = coord - GL_TEXTURE0_ARB;
  459.       if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
  460.            (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
  461.          _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)");
  462.          return;
  463.       } else {
  464.          curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
  465.       }
  466.    }
  467.  
  468.    curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
  469.    new_tex_inst(curProg);
  470.  
  471.    /* add the instructions */
  472.    curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
  473.  
  474.    curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP;
  475.    curI->src = coord;
  476.    curI->swizzle = swizzle;
  477.  
  478. #if MESA_DEBUG_ATI_FS
  479.    _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
  480.                _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord),
  481.                _mesa_lookup_enum_by_nr(swizzle));
  482. #endif
  483. }
  484.  
  485. void GLAPIENTRY
  486. _mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle)
  487. {
  488.    GET_CURRENT_CONTEXT(ctx);
  489.    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
  490.    struct atifs_setupinst *curI;
  491.  
  492.    if (!ctx->ATIFragmentShader.Compiling) {
  493.       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)");
  494.       return;
  495.    }
  496.  
  497.    if (curProg->cur_pass == 1) {
  498.       match_pair_inst(curProg, 0);
  499.       curProg->cur_pass = 2;
  500.    }
  501.    if ((curProg->cur_pass > 2) ||
  502.       ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) {
  503.       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)");
  504.       return;
  505.    }
  506.    if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) ||
  507.       ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) {
  508.       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)");
  509.       return;
  510.    }
  511.    if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) &&
  512.        ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) ||
  513.        ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) {
  514.    /* is this texture5 or texture7? spec is a bit unclear there */
  515.       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)");
  516.       return;
  517.    }
  518.    if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) {
  519.       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)");
  520.       return;
  521.    }
  522.    if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) {
  523.       _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)");
  524.       return;
  525.    }
  526.    if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) {
  527.       _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
  528.       return;
  529.    }
  530.    if (interp <= GL_TEXTURE7_ARB) {
  531.       GLuint tmp = interp - GL_TEXTURE0_ARB;
  532.       if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) &&
  533.            (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) {
  534.          _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)");
  535.          return;
  536.       } else {
  537.          curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2));
  538.       }
  539.    }
  540.  
  541.    curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI);
  542.    new_tex_inst(curProg);
  543.  
  544.    /* add the instructions */
  545.    curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI];
  546.  
  547.    curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP;
  548.    curI->src = interp;
  549.    curI->swizzle = swizzle;
  550.  
  551. #if MESA_DEBUG_ATI_FS
  552.    _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__,
  553.                _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp),
  554.                _mesa_lookup_enum_by_nr(swizzle));
  555. #endif
  556. }
  557.  
  558. static void
  559. _mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst,
  560.                      GLuint dstMask, GLuint dstMod, GLuint arg1,
  561.                      GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
  562.                      GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
  563.                      GLuint arg3Rep, GLuint arg3Mod)
  564. {
  565.    GET_CURRENT_CONTEXT(ctx);
  566.    struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
  567.    GLint ci;
  568.    struct atifs_instruction *curI;
  569.    GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI;
  570.  
  571.    if (!ctx->ATIFragmentShader.Compiling) {
  572.       _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)");
  573.       return;
  574.    }
  575.  
  576.    if (curProg->cur_pass==0)
  577.       curProg->cur_pass=1;
  578.  
  579.    else if (curProg->cur_pass==2)
  580.       curProg->cur_pass=3;
  581.  
  582.    /* decide whether this is a new instruction or not ... all color instructions are new,
  583.       and alpha instructions might also be new if there was no preceding color inst */
  584.    if ((optype == 0) || (curProg->last_optype == optype)) {
  585.       if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) {
  586.          _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)");
  587.          return;
  588.       }
  589.       /* easier to do that here slight side effect invalid instr will still be inserted as nops */
  590.       match_pair_inst(curProg, optype);
  591.       new_arith_inst(curProg);
  592.    }
  593.    curProg->last_optype = optype;
  594.    ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1;
  595.  
  596.    /* add the instructions */
  597.    curI = &curProg->Instructions[curProg->cur_pass >> 1][ci];
  598.  
  599.    /* error checking */
  600.    if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) {
  601.       _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)");
  602.       return;
  603.    }
  604.    if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) &&
  605.       (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) &&
  606.       (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) &&
  607.       (modtemp != GL_EIGHTH_BIT_ATI)) {
  608.       _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp);
  609.       return;
  610.    }
  611.    /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */
  612.    if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) {
  613.       _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)");
  614.       return;
  615.    }
  616.    if (optype == 1) {
  617.       if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) ||
  618.          ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) ||
  619.          ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) ||
  620.          ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) {
  621.          _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)");
  622.          return;
  623.       }
  624.    }
  625.    if ((op == GL_DOT4_ATI) &&
  626.       (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) ||
  627.       (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) {
  628.       _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)");
  629.    }
  630.  
  631.    if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) {
  632.       return;
  633.    }
  634.    if (arg2) {
  635.       if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) {
  636.          return;
  637.       }
  638.    }
  639.    if (arg3) {
  640.       if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) {
  641.          return;
  642.       }
  643.       if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) &&
  644.           (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) &&
  645.           (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) &&
  646.           (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) {
  647.          _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)");
  648.          return;
  649.       }
  650.    }
  651.  
  652.    /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */
  653.  
  654.    curI->Opcode[optype] = op;
  655.    curI->SrcReg[optype][0].Index = arg1;
  656.    curI->SrcReg[optype][0].argRep = arg1Rep;
  657.    curI->SrcReg[optype][0].argMod = arg1Mod;
  658.    curI->ArgCount[optype] = arg_count;
  659.  
  660.    if (arg2) {
  661.       curI->SrcReg[optype][1].Index = arg2;
  662.       curI->SrcReg[optype][1].argRep = arg2Rep;
  663.       curI->SrcReg[optype][1].argMod = arg2Mod;
  664.    }
  665.  
  666.    if (arg3) {
  667.       curI->SrcReg[optype][2].Index = arg3;
  668.       curI->SrcReg[optype][2].argRep = arg3Rep;
  669.       curI->SrcReg[optype][2].argMod = arg3Mod;
  670.    }
  671.  
  672.    curI->DstReg[optype].Index = dst;
  673.    curI->DstReg[optype].dstMod = dstMod;
  674.    curI->DstReg[optype].dstMask = dstMask;
  675.  
  676. #if MESA_DEBUG_ATI_FS
  677.    debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
  678. #endif
  679.  
  680. }
  681.  
  682. void GLAPIENTRY
  683. _mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask,
  684.                           GLuint dstMod, GLuint arg1, GLuint arg1Rep,
  685.                           GLuint arg1Mod)
  686. {
  687.    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask,
  688.                         dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
  689. }
  690.  
  691. void GLAPIENTRY
  692. _mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask,
  693.                           GLuint dstMod, GLuint arg1, GLuint arg1Rep,
  694.                           GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
  695.                           GLuint arg2Mod)
  696. {
  697.    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask,
  698.                         dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
  699.                         arg2Mod, 0, 0, 0);
  700. }
  701.  
  702. void GLAPIENTRY
  703. _mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask,
  704.                           GLuint dstMod, GLuint arg1, GLuint arg1Rep,
  705.                           GLuint arg1Mod, GLuint arg2, GLuint arg2Rep,
  706.                           GLuint arg2Mod, GLuint arg3, GLuint arg3Rep,
  707.                           GLuint arg3Mod)
  708. {
  709.    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask,
  710.                         dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep,
  711.                         arg2Mod, arg3, arg3Rep, arg3Mod);
  712. }
  713.  
  714. void GLAPIENTRY
  715. _mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
  716.                           GLuint arg1Rep, GLuint arg1Mod)
  717. {
  718.    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod,
  719.                         arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0);
  720. }
  721.  
  722. void GLAPIENTRY
  723. _mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
  724.                           GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
  725.                           GLuint arg2Rep, GLuint arg2Mod)
  726. {
  727.    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod,
  728.                         arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0,
  729.                         0);
  730. }
  731.  
  732. void GLAPIENTRY
  733. _mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1,
  734.                           GLuint arg1Rep, GLuint arg1Mod, GLuint arg2,
  735.                           GLuint arg2Rep, GLuint arg2Mod, GLuint arg3,
  736.                           GLuint arg3Rep, GLuint arg3Mod)
  737. {
  738.    _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod,
  739.                         arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3,
  740.                         arg3Rep, arg3Mod);
  741. }
  742.  
  743. void GLAPIENTRY
  744. _mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value)
  745. {
  746.    GLuint dstindex;
  747.    GET_CURRENT_CONTEXT(ctx);
  748.  
  749.    if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) {
  750.       /* spec says nothing about what should happen here but we can't just segfault...*/
  751.       _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)");
  752.       return;
  753.    }
  754.  
  755.    dstindex = dst - GL_CON_0_ATI;
  756.    if (ctx->ATIFragmentShader.Compiling) {
  757.       struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current;
  758.       COPY_4V(curProg->Constants[dstindex], value);
  759.       curProg->LocalConstDef |= 1 << dstindex;
  760.    }
  761.    else {
  762.       FLUSH_VERTICES(ctx, _NEW_PROGRAM);
  763.       COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value);
  764.    }
  765. }
  766.