Subversion Repositories Kolibri OS

Rev

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