Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2007  Brian Paul   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.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * 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/program.h"
  41. #include "program/prog_print.h"
  42.  
  43.  
  44. /**
  45.  * Bind a program (make it current)
  46.  * \note Called from the GL API dispatcher by both glBindProgramNV
  47.  * and glBindProgramARB.
  48.  */
  49. void GLAPIENTRY
  50. _mesa_BindProgramARB(GLenum target, GLuint id)
  51. {
  52.    struct gl_program *curProg, *newProg;
  53.    GET_CURRENT_CONTEXT(ctx);
  54.  
  55.    /* Error-check target and get curProg */
  56.    if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
  57.       curProg = &ctx->VertexProgram.Current->Base;
  58.    }
  59.    else if (target == GL_FRAGMENT_PROGRAM_ARB
  60.             && ctx->Extensions.ARB_fragment_program) {
  61.       curProg = &ctx->FragmentProgram.Current->Base;
  62.    }
  63.    else {
  64.       _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramARB(target)");
  65.       return;
  66.    }
  67.  
  68.    /*
  69.     * Get pointer to new program to bind.
  70.     * NOTE: binding to a non-existant program is not an error.
  71.     * That's supposed to be caught in glBegin.
  72.     */
  73.    if (id == 0) {
  74.       /* Bind a default program */
  75.       newProg = NULL;
  76.       if (target == GL_VERTEX_PROGRAM_ARB)
  77.          newProg = &ctx->Shared->DefaultVertexProgram->Base;
  78.       else
  79.          newProg = &ctx->Shared->DefaultFragmentProgram->Base;
  80.    }
  81.    else {
  82.       /* Bind a user program */
  83.       newProg = _mesa_lookup_program(ctx, id);
  84.       if (!newProg || newProg == &_mesa_DummyProgram) {
  85.          /* allocate a new program now */
  86.          newProg = ctx->Driver.NewProgram(ctx, target, id);
  87.          if (!newProg) {
  88.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramARB");
  89.             return;
  90.          }
  91.          _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
  92.       }
  93.       else if (newProg->Target != target) {
  94.          _mesa_error(ctx, GL_INVALID_OPERATION,
  95.                      "glBindProgramARB(target mismatch)");
  96.          return;
  97.       }
  98.    }
  99.  
  100.    /** All error checking is complete now **/
  101.  
  102.    if (curProg->Id == id) {
  103.       /* binding same program - no change */
  104.       return;
  105.    }
  106.  
  107.    /* signal new program (and its new constants) */
  108.    FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
  109.  
  110.    /* bind newProg */
  111.    if (target == GL_VERTEX_PROGRAM_ARB) {
  112.       _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
  113.                                gl_vertex_program(newProg));
  114.    }
  115.    else if (target == GL_FRAGMENT_PROGRAM_ARB) {
  116.       _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
  117.                                gl_fragment_program(newProg));
  118.    }
  119.  
  120.    /* Never null pointers */
  121.    assert(ctx->VertexProgram.Current);
  122.    assert(ctx->FragmentProgram.Current);
  123.  
  124.    if (ctx->Driver.BindProgram)
  125.       ctx->Driver.BindProgram(ctx, target, newProg);
  126. }
  127.  
  128.  
  129. /**
  130.  * Delete a list of programs.
  131.  * \note Not compiled into display lists.
  132.  * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
  133.  */
  134. void GLAPIENTRY
  135. _mesa_DeleteProgramsARB(GLsizei n, const GLuint *ids)
  136. {
  137.    GLint i;
  138.    GET_CURRENT_CONTEXT(ctx);
  139.  
  140.    FLUSH_VERTICES(ctx, 0);
  141.  
  142.    if (n < 0) {
  143.       _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
  144.       return;
  145.    }
  146.  
  147.    for (i = 0; i < n; i++) {
  148.       if (ids[i] != 0) {
  149.          struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
  150.          if (prog == &_mesa_DummyProgram) {
  151.             _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
  152.          }
  153.          else if (prog) {
  154.             /* Unbind program if necessary */
  155.             switch (prog->Target) {
  156.             case GL_VERTEX_PROGRAM_ARB:
  157.                if (ctx->VertexProgram.Current &&
  158.                    ctx->VertexProgram.Current->Base.Id == ids[i]) {
  159.                   /* unbind this currently bound program */
  160.                   _mesa_BindProgramARB(prog->Target, 0);
  161.                }
  162.                break;
  163.             case GL_FRAGMENT_PROGRAM_ARB:
  164.                if (ctx->FragmentProgram.Current &&
  165.                    ctx->FragmentProgram.Current->Base.Id == ids[i]) {
  166.                   /* unbind this currently bound program */
  167.                   _mesa_BindProgramARB(prog->Target, 0);
  168.                }
  169.                break;
  170.             default:
  171.                _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
  172.                return;
  173.             }
  174.             /* The ID is immediately available for re-use now */
  175.             _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
  176.             _mesa_reference_program(ctx, &prog, NULL);
  177.          }
  178.       }
  179.    }
  180. }
  181.  
  182.  
  183. /**
  184.  * Generate a list of new program identifiers.
  185.  * \note Not compiled into display lists.
  186.  * \note Called by both glGenProgramsNV and glGenProgramsARB.
  187.  */
  188. void GLAPIENTRY
  189. _mesa_GenProgramsARB(GLsizei n, GLuint *ids)
  190. {
  191.    GLuint first;
  192.    GLuint i;
  193.    GET_CURRENT_CONTEXT(ctx);
  194.  
  195.    if (n < 0) {
  196.       _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
  197.       return;
  198.    }
  199.  
  200.    if (!ids)
  201.       return;
  202.  
  203.    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
  204.  
  205.    /* Insert pointer to dummy program as placeholder */
  206.    for (i = 0; i < (GLuint) n; i++) {
  207.       _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
  208.    }
  209.  
  210.    /* Return the program names */
  211.    for (i = 0; i < (GLuint) n; i++) {
  212.       ids[i] = first + i;
  213.    }
  214. }
  215.  
  216.  
  217. /**
  218.  * Determine if id names a vertex or fragment program.
  219.  * \note Not compiled into display lists.
  220.  * \note Called from both glIsProgramNV and glIsProgramARB.
  221.  * \param id is the program identifier
  222.  * \return GL_TRUE if id is a program, else GL_FALSE.
  223.  */
  224. GLboolean GLAPIENTRY
  225. _mesa_IsProgramARB(GLuint id)
  226. {
  227.    struct gl_program *prog = NULL;
  228.    GET_CURRENT_CONTEXT(ctx);
  229.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  230.  
  231.    if (id == 0)
  232.       return GL_FALSE;
  233.  
  234.    prog = _mesa_lookup_program(ctx, id);
  235.    if (prog && (prog != &_mesa_DummyProgram))
  236.       return GL_TRUE;
  237.    else
  238.       return GL_FALSE;
  239. }
  240.  
  241. static GLboolean
  242. get_local_param_pointer(struct gl_context *ctx, const char *func,
  243.                         GLenum target, GLuint index, GLfloat **param)
  244. {
  245.    struct gl_program *prog;
  246.    GLuint maxParams;
  247.  
  248.    if (target == GL_VERTEX_PROGRAM_ARB
  249.        && ctx->Extensions.ARB_vertex_program) {
  250.       prog = &(ctx->VertexProgram.Current->Base);
  251.       maxParams = ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams;
  252.    }
  253.    else if (target == GL_FRAGMENT_PROGRAM_ARB
  254.             && ctx->Extensions.ARB_fragment_program) {
  255.       prog = &(ctx->FragmentProgram.Current->Base);
  256.       maxParams = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams;
  257.    }
  258.    else {
  259.       _mesa_error(ctx, GL_INVALID_ENUM,
  260.                   "%s(target)", func);
  261.       return GL_FALSE;
  262.    }
  263.  
  264.    if (index >= maxParams) {
  265.       _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
  266.       return GL_FALSE;
  267.    }
  268.  
  269.    if (!prog->LocalParams) {
  270.       prog->LocalParams = calloc(maxParams, sizeof(float[4]));
  271.       if (!prog->LocalParams)
  272.          return GL_FALSE;
  273.    }
  274.  
  275.    *param = prog->LocalParams[index];
  276.    return GL_TRUE;
  277. }
  278.  
  279.  
  280. static GLboolean
  281. get_env_param_pointer(struct gl_context *ctx, const char *func,
  282.                       GLenum target, GLuint index, GLfloat **param)
  283. {
  284.    if (target == GL_FRAGMENT_PROGRAM_ARB
  285.        && ctx->Extensions.ARB_fragment_program) {
  286.       if (index >= ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
  287.          _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
  288.          return GL_FALSE;
  289.       }
  290.       *param = ctx->FragmentProgram.Parameters[index];
  291.       return GL_TRUE;
  292.    }
  293.    else if (target == GL_VERTEX_PROGRAM_ARB &&
  294.             ctx->Extensions.ARB_vertex_program) {
  295.       if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
  296.          _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
  297.          return GL_FALSE;
  298.       }
  299.       *param = ctx->VertexProgram.Parameters[index];
  300.       return GL_TRUE;
  301.    } else {
  302.       _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
  303.       return GL_FALSE;
  304.    }
  305. }
  306.  
  307. void GLAPIENTRY
  308. _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
  309.                        const GLvoid *string)
  310. {
  311.    struct gl_program *base;
  312.    bool failed;
  313.    GET_CURRENT_CONTEXT(ctx);
  314.  
  315.    FLUSH_VERTICES(ctx, _NEW_PROGRAM);
  316.  
  317.    if (!ctx->Extensions.ARB_vertex_program
  318.        && !ctx->Extensions.ARB_fragment_program) {
  319.       _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()");
  320.       return;
  321.    }
  322.  
  323.    if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
  324.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
  325.       return;
  326.    }
  327.  
  328.    if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
  329.       struct gl_vertex_program *prog = ctx->VertexProgram.Current;
  330.       _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
  331.  
  332.       base = & prog->Base;
  333.    }
  334.    else if (target == GL_FRAGMENT_PROGRAM_ARB
  335.             && ctx->Extensions.ARB_fragment_program) {
  336.       struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
  337.       _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
  338.  
  339.       base = & prog->Base;
  340.    }
  341.    else {
  342.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
  343.       return;
  344.    }
  345.  
  346.    failed = ctx->Program.ErrorPos != -1;
  347.  
  348.    if (!failed) {
  349.       /* finally, give the program to the driver for translation/checking */
  350.       if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) {
  351.          failed = true;
  352.          _mesa_error(ctx, GL_INVALID_OPERATION,
  353.                      "glProgramStringARB(rejected by driver");
  354.       }
  355.    }
  356.  
  357.    if (ctx->_Shader->Flags & GLSL_DUMP) {
  358.       const char *shader_type =
  359.          target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
  360.  
  361.       fprintf(stderr, "ARB_%s_program source for program %d:\n",
  362.               shader_type, base->Id);
  363.       fprintf(stderr, "%s\n", (const char *) string);
  364.  
  365.       if (failed) {
  366.          fprintf(stderr, "ARB_%s_program %d failed to compile.\n",
  367.                  shader_type, base->Id);
  368.       } else {
  369.          fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n",
  370.                  shader_type, base->Id);
  371.          _mesa_print_program(base);
  372.          fprintf(stderr, "\n");
  373.       }
  374.       fflush(stderr);
  375.    }
  376. }
  377.  
  378.  
  379. /**
  380.  * Set a program env parameter register.
  381.  * \note Called from the GL API dispatcher.
  382.  */
  383. void GLAPIENTRY
  384. _mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
  385.                                GLdouble x, GLdouble y, GLdouble z, GLdouble w)
  386. {
  387.    _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
  388.                                   (GLfloat) z, (GLfloat) w);
  389. }
  390.  
  391.  
  392. /**
  393.  * Set a program env parameter register.
  394.  * \note Called from the GL API dispatcher.
  395.  */
  396. void GLAPIENTRY
  397. _mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
  398.                                 const GLdouble *params)
  399. {
  400.    _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
  401.                                   (GLfloat) params[1], (GLfloat) params[2],
  402.                                   (GLfloat) params[3]);
  403. }
  404.  
  405.  
  406. /**
  407.  * Set a program env parameter register.
  408.  * \note Called from the GL API dispatcher.
  409.  */
  410. void GLAPIENTRY
  411. _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
  412.                                GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  413. {
  414.    GLfloat *param;
  415.  
  416.    GET_CURRENT_CONTEXT(ctx);
  417.  
  418.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  419.  
  420.    if (get_env_param_pointer(ctx, "glProgramEnvParameter",
  421.                              target, index, &param)) {
  422.       ASSIGN_4V(param, x, y, z, w);
  423.    }
  424. }
  425.  
  426.  
  427.  
  428. /**
  429.  * Set a program env parameter register.
  430.  * \note Called from the GL API dispatcher.
  431.  */
  432. void GLAPIENTRY
  433. _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
  434.                                 const GLfloat *params)
  435. {
  436.    GLfloat *param;
  437.  
  438.    GET_CURRENT_CONTEXT(ctx);
  439.  
  440.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  441.  
  442.    if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv",
  443.                               target, index, &param)) {
  444.       memcpy(param, params, 4 * sizeof(GLfloat));
  445.    }
  446. }
  447.  
  448.  
  449. void GLAPIENTRY
  450. _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
  451.                                  const GLfloat *params)
  452. {
  453.    GET_CURRENT_CONTEXT(ctx);
  454.    GLfloat * dest;
  455.  
  456.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  457.  
  458.    if (count <= 0) {
  459.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
  460.    }
  461.  
  462.    if (target == GL_FRAGMENT_PROGRAM_ARB
  463.        && ctx->Extensions.ARB_fragment_program) {
  464.       if ((index + count) > ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
  465.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
  466.          return;
  467.       }
  468.       dest = ctx->FragmentProgram.Parameters[index];
  469.    }
  470.    else if (target == GL_VERTEX_PROGRAM_ARB
  471.        && ctx->Extensions.ARB_vertex_program) {
  472.       if ((index + count) > ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
  473.          _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
  474.          return;
  475.       }
  476.       dest = ctx->VertexProgram.Parameters[index];
  477.    }
  478.    else {
  479.       _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
  480.       return;
  481.    }
  482.  
  483.    memcpy(dest, params, count * 4 * sizeof(GLfloat));
  484. }
  485.  
  486.  
  487. void GLAPIENTRY
  488. _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
  489.                                   GLdouble *params)
  490. {
  491.    GET_CURRENT_CONTEXT(ctx);
  492.    GLfloat *fparam;
  493.  
  494.    if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv",
  495.                              target, index, &fparam)) {
  496.       COPY_4V(params, fparam);
  497.    }
  498. }
  499.  
  500.  
  501. void GLAPIENTRY
  502. _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
  503.                                   GLfloat *params)
  504. {
  505.    GLfloat *param;
  506.  
  507.    GET_CURRENT_CONTEXT(ctx);
  508.  
  509.    if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv",
  510.                               target, index, &param)) {
  511.       COPY_4V(params, param);
  512.    }
  513. }
  514.  
  515.  
  516. void GLAPIENTRY
  517. _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
  518.                                  GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  519. {
  520.    GET_CURRENT_CONTEXT(ctx);
  521.    GLfloat *param;
  522.  
  523.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  524.  
  525.    if (get_local_param_pointer(ctx, "glProgramLocalParameterARB",
  526.                                target, index, &param)) {
  527.       assert(index < MAX_PROGRAM_LOCAL_PARAMS);
  528.       ASSIGN_4V(param, x, y, z, w);
  529.    }
  530. }
  531.  
  532.  
  533. void GLAPIENTRY
  534. _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
  535.                                   const GLfloat *params)
  536. {
  537.    _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
  538.                                     params[2], params[3]);
  539. }
  540.  
  541.  
  542. void GLAPIENTRY
  543. _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
  544.                                    const GLfloat *params)
  545. {
  546.    GET_CURRENT_CONTEXT(ctx);
  547.    GLfloat *dest;
  548.  
  549.    FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
  550.  
  551.    if (count <= 0) {
  552.       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
  553.    }
  554.  
  555.    if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
  556.                                target, index, &dest)) {
  557.       GLuint maxParams = target == GL_FRAGMENT_PROGRAM_ARB ?
  558.          ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams :
  559.          ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams;
  560.  
  561.       if ((index + count) > maxParams) {
  562.          _mesa_error(ctx, GL_INVALID_VALUE,
  563.                      "glProgramLocalParameters4fvEXT(index + count)");
  564.          return;
  565.       }
  566.  
  567.       memcpy(dest, params, count * 4 * sizeof(GLfloat));
  568.    }
  569. }
  570.  
  571.  
  572. void GLAPIENTRY
  573. _mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
  574.                                  GLdouble x, GLdouble y,
  575.                                  GLdouble z, GLdouble w)
  576. {
  577.    _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
  578.                                     (GLfloat) z, (GLfloat) w);
  579. }
  580.  
  581.  
  582. void GLAPIENTRY
  583. _mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
  584.                                   const GLdouble *params)
  585. {
  586.    _mesa_ProgramLocalParameter4fARB(target, index,
  587.                                     (GLfloat) params[0], (GLfloat) params[1],
  588.                                     (GLfloat) params[2], (GLfloat) params[3]);
  589. }
  590.  
  591.  
  592. void GLAPIENTRY
  593. _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
  594.                                     GLfloat *params)
  595. {
  596.    GLfloat *param;
  597.    GET_CURRENT_CONTEXT(ctx);
  598.  
  599.    if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
  600.                                 target, index, &param)) {
  601.       COPY_4V(params, param);
  602.    }
  603. }
  604.  
  605.  
  606. void GLAPIENTRY
  607. _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
  608.                                     GLdouble *params)
  609. {
  610.    GLfloat *param;
  611.    GET_CURRENT_CONTEXT(ctx);
  612.  
  613.    if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
  614.                                 target, index, &param)) {
  615.       COPY_4V(params, param);
  616.    }
  617. }
  618.  
  619.  
  620. void GLAPIENTRY
  621. _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
  622. {
  623.    const struct gl_program_constants *limits;
  624.    struct gl_program *prog;
  625.    GET_CURRENT_CONTEXT(ctx);
  626.  
  627.    if (target == GL_VERTEX_PROGRAM_ARB
  628.        && ctx->Extensions.ARB_vertex_program) {
  629.       prog = &(ctx->VertexProgram.Current->Base);
  630.       limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
  631.    }
  632.    else if (target == GL_FRAGMENT_PROGRAM_ARB
  633.             && ctx->Extensions.ARB_fragment_program) {
  634.       prog = &(ctx->FragmentProgram.Current->Base);
  635.       limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
  636.    }
  637.    else {
  638.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
  639.       return;
  640.    }
  641.  
  642.    assert(prog);
  643.    assert(limits);
  644.  
  645.    /* Queries supported for both vertex and fragment programs */
  646.    switch (pname) {
  647.       case GL_PROGRAM_LENGTH_ARB:
  648.          *params
  649.             = prog->String ? (GLint) strlen((char *) prog->String) : 0;
  650.          return;
  651.       case GL_PROGRAM_FORMAT_ARB:
  652.          *params = prog->Format;
  653.          return;
  654.       case GL_PROGRAM_BINDING_ARB:
  655.          *params = prog->Id;
  656.          return;
  657.       case GL_PROGRAM_INSTRUCTIONS_ARB:
  658.          *params = prog->NumInstructions;
  659.          return;
  660.       case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
  661.          *params = limits->MaxInstructions;
  662.          return;
  663.       case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
  664.          *params = prog->NumNativeInstructions;
  665.          return;
  666.       case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
  667.          *params = limits->MaxNativeInstructions;
  668.          return;
  669.       case GL_PROGRAM_TEMPORARIES_ARB:
  670.          *params = prog->NumTemporaries;
  671.          return;
  672.       case GL_MAX_PROGRAM_TEMPORARIES_ARB:
  673.          *params = limits->MaxTemps;
  674.          return;
  675.       case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
  676.          *params = prog->NumNativeTemporaries;
  677.          return;
  678.       case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
  679.          *params = limits->MaxNativeTemps;
  680.          return;
  681.       case GL_PROGRAM_PARAMETERS_ARB:
  682.          *params = prog->NumParameters;
  683.          return;
  684.       case GL_MAX_PROGRAM_PARAMETERS_ARB:
  685.          *params = limits->MaxParameters;
  686.          return;
  687.       case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
  688.          *params = prog->NumNativeParameters;
  689.          return;
  690.       case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
  691.          *params = limits->MaxNativeParameters;
  692.          return;
  693.       case GL_PROGRAM_ATTRIBS_ARB:
  694.          *params = prog->NumAttributes;
  695.          return;
  696.       case GL_MAX_PROGRAM_ATTRIBS_ARB:
  697.          *params = limits->MaxAttribs;
  698.          return;
  699.       case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
  700.          *params = prog->NumNativeAttributes;
  701.          return;
  702.       case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
  703.          *params = limits->MaxNativeAttribs;
  704.          return;
  705.       case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
  706.          *params = prog->NumAddressRegs;
  707.          return;
  708.       case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
  709.          *params = limits->MaxAddressRegs;
  710.          return;
  711.       case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
  712.          *params = prog->NumNativeAddressRegs;
  713.          return;
  714.       case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
  715.          *params = limits->MaxNativeAddressRegs;
  716.          return;
  717.       case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
  718.          *params = limits->MaxLocalParams;
  719.          return;
  720.       case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
  721.          *params = limits->MaxEnvParams;
  722.          return;
  723.       case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
  724.          /*
  725.           * XXX we may not really need a driver callback here.
  726.           * If the number of native instructions, registers, etc. used
  727.           * are all below the maximums, we could return true.
  728.           * The spec says that even if this query returns true, there's
  729.           * no guarantee that the program will run in hardware.
  730.           */
  731.          if (prog->Id == 0) {
  732.             /* default/null program */
  733.             *params = GL_FALSE;
  734.          }
  735.          else if (ctx->Driver.IsProgramNative) {
  736.             /* ask the driver */
  737.             *params = ctx->Driver.IsProgramNative( ctx, target, prog );
  738.          }
  739.          else {
  740.             /* probably running in software */
  741.             *params = GL_TRUE;
  742.          }
  743.          return;
  744.       default:
  745.          /* continue with fragment-program only queries below */
  746.          break;
  747.    }
  748.  
  749.    /*
  750.     * The following apply to fragment programs only (at this time)
  751.     */
  752.    if (target == GL_FRAGMENT_PROGRAM_ARB) {
  753.       const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
  754.       switch (pname) {
  755.          case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
  756.             *params = fp->Base.NumNativeAluInstructions;
  757.             return;
  758.          case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
  759.             *params = fp->Base.NumAluInstructions;
  760.             return;
  761.          case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
  762.             *params = fp->Base.NumTexInstructions;
  763.             return;
  764.          case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
  765.             *params = fp->Base.NumNativeTexInstructions;
  766.             return;
  767.          case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
  768.             *params = fp->Base.NumTexIndirections;
  769.             return;
  770.          case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
  771.             *params = fp->Base.NumNativeTexIndirections;
  772.             return;
  773.          case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
  774.             *params = limits->MaxAluInstructions;
  775.             return;
  776.          case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
  777.             *params = limits->MaxNativeAluInstructions;
  778.             return;
  779.          case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
  780.             *params = limits->MaxTexInstructions;
  781.             return;
  782.          case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
  783.             *params = limits->MaxNativeTexInstructions;
  784.             return;
  785.          case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
  786.             *params = limits->MaxTexIndirections;
  787.             return;
  788.          case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
  789.             *params = limits->MaxNativeTexIndirections;
  790.             return;
  791.          default:
  792.             _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
  793.             return;
  794.       }
  795.    } else {
  796.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
  797.       return;
  798.    }
  799. }
  800.  
  801.  
  802. void GLAPIENTRY
  803. _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
  804. {
  805.    const struct gl_program *prog;
  806.    char *dst = (char *) string;
  807.    GET_CURRENT_CONTEXT(ctx);
  808.  
  809.    if (target == GL_VERTEX_PROGRAM_ARB) {
  810.       prog = &(ctx->VertexProgram.Current->Base);
  811.    }
  812.    else if (target == GL_FRAGMENT_PROGRAM_ARB) {
  813.       prog = &(ctx->FragmentProgram.Current->Base);
  814.    }
  815.    else {
  816.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
  817.       return;
  818.    }
  819.  
  820.    assert(prog);
  821.  
  822.    if (pname != GL_PROGRAM_STRING_ARB) {
  823.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
  824.       return;
  825.    }
  826.  
  827.    if (prog->String)
  828.       memcpy(dst, prog->String, strlen((char *) prog->String));
  829.    else
  830.       *dst = '\0';
  831. }
  832.