Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.0
  4.  *
  5.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. /**
  26.  * \file arbprogram.c
  27.  * ARB_vertex/fragment_program state management functions.
  28.  * \author Brian Paul
  29.  */
  30.  
  31.  
  32. #include "main/glheader.h"
  33. #include "main/context.h"
  34. #include "main/hash.h"
  35. #include "main/imports.h"
  36. #include "main/macros.h"
  37. #include "main/mtypes.h"
  38. #include "main/arbprogram.h"
  39. #include "program/arbprogparse.h"
  40. #include "program/nvfragparse.h"
  41. #include "program/nvvertparse.h"
  42. #include "program/program.h"
  43.  
  44.  
  45.  
  46. /**
  47.  * Mixing ARB and NV vertex/fragment programs can be tricky.
  48.  * Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
  49.  *  but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
  50.  * The two different fragment program targets are supposed to be compatible
  51.  * to some extent (see GL_ARB_fragment_program spec).
  52.  * This function does the compatibility check.
  53.  */
  54. static GLboolean
  55. compatible_program_targets(GLenum t1, GLenum t2)
  56. {
  57.    if (t1 == t2)
  58.       return GL_TRUE;
  59.    if (t1 == GL_FRAGMENT_PROGRAM_ARB && t2 == GL_FRAGMENT_PROGRAM_NV)
  60.       return GL_TRUE;
  61.    if (t1 == GL_FRAGMENT_PROGRAM_NV && t2 == GL_FRAGMENT_PROGRAM_ARB)
  62.       return GL_TRUE;
  63.    return GL_FALSE;
  64. }
  65.  
  66.  
  67. /**
  68.  * Bind a program (make it current)
  69.  * \note Called from the GL API dispatcher by both glBindProgramNV
  70.  * and glBindProgramARB.
  71.  */
  72. void GLAPIENTRY
  73. _mesa_BindProgram(GLenum target, GLuint id)
  74. {
  75.    struct gl_program *curProg, *newProg;
  76.    GET_CURRENT_CONTEXT(ctx);
  77.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  78.  
  79.    /* Error-check target and get curProg */
  80.    if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */
  81.         (ctx->Extensions.NV_vertex_program ||
  82.          ctx->Extensions.ARB_vertex_program)) {
  83.       curProg = &ctx->VertexProgram.Current->Base;
  84.    }
  85.    else if ((target == GL_FRAGMENT_PROGRAM_NV
  86.              && ctx->Extensions.NV_fragment_program) ||
  87.             (target == GL_FRAGMENT_PROGRAM_ARB
  88.              && ctx->Extensions.ARB_fragment_program)) {
  89.       curProg = &ctx->FragmentProgram.Current->Base;
  90.    }
  91.    else {
  92.       _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
  93.       return;
  94.    }
  95.  
  96.    /*
  97.     * Get pointer to new program to bind.
  98.     * NOTE: binding to a non-existant program is not an error.
  99.     * That's supposed to be caught in glBegin.
  100.     */
  101.    if (id == 0) {
  102.       /* Bind a default program */
  103.       newProg = NULL;
  104.       if (target == GL_VERTEX_PROGRAM_ARB) /* == GL_VERTEX_PROGRAM_NV */
  105.          newProg = &ctx->Shared->DefaultVertexProgram->Base;
  106.       else
  107.          newProg = &ctx->Shared->DefaultFragmentProgram->Base;
  108.    }
  109.    else {
  110.       /* Bind a user program */
  111.       newProg = _mesa_lookup_program(ctx, id);
  112.       if (!newProg || newProg == &_mesa_DummyProgram) {
  113.          /* allocate a new program now */
  114.          newProg = ctx->Driver.NewProgram(ctx, target, id);
  115.          if (!newProg) {
  116.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
  117.             return;
  118.          }
  119.          _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
  120.       }
  121.       else if (!compatible_program_targets(newProg->Target, target)) {
  122.          _mesa_error(ctx, GL_INVALID_OPERATION,
  123.                      "glBindProgramNV/ARB(target mismatch)");
  124.          return;
  125.       }
  126.    }
  127.  
  128.    /** All error checking is complete now **/
  129.  
  130.    if (curProg->Id == id) {
  131.       /* binding same program - no change */
  132.       return;
  133.    }
  134.  
  135.    /* signal new program (and its new constants) */
  136.    FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
  137.  
  138.    /* bind newProg */
  139.    if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
  140.       _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
  141.                                (struct gl_vertex_program *) newProg);
  142.    }
  143.    else if (target == GL_FRAGMENT_PROGRAM_NV ||
  144.             target == GL_FRAGMENT_PROGRAM_ARB) {
  145.       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
  146.                                (struct gl_fragment_program *) newProg);
  147.    }
  148.  
  149.    /* Never null pointers */
  150.    ASSERT(ctx->VertexProgram.Current);
  151.    ASSERT(ctx->FragmentProgram.Current);
  152.  
  153.    if (ctx->Driver.BindProgram)
  154.       ctx->Driver.BindProgram(ctx, target, newProg);
  155. }
  156.  
  157.  
  158. /**
  159.  * Delete a list of programs.
  160.  * \note Not compiled into display lists.
  161.  * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
  162.  */
  163. void GLAPIENTRY
  164. _mesa_DeletePrograms(GLsizei n, const GLuint *ids)
  165. {
  166.    GLint i;
  167.    GET_CURRENT_CONTEXT(ctx);
  168.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  169.  
  170.    if (n < 0) {
  171.       _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
  172.       return;
  173.    }
  174.  
  175.    for (i = 0; i < n; i++) {
  176.       if (ids[i] != 0) {
  177.          struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
  178.          if (prog == &_mesa_DummyProgram) {
  179.             _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
  180.          }
  181.          else if (prog) {
  182.             /* Unbind program if necessary */
  183.             switch (prog->Target) {
  184.             case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
  185.             case GL_VERTEX_STATE_PROGRAM_NV:
  186.                if (ctx->VertexProgram.Current &&
  187.                    ctx->VertexProgram.Current->Base.Id == ids[i]) {
  188.                   /* unbind this currently bound program */
  189.                   _mesa_BindProgram(prog->Target, 0);
  190.                }
  191.                break;
  192.             case GL_FRAGMENT_PROGRAM_NV:
  193.             case GL_FRAGMENT_PROGRAM_ARB:
  194.                if (ctx->FragmentProgram.Current &&
  195.                    ctx->FragmentProgram.Current->Base.Id == ids[i]) {
  196.                   /* unbind this currently bound program */
  197.                   _mesa_BindProgram(prog->Target, 0);
  198.                }
  199.                break;
  200.             default:
  201.                _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
  202.                return;
  203.             }
  204.             /* The ID is immediately available for re-use now */
  205.             _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
  206.             _mesa_reference_program(ctx, &prog, NULL);
  207.          }
  208.       }
  209.    }
  210. }
  211.  
  212.  
  213. /**
  214.  * Generate a list of new program identifiers.
  215.  * \note Not compiled into display lists.
  216.  * \note Called by both glGenProgramsNV and glGenProgramsARB.
  217.  */
  218. void GLAPIENTRY
  219. _mesa_GenPrograms(GLsizei n, GLuint *ids)
  220. {
  221.    GLuint first;
  222.    GLuint i;
  223.    GET_CURRENT_CONTEXT(ctx);
  224.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  225.  
  226.    if (n < 0) {
  227.       _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
  228.       return;
  229.    }
  230.  
  231.    if (!ids)
  232.       return;
  233.  
  234.    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
  235.  
  236.    /* Insert pointer to dummy program as placeholder */
  237.    for (i = 0; i < (GLuint) n; i++) {
  238.       _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
  239.    }
  240.  
  241.    /* Return the program names */
  242.    for (i = 0; i < (GLuint) n; i++) {
  243.       ids[i] = first + i;
  244.    }
  245. }
  246.  
  247.  
  248. /**
  249.  * Determine if id names a vertex or fragment program.
  250.  * \note Not compiled into display lists.
  251.  * \note Called from both glIsProgramNV and glIsProgramARB.
  252.  * \param id is the program identifier
  253.  * \return GL_TRUE if id is a program, else GL_FALSE.
  254.  */
  255. GLboolean GLAPIENTRY
  256. _mesa_IsProgramARB(GLuint id)
  257. {
  258.    struct gl_program *prog = NULL;
  259.    GET_CURRENT_CONTEXT(ctx);
  260.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  261.  
  262.    if (id == 0)
  263.       return GL_FALSE;
  264.  
  265.    prog = _mesa_lookup_program(ctx, id);
  266.    if (prog && (prog != &_mesa_DummyProgram))
  267.       return GL_TRUE;
  268.    else
  269.       return GL_FALSE;
  270. }
  271.  
  272.  
  273. void GLAPIENTRY
  274. _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
  275.                        const GLvoid *string)
  276. {
  277.    struct gl_program *base;
  278.    GET_CURRENT_CONTEXT(ctx);
  279.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  280.  
  281.    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
  282.  
  283.    if (!ctx->Extensions.ARB_vertex_program
  284.        && !ctx->Extensions.ARB_fragment_program) {
  285.       _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()");
  286.       return;
  287.    }
  288.  
  289.    if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
  290.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
  291.       return;
  292.    }
  293.  
  294.    /* The first couple cases are complicated.  The same enum value is used for
  295.     * ARB and NV vertex programs.  If the target is a vertex program, parse it
  296.     * using the ARB grammar if the string starts with "!!ARB" or if
  297.     * NV_vertex_program is not supported.
  298.     */
  299.    if (target == GL_VERTEX_PROGRAM_ARB
  300.        && ctx->Extensions.ARB_vertex_program
  301.        && ((strncmp(string, "!!ARB", 5) == 0)
  302.            || !ctx->Extensions.NV_vertex_program)) {
  303.       struct gl_vertex_program *prog = ctx->VertexProgram.Current;
  304.       _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
  305.  
  306.       base = & prog->Base;
  307.    }
  308.    else if ((target == GL_VERTEX_PROGRAM_ARB
  309.              || target == GL_VERTEX_STATE_PROGRAM_NV)
  310.             && ctx->Extensions.NV_vertex_program) {
  311.       struct gl_vertex_program *prog = ctx->VertexProgram.Current;
  312.       _mesa_parse_nv_vertex_program(ctx, target, string, len, prog);
  313.  
  314.       base = & prog->Base;
  315.    }
  316.    else if (target == GL_FRAGMENT_PROGRAM_ARB
  317.             && ctx->Extensions.ARB_fragment_program) {
  318.       struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
  319.       _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
  320.  
  321.       base = & prog->Base;
  322.    }
  323.    else if (target == GL_FRAGMENT_PROGRAM_NV
  324.             && ctx->Extensions.NV_fragment_program) {
  325.       struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
  326.       _mesa_parse_nv_fragment_program(ctx, target, string, len, prog);
  327.  
  328.       base = & prog->Base;
  329.    }
  330.    else {
  331.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
  332.       return;
  333.    }
  334.  
  335.    if (ctx->Program.ErrorPos == -1) {
  336.       /* finally, give the program to the driver for translation/checking */
  337.       if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) {
  338.          _mesa_error(ctx, GL_INVALID_OPERATION,
  339.                      "glProgramStringARB(rejected by driver");
  340.       }
  341.    }
  342. }
  343.  
  344.  
  345. /**
  346.  * Set a program env parameter register.
  347.  * \note Called from the GL API dispatcher.
  348.  * Note, this function is also used by the GL_NV_vertex_program extension
  349.  * (alias to ProgramParameterdNV)
  350.  */
  351. void GLAPIENTRY
  352. _mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
  353.                                GLdouble x, GLdouble y, GLdouble z, GLdouble w)
  354. {
  355.    _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
  356.                                   (GLfloat) z, (GLfloat) w);
  357. }
  358.  
  359.  
  360. /**
  361.  * Set a program env parameter register.
  362.  * \note Called from the GL API dispatcher.
  363.  * Note, this function is also used by the GL_NV_vertex_program extension
  364.  * (alias to ProgramParameterdvNV)
  365.  */
  366. void GLAPIENTRY
  367. _mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
  368.                                 const GLdouble *params)
  369. {
  370.    _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
  371.                                   (GLfloat) params[1], (GLfloat) params[2],
  372.                                   (GLfloat) params[3]);
  373. }
  374.  
  375.  
  376. /**
  377.  * Set a program env parameter register.
  378.  * \note Called from the GL API dispatcher.
  379.  * Note, this function is also used by the GL_NV_vertex_program extension
  380.  * (alias to ProgramParameterfNV)
  381.  */
  382. void GLAPIENTRY
  383. _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
  384.                                GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  385. {
  386.    GET_CURRENT_CONTEXT(ctx);
  387.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  388.  
  389.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  390.  
  391.    if (target == GL_FRAGMENT_PROGRAM_ARB
  392.        && ctx->Extensions.ARB_fragment_program) {
  393.       if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
  394.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
  395.          return;
  396.       }
  397.       ASSIGN_4V(ctx->FragmentProgram.Parameters[index], x, y, z, w);
  398.    }
  399.    else if (target == GL_VERTEX_PROGRAM_ARB /* == GL_VERTEX_PROGRAM_NV */
  400.        && (ctx->Extensions.ARB_vertex_program || ctx->Extensions.NV_vertex_program)) {
  401.       if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
  402.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
  403.          return;
  404.       }
  405.       ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
  406.    }
  407.    else {
  408.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter(target)");
  409.       return;
  410.    }
  411. }
  412.  
  413.  
  414.  
  415. /**
  416.  * Set a program env parameter register.
  417.  * \note Called from the GL API dispatcher.
  418.  * Note, this function is also used by the GL_NV_vertex_program extension
  419.  * (alias to ProgramParameterfvNV)
  420.  */
  421. void GLAPIENTRY
  422. _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
  423.                                 const GLfloat *params)
  424. {
  425.    GET_CURRENT_CONTEXT(ctx);
  426.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  427.  
  428.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  429.  
  430.    if (target == GL_FRAGMENT_PROGRAM_ARB
  431.        && ctx->Extensions.ARB_fragment_program) {
  432.       if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
  433.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter4fv(index)");
  434.          return;
  435.       }
  436.       memcpy(ctx->FragmentProgram.Parameters[index], params,
  437.              4 * sizeof(GLfloat));
  438.    }
  439.    else if (target == GL_VERTEX_PROGRAM_ARB /* == GL_VERTEX_PROGRAM_NV */
  440.        && (ctx->Extensions.ARB_vertex_program || ctx->Extensions.NV_vertex_program)) {
  441.       if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
  442.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter4fv(index)");
  443.          return;
  444.       }
  445.       memcpy(ctx->VertexProgram.Parameters[index], params,
  446.              4 * sizeof(GLfloat));
  447.    }
  448.    else {
  449.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter4fv(target)");
  450.       return;
  451.    }
  452. }
  453.  
  454.  
  455. void GLAPIENTRY
  456. _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
  457.                                  const GLfloat *params)
  458. {
  459.    GET_CURRENT_CONTEXT(ctx);
  460.    GLfloat * dest;
  461.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  462.  
  463.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  464.  
  465.    if (count <= 0) {
  466.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
  467.    }
  468.  
  469.    if (target == GL_FRAGMENT_PROGRAM_ARB
  470.        && ctx->Extensions.ARB_fragment_program) {
  471.       if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) {
  472.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
  473.          return;
  474.       }
  475.       dest = ctx->FragmentProgram.Parameters[index];
  476.    }
  477.    else if (target == GL_VERTEX_PROGRAM_ARB
  478.        && ctx->Extensions.ARB_vertex_program) {
  479.       if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) {
  480.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
  481.          return;
  482.       }
  483.       dest = ctx->VertexProgram.Parameters[index];
  484.    }
  485.    else {
  486.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
  487.       return;
  488.    }
  489.  
  490.    memcpy(dest, params, count * 4 * sizeof(GLfloat));
  491. }
  492.  
  493.  
  494. void GLAPIENTRY
  495. _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
  496.                                   GLdouble *params)
  497. {
  498.    GET_CURRENT_CONTEXT(ctx);
  499.    GLfloat fparams[4];
  500.  
  501.    _mesa_GetProgramEnvParameterfvARB(target, index, fparams);
  502.    if (ctx->ErrorValue == GL_NO_ERROR) {
  503.       params[0] = fparams[0];
  504.       params[1] = fparams[1];
  505.       params[2] = fparams[2];
  506.       params[3] = fparams[3];
  507.    }
  508. }
  509.  
  510.  
  511. void GLAPIENTRY
  512. _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
  513.                                   GLfloat *params)
  514. {
  515.    GET_CURRENT_CONTEXT(ctx);
  516.  
  517.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  518.  
  519.    if (target == GL_FRAGMENT_PROGRAM_ARB
  520.        && ctx->Extensions.ARB_fragment_program) {
  521.       if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
  522.          _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
  523.          return;
  524.       }
  525.       COPY_4V(params, ctx->FragmentProgram.Parameters[index]);
  526.    }
  527.    else if (target == GL_VERTEX_PROGRAM_ARB
  528.        && ctx->Extensions.ARB_vertex_program) {
  529.       if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
  530.          _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
  531.          return;
  532.       }
  533.       COPY_4V(params, ctx->VertexProgram.Parameters[index]);
  534.    }
  535.    else {
  536.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramEnvParameter(target)");
  537.       return;
  538.    }
  539. }
  540.  
  541.  
  542. /**
  543.  * Note, this function is also used by the GL_NV_fragment_program extension.
  544.  */
  545. void GLAPIENTRY
  546. _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
  547.                                  GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  548. {
  549.    GET_CURRENT_CONTEXT(ctx);
  550.    struct gl_program *prog;
  551.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  552.  
  553.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  554.  
  555.    if ((target == GL_FRAGMENT_PROGRAM_NV
  556.         && ctx->Extensions.NV_fragment_program) ||
  557.        (target == GL_FRAGMENT_PROGRAM_ARB
  558.         && ctx->Extensions.ARB_fragment_program)) {
  559.       if (index >= ctx->Const.FragmentProgram.MaxLocalParams) {
  560.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
  561.          return;
  562.       }
  563.       prog = &(ctx->FragmentProgram.Current->Base);
  564.    }
  565.    else if (target == GL_VERTEX_PROGRAM_ARB
  566.             && ctx->Extensions.ARB_vertex_program) {
  567.       if (index >= ctx->Const.VertexProgram.MaxLocalParams) {
  568.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
  569.          return;
  570.       }
  571.       prog = &(ctx->VertexProgram.Current->Base);
  572.    }
  573.    else {
  574.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
  575.       return;
  576.    }
  577.  
  578.    ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
  579.    prog->LocalParams[index][0] = x;
  580.    prog->LocalParams[index][1] = y;
  581.    prog->LocalParams[index][2] = z;
  582.    prog->LocalParams[index][3] = w;
  583. }
  584.  
  585.  
  586. /**
  587.  * Note, this function is also used by the GL_NV_fragment_program extension.
  588.  */
  589. void GLAPIENTRY
  590. _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
  591.                                   const GLfloat *params)
  592. {
  593.    _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
  594.                                     params[2], params[3]);
  595. }
  596.  
  597.  
  598. void GLAPIENTRY
  599. _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
  600.                                    const GLfloat *params)
  601. {
  602.    GET_CURRENT_CONTEXT(ctx);
  603.    GLfloat *dest;
  604.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  605.  
  606.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  607.  
  608.    if (count <= 0) {
  609.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
  610.    }
  611.  
  612.    if (target == GL_FRAGMENT_PROGRAM_ARB
  613.        && ctx->Extensions.ARB_fragment_program) {
  614.       if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) {
  615.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
  616.          return;
  617.       }
  618.       dest = ctx->FragmentProgram.Current->Base.LocalParams[index];
  619.    }
  620.    else if (target == GL_VERTEX_PROGRAM_ARB
  621.             && ctx->Extensions.ARB_vertex_program) {
  622.       if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) {
  623.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
  624.          return;
  625.       }
  626.       dest = ctx->VertexProgram.Current->Base.LocalParams[index];
  627.    }
  628.    else {
  629.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)");
  630.       return;
  631.    }
  632.  
  633.    memcpy(dest, params, count * 4 * sizeof(GLfloat));
  634. }
  635.  
  636.  
  637. /**
  638.  * Note, this function is also used by the GL_NV_fragment_program extension.
  639.  */
  640. void GLAPIENTRY
  641. _mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
  642.                                  GLdouble x, GLdouble y,
  643.                                  GLdouble z, GLdouble w)
  644. {
  645.    _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
  646.                                     (GLfloat) z, (GLfloat) w);
  647. }
  648.  
  649.  
  650. /**
  651.  * Note, this function is also used by the GL_NV_fragment_program extension.
  652.  */
  653. void GLAPIENTRY
  654. _mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
  655.                                   const GLdouble *params)
  656. {
  657.    _mesa_ProgramLocalParameter4fARB(target, index,
  658.                                     (GLfloat) params[0], (GLfloat) params[1],
  659.                                     (GLfloat) params[2], (GLfloat) params[3]);
  660. }
  661.  
  662.  
  663. /**
  664.  * Note, this function is also used by the GL_NV_fragment_program extension.
  665.  */
  666. void GLAPIENTRY
  667. _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
  668.                                     GLfloat *params)
  669. {
  670.    const struct gl_program *prog;
  671.    GLuint maxParams;
  672.    GET_CURRENT_CONTEXT(ctx);
  673.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  674.  
  675.    if (target == GL_VERTEX_PROGRAM_ARB
  676.        && ctx->Extensions.ARB_vertex_program) {
  677.       prog = &(ctx->VertexProgram.Current->Base);
  678.       maxParams = ctx->Const.VertexProgram.MaxLocalParams;
  679.    }
  680.    else if (target == GL_FRAGMENT_PROGRAM_ARB
  681.             && ctx->Extensions.ARB_fragment_program) {
  682.       prog = &(ctx->FragmentProgram.Current->Base);
  683.       maxParams = ctx->Const.FragmentProgram.MaxLocalParams;
  684.    }
  685.    else if (target == GL_FRAGMENT_PROGRAM_NV
  686.             && ctx->Extensions.NV_fragment_program) {
  687.       prog = &(ctx->FragmentProgram.Current->Base);
  688.       maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
  689.    }
  690.    else {
  691.       _mesa_error(ctx, GL_INVALID_ENUM,
  692.                   "glGetProgramLocalParameterARB(target)");
  693.       return;
  694.    }
  695.  
  696.    if (index >= maxParams) {
  697.       _mesa_error(ctx, GL_INVALID_VALUE,
  698.                   "glGetProgramLocalParameterARB(index)");
  699.       return;
  700.    }
  701.  
  702.    ASSERT(prog);
  703.    ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
  704.    COPY_4V(params, prog->LocalParams[index]);
  705. }
  706.  
  707.  
  708. /**
  709.  * Note, this function is also used by the GL_NV_fragment_program extension.
  710.  */
  711. void GLAPIENTRY
  712. _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
  713.                                     GLdouble *params)
  714. {
  715.    GET_CURRENT_CONTEXT(ctx);
  716.    GLfloat floatParams[4];
  717.    ASSIGN_4V(floatParams, 0.0F, 0.0F, 0.0F, 0.0F);
  718.    _mesa_GetProgramLocalParameterfvARB(target, index, floatParams);
  719.    if (ctx->ErrorValue == GL_NO_ERROR) {
  720.       COPY_4V(params, floatParams);
  721.    }
  722. }
  723.  
  724.  
  725. void GLAPIENTRY
  726. _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
  727. {
  728.    const struct gl_program_constants *limits;
  729.    struct gl_program *prog;
  730.    GET_CURRENT_CONTEXT(ctx);
  731.  
  732.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  733.  
  734.    if (target == GL_VERTEX_PROGRAM_ARB
  735.        && ctx->Extensions.ARB_vertex_program) {
  736.       prog = &(ctx->VertexProgram.Current->Base);
  737.       limits = &ctx->Const.VertexProgram;
  738.    }
  739.    else if (target == GL_FRAGMENT_PROGRAM_ARB
  740.             && ctx->Extensions.ARB_fragment_program) {
  741.       prog = &(ctx->FragmentProgram.Current->Base);
  742.       limits = &ctx->Const.FragmentProgram;
  743.    }
  744.    else {
  745.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
  746.       return;
  747.    }
  748.  
  749.    ASSERT(prog);
  750.    ASSERT(limits);
  751.  
  752.    /* Queries supported for both vertex and fragment programs */
  753.    switch (pname) {
  754.       case GL_PROGRAM_LENGTH_ARB:
  755.          *params
  756.             = prog->String ? (GLint) strlen((char *) prog->String) : 0;
  757.          return;
  758.       case GL_PROGRAM_FORMAT_ARB:
  759.          *params = prog->Format;
  760.          return;
  761.       case GL_PROGRAM_BINDING_ARB:
  762.          *params = prog->Id;
  763.          return;
  764.       case GL_PROGRAM_INSTRUCTIONS_ARB:
  765.          *params = prog->NumInstructions;
  766.          return;
  767.       case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
  768.          *params = limits->MaxInstructions;
  769.          return;
  770.       case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
  771.          *params = prog->NumNativeInstructions;
  772.          return;
  773.       case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
  774.          *params = limits->MaxNativeInstructions;
  775.          return;
  776.       case GL_PROGRAM_TEMPORARIES_ARB:
  777.          *params = prog->NumTemporaries;
  778.          return;
  779.       case GL_MAX_PROGRAM_TEMPORARIES_ARB:
  780.          *params = limits->MaxTemps;
  781.          return;
  782.       case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
  783.          *params = prog->NumNativeTemporaries;
  784.          return;
  785.       case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
  786.          *params = limits->MaxNativeTemps;
  787.          return;
  788.       case GL_PROGRAM_PARAMETERS_ARB:
  789.          *params = prog->NumParameters;
  790.          return;
  791.       case GL_MAX_PROGRAM_PARAMETERS_ARB:
  792.          *params = limits->MaxParameters;
  793.          return;
  794.       case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
  795.          *params = prog->NumNativeParameters;
  796.          return;
  797.       case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
  798.          *params = limits->MaxNativeParameters;
  799.          return;
  800.       case GL_PROGRAM_ATTRIBS_ARB:
  801.          *params = prog->NumAttributes;
  802.          return;
  803.       case GL_MAX_PROGRAM_ATTRIBS_ARB:
  804.          *params = limits->MaxAttribs;
  805.          return;
  806.       case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
  807.          *params = prog->NumNativeAttributes;
  808.          return;
  809.       case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
  810.          *params = limits->MaxNativeAttribs;
  811.          return;
  812.       case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
  813.          *params = prog->NumAddressRegs;
  814.          return;
  815.       case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
  816.          *params = limits->MaxAddressRegs;
  817.          return;
  818.       case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
  819.          *params = prog->NumNativeAddressRegs;
  820.          return;
  821.       case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
  822.          *params = limits->MaxNativeAddressRegs;
  823.          return;
  824.       case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
  825.          *params = limits->MaxLocalParams;
  826.          return;
  827.       case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
  828.          *params = limits->MaxEnvParams;
  829.          return;
  830.       case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
  831.          /*
  832.           * XXX we may not really need a driver callback here.
  833.           * If the number of native instructions, registers, etc. used
  834.           * are all below the maximums, we could return true.
  835.           * The spec says that even if this query returns true, there's
  836.           * no guarantee that the program will run in hardware.
  837.           */
  838.          if (prog->Id == 0) {
  839.             /* default/null program */
  840.             *params = GL_FALSE;
  841.          }
  842.          else if (ctx->Driver.IsProgramNative) {
  843.             /* ask the driver */
  844.             *params = ctx->Driver.IsProgramNative( ctx, target, prog );
  845.          }
  846.          else {
  847.             /* probably running in software */
  848.             *params = GL_TRUE;
  849.          }
  850.          return;
  851.       default:
  852.          /* continue with fragment-program only queries below */
  853.          break;
  854.    }
  855.  
  856.    /*
  857.     * The following apply to fragment programs only (at this time)
  858.     */
  859.    if (target == GL_FRAGMENT_PROGRAM_ARB) {
  860.       const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
  861.       switch (pname) {
  862.          case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
  863.             *params = fp->Base.NumNativeAluInstructions;
  864.             return;
  865.          case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
  866.             *params = fp->Base.NumAluInstructions;
  867.             return;
  868.          case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
  869.             *params = fp->Base.NumTexInstructions;
  870.             return;
  871.          case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
  872.             *params = fp->Base.NumNativeTexInstructions;
  873.             return;
  874.          case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
  875.             *params = fp->Base.NumTexIndirections;
  876.             return;
  877.          case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
  878.             *params = fp->Base.NumNativeTexIndirections;
  879.             return;
  880.          case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
  881.             *params = limits->MaxAluInstructions;
  882.             return;
  883.          case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
  884.             *params = limits->MaxNativeAluInstructions;
  885.             return;
  886.          case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
  887.             *params = limits->MaxTexInstructions;
  888.             return;
  889.          case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
  890.             *params = limits->MaxNativeTexInstructions;
  891.             return;
  892.          case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
  893.             *params = limits->MaxTexIndirections;
  894.             return;
  895.          case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
  896.             *params = limits->MaxNativeTexIndirections;
  897.             return;
  898.          default:
  899.             _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
  900.             return;
  901.       }
  902.    } else {
  903.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
  904.       return;
  905.    }
  906. }
  907.  
  908.  
  909. void GLAPIENTRY
  910. _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
  911. {
  912.    const struct gl_program *prog;
  913.    char *dst = (char *) string;
  914.    GET_CURRENT_CONTEXT(ctx);
  915.  
  916.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  917.  
  918.    if (target == GL_VERTEX_PROGRAM_ARB) {
  919.       prog = &(ctx->VertexProgram.Current->Base);
  920.    }
  921.    else if (target == GL_FRAGMENT_PROGRAM_ARB) {
  922.       prog = &(ctx->FragmentProgram.Current->Base);
  923.    }
  924.    else {
  925.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
  926.       return;
  927.    }
  928.  
  929.    ASSERT(prog);
  930.  
  931.    if (pname != GL_PROGRAM_STRING_ARB) {
  932.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
  933.       return;
  934.    }
  935.  
  936.    if (prog->String)
  937.       memcpy(dst, prog->String, strlen((char *) prog->String));
  938.    else
  939.       *dst = '\0';
  940. }
  941.