Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1.  
  2. /*
  3.  * Mesa 3-D graphics library
  4.  *
  5.  * Copyright (C) 1999-2003  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.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26.  
  27. /*
  28.  * eval.c was written by
  29.  * Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and
  30.  * Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de).
  31.  *
  32.  * My original implementation of evaluators was simplistic and didn't
  33.  * compute surface normal vectors properly.  Bernd and Volker applied
  34.  * used more sophisticated methods to get better results.
  35.  *
  36.  * Thanks guys!
  37.  */
  38.  
  39.  
  40. #include "glheader.h"
  41. #include "imports.h"
  42. #include "context.h"
  43. #include "eval.h"
  44. #include "macros.h"
  45. #include "mtypes.h"
  46. #include "main/dispatch.h"
  47.  
  48.  
  49. /*
  50.  * Return the number of components per control point for any type of
  51.  * evaluator.  Return 0 if bad target.
  52.  * See table 5.1 in the OpenGL 1.2 spec.
  53.  */
  54. GLuint _mesa_evaluator_components( GLenum target )
  55. {
  56.    switch (target) {
  57.       case GL_MAP1_VERTEX_3:            return 3;
  58.       case GL_MAP1_VERTEX_4:            return 4;
  59.       case GL_MAP1_INDEX:               return 1;
  60.       case GL_MAP1_COLOR_4:             return 4;
  61.       case GL_MAP1_NORMAL:              return 3;
  62.       case GL_MAP1_TEXTURE_COORD_1:     return 1;
  63.       case GL_MAP1_TEXTURE_COORD_2:     return 2;
  64.       case GL_MAP1_TEXTURE_COORD_3:     return 3;
  65.       case GL_MAP1_TEXTURE_COORD_4:     return 4;
  66.       case GL_MAP2_VERTEX_3:            return 3;
  67.       case GL_MAP2_VERTEX_4:            return 4;
  68.       case GL_MAP2_INDEX:               return 1;
  69.       case GL_MAP2_COLOR_4:             return 4;
  70.       case GL_MAP2_NORMAL:              return 3;
  71.       case GL_MAP2_TEXTURE_COORD_1:     return 1;
  72.       case GL_MAP2_TEXTURE_COORD_2:     return 2;
  73.       case GL_MAP2_TEXTURE_COORD_3:     return 3;
  74.       case GL_MAP2_TEXTURE_COORD_4:     return 4;
  75.       default:                          break;
  76.    }
  77.  
  78.    return 0;
  79. }
  80.  
  81.  
  82. /*
  83.  * Return pointer to the gl_1d_map struct for the named target.
  84.  */
  85. static struct gl_1d_map *
  86. get_1d_map( struct gl_context *ctx, GLenum target )
  87. {
  88.    switch (target) {
  89.       case GL_MAP1_VERTEX_3:
  90.          return &ctx->EvalMap.Map1Vertex3;
  91.       case GL_MAP1_VERTEX_4:
  92.          return &ctx->EvalMap.Map1Vertex4;
  93.       case GL_MAP1_INDEX:
  94.          return &ctx->EvalMap.Map1Index;
  95.       case GL_MAP1_COLOR_4:
  96.          return &ctx->EvalMap.Map1Color4;
  97.       case GL_MAP1_NORMAL:
  98.          return &ctx->EvalMap.Map1Normal;
  99.       case GL_MAP1_TEXTURE_COORD_1:
  100.          return &ctx->EvalMap.Map1Texture1;
  101.       case GL_MAP1_TEXTURE_COORD_2:
  102.          return &ctx->EvalMap.Map1Texture2;
  103.       case GL_MAP1_TEXTURE_COORD_3:
  104.          return &ctx->EvalMap.Map1Texture3;
  105.       case GL_MAP1_TEXTURE_COORD_4:
  106.          return &ctx->EvalMap.Map1Texture4;
  107.       default:
  108.          return NULL;
  109.    }
  110. }
  111.  
  112.  
  113. /*
  114.  * Return pointer to the gl_2d_map struct for the named target.
  115.  */
  116. static struct gl_2d_map *
  117. get_2d_map( struct gl_context *ctx, GLenum target )
  118. {
  119.    switch (target) {
  120.       case GL_MAP2_VERTEX_3:
  121.          return &ctx->EvalMap.Map2Vertex3;
  122.       case GL_MAP2_VERTEX_4:
  123.          return &ctx->EvalMap.Map2Vertex4;
  124.       case GL_MAP2_INDEX:
  125.          return &ctx->EvalMap.Map2Index;
  126.       case GL_MAP2_COLOR_4:
  127.          return &ctx->EvalMap.Map2Color4;
  128.       case GL_MAP2_NORMAL:
  129.          return &ctx->EvalMap.Map2Normal;
  130.       case GL_MAP2_TEXTURE_COORD_1:
  131.          return &ctx->EvalMap.Map2Texture1;
  132.       case GL_MAP2_TEXTURE_COORD_2:
  133.          return &ctx->EvalMap.Map2Texture2;
  134.       case GL_MAP2_TEXTURE_COORD_3:
  135.          return &ctx->EvalMap.Map2Texture3;
  136.       case GL_MAP2_TEXTURE_COORD_4:
  137.          return &ctx->EvalMap.Map2Texture4;
  138.       default:
  139.          return NULL;
  140.    }
  141. }
  142.  
  143.  
  144. /**********************************************************************/
  145. /***            Copy and deallocate control points                  ***/
  146. /**********************************************************************/
  147.  
  148.  
  149. /*
  150.  * Copy 1-parametric evaluator control points from user-specified
  151.  * memory space to a buffer of contiguous control points.
  152.  * \param see glMap1f for details
  153.  * \return pointer to buffer of contiguous control points or NULL if out
  154.  *          of memory.
  155.  */
  156. GLfloat *_mesa_copy_map_points1f( GLenum target, GLint ustride, GLint uorder,
  157.                                   const GLfloat *points )
  158. {
  159.    GLfloat *buffer, *p;
  160.    GLint i, k, size = _mesa_evaluator_components(target);
  161.  
  162.    if (!points || !size)
  163.       return NULL;
  164.  
  165.    buffer = malloc(uorder * size * sizeof(GLfloat));
  166.  
  167.    if (buffer)
  168.       for (i = 0, p = buffer; i < uorder; i++, points += ustride)
  169.         for (k = 0; k < size; k++)
  170.           *p++ = points[k];
  171.  
  172.    return buffer;
  173. }
  174.  
  175.  
  176.  
  177. /*
  178.  * Same as above but convert doubles to floats.
  179.  */
  180. GLfloat *_mesa_copy_map_points1d( GLenum target, GLint ustride, GLint uorder,
  181.                                   const GLdouble *points )
  182. {
  183.    GLfloat *buffer, *p;
  184.    GLint i, k, size = _mesa_evaluator_components(target);
  185.  
  186.    if (!points || !size)
  187.       return NULL;
  188.  
  189.    buffer = malloc(uorder * size * sizeof(GLfloat));
  190.  
  191.    if (buffer)
  192.       for (i = 0, p = buffer; i < uorder; i++, points += ustride)
  193.         for (k = 0; k < size; k++)
  194.           *p++ = (GLfloat) points[k];
  195.  
  196.    return buffer;
  197. }
  198.  
  199.  
  200.  
  201. /*
  202.  * Copy 2-parametric evaluator control points from user-specified
  203.  * memory space to a buffer of contiguous control points.
  204.  * Additional memory is allocated to be used by the horner and
  205.  * de Casteljau evaluation schemes.
  206.  *
  207.  * \param see glMap2f for details
  208.  * \return pointer to buffer of contiguous control points or NULL if out
  209.  *          of memory.
  210.  */
  211. GLfloat *_mesa_copy_map_points2f( GLenum target,
  212.                                   GLint ustride, GLint uorder,
  213.                                   GLint vstride, GLint vorder,
  214.                                   const GLfloat *points )
  215. {
  216.    GLfloat *buffer, *p;
  217.    GLint i, j, k, size, dsize, hsize;
  218.    GLint uinc;
  219.  
  220.    size = _mesa_evaluator_components(target);
  221.  
  222.    if (!points || size==0) {
  223.       return NULL;
  224.    }
  225.  
  226.    /* max(uorder, vorder) additional points are used in      */
  227.    /* horner evaluation and uorder*vorder additional */
  228.    /* values are needed for de Casteljau                     */
  229.    dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
  230.    hsize = (uorder > vorder ? uorder : vorder)*size;
  231.  
  232.    if(hsize>dsize)
  233.      buffer = malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
  234.    else
  235.      buffer = malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
  236.  
  237.    /* compute the increment value for the u-loop */
  238.    uinc = ustride - vorder*vstride;
  239.  
  240.    if (buffer)
  241.       for (i=0, p=buffer; i<uorder; i++, points += uinc)
  242.          for (j=0; j<vorder; j++, points += vstride)
  243.             for (k=0; k<size; k++)
  244.                *p++ = points[k];
  245.  
  246.    return buffer;
  247. }
  248.  
  249.  
  250.  
  251. /*
  252.  * Same as above but convert doubles to floats.
  253.  */
  254. GLfloat *_mesa_copy_map_points2d(GLenum target,
  255.                                  GLint ustride, GLint uorder,
  256.                                  GLint vstride, GLint vorder,
  257.                                  const GLdouble *points )
  258. {
  259.    GLfloat *buffer, *p;
  260.    GLint i, j, k, size, hsize, dsize;
  261.    GLint uinc;
  262.  
  263.    size = _mesa_evaluator_components(target);
  264.  
  265.    if (!points || size==0) {
  266.       return NULL;
  267.    }
  268.  
  269.    /* max(uorder, vorder) additional points are used in      */
  270.    /* horner evaluation and uorder*vorder additional */
  271.    /* values are needed for de Casteljau                     */
  272.    dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
  273.    hsize = (uorder > vorder ? uorder : vorder)*size;
  274.  
  275.    if(hsize>dsize)
  276.      buffer = malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
  277.    else
  278.      buffer = malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
  279.  
  280.    /* compute the increment value for the u-loop */
  281.    uinc = ustride - vorder*vstride;
  282.  
  283.    if (buffer)
  284.       for (i=0, p=buffer; i<uorder; i++, points += uinc)
  285.          for (j=0; j<vorder; j++, points += vstride)
  286.             for (k=0; k<size; k++)
  287.                *p++ = (GLfloat) points[k];
  288.  
  289.    return buffer;
  290. }
  291.  
  292.  
  293.  
  294.  
  295. /**********************************************************************/
  296. /***                      API entry points                          ***/
  297. /**********************************************************************/
  298.  
  299.  
  300. /*
  301.  * This does the work of glMap1[fd].
  302.  */
  303. static void
  304. map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
  305.      GLint uorder, const GLvoid *points, GLenum type )
  306. {
  307.    GET_CURRENT_CONTEXT(ctx);
  308.    GLint k;
  309.    GLfloat *pnts;
  310.    struct gl_1d_map *map = NULL;
  311.  
  312.    assert(type == GL_FLOAT || type == GL_DOUBLE);
  313.  
  314.    if (u1 == u2) {
  315.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
  316.       return;
  317.    }
  318.    if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
  319.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
  320.       return;
  321.    }
  322.    if (!points) {
  323.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(points)" );
  324.       return;
  325.    }
  326.  
  327.    k = _mesa_evaluator_components( target );
  328.    if (k == 0) {
  329.       _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
  330.       return;
  331.    }
  332.  
  333.    if (ustride < k) {
  334.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
  335.       return;
  336.    }
  337.  
  338.    if (ctx->Texture.CurrentUnit != 0) {
  339.       /* See OpenGL 1.2.1 spec, section F.2.13 */
  340.       _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
  341.       return;
  342.    }
  343.  
  344.    map = get_1d_map(ctx, target);
  345.    if (!map) {
  346.       _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
  347.       return;
  348.    }
  349.  
  350.    /* make copy of the control points */
  351.    if (type == GL_FLOAT)
  352.       pnts = _mesa_copy_map_points1f(target, ustride, uorder, (GLfloat*) points);
  353.    else
  354.       pnts = _mesa_copy_map_points1d(target, ustride, uorder, (GLdouble*) points);
  355.  
  356.  
  357.    FLUSH_VERTICES(ctx, _NEW_EVAL);
  358.    map->Order = uorder;
  359.    map->u1 = u1;
  360.    map->u2 = u2;
  361.    map->du = 1.0F / (u2 - u1);
  362.    free(map->Points);
  363.    map->Points = pnts;
  364. }
  365.  
  366.  
  367.  
  368. void GLAPIENTRY
  369. _mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride,
  370.              GLint order, const GLfloat *points )
  371. {
  372.    map1(target, u1, u2, stride, order, points, GL_FLOAT);
  373. }
  374.  
  375.  
  376. void GLAPIENTRY
  377. _mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride,
  378.              GLint order, const GLdouble *points )
  379. {
  380.    map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE);
  381. }
  382.  
  383.  
  384. static void
  385. map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
  386.       GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
  387.       const GLvoid *points, GLenum type )
  388. {
  389.    GET_CURRENT_CONTEXT(ctx);
  390.    GLint k;
  391.    GLfloat *pnts;
  392.    struct gl_2d_map *map = NULL;
  393.  
  394.    assert(type == GL_FLOAT || type == GL_DOUBLE);
  395.  
  396.    if (u1==u2) {
  397.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
  398.       return;
  399.    }
  400.  
  401.    if (v1==v2) {
  402.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
  403.       return;
  404.    }
  405.  
  406.    if (uorder<1 || uorder>MAX_EVAL_ORDER) {
  407.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
  408.       return;
  409.    }
  410.  
  411.    if (vorder<1 || vorder>MAX_EVAL_ORDER) {
  412.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
  413.       return;
  414.    }
  415.  
  416.    k = _mesa_evaluator_components( target );
  417.    if (k==0) {
  418.       _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
  419.       return;
  420.    }
  421.  
  422.    if (ustride < k) {
  423.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
  424.       return;
  425.    }
  426.    if (vstride < k) {
  427.       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
  428.       return;
  429.    }
  430.  
  431.    if (ctx->Texture.CurrentUnit != 0) {
  432.       /* See OpenGL 1.2.1 spec, section F.2.13 */
  433.       _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
  434.       return;
  435.    }
  436.  
  437.    map = get_2d_map(ctx, target);
  438.    if (!map) {
  439.       _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
  440.       return;
  441.    }
  442.  
  443.    /* make copy of the control points */
  444.    if (type == GL_FLOAT)
  445.       pnts = _mesa_copy_map_points2f(target, ustride, uorder,
  446.                                   vstride, vorder, (GLfloat*) points);
  447.    else
  448.       pnts = _mesa_copy_map_points2d(target, ustride, uorder,
  449.                                   vstride, vorder, (GLdouble*) points);
  450.  
  451.  
  452.    FLUSH_VERTICES(ctx, _NEW_EVAL);
  453.    map->Uorder = uorder;
  454.    map->u1 = u1;
  455.    map->u2 = u2;
  456.    map->du = 1.0F / (u2 - u1);
  457.    map->Vorder = vorder;
  458.    map->v1 = v1;
  459.    map->v2 = v2;
  460.    map->dv = 1.0F / (v2 - v1);
  461.    free(map->Points);
  462.    map->Points = pnts;
  463. }
  464.  
  465.  
  466. void GLAPIENTRY
  467. _mesa_Map2f( GLenum target,
  468.              GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
  469.              GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
  470.              const GLfloat *points)
  471. {
  472.    map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder,
  473.         points, GL_FLOAT);
  474. }
  475.  
  476.  
  477. void GLAPIENTRY
  478. _mesa_Map2d( GLenum target,
  479.              GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
  480.              GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
  481.              const GLdouble *points )
  482. {
  483.    map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder,
  484.         (GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE);
  485. }
  486.  
  487.  
  488.  
  489. void GLAPIENTRY
  490. _mesa_GetnMapdvARB( GLenum target, GLenum query, GLsizei bufSize, GLdouble *v )
  491. {
  492.    GET_CURRENT_CONTEXT(ctx);
  493.    struct gl_1d_map *map1d;
  494.    struct gl_2d_map *map2d;
  495.    GLint i, n;
  496.    GLfloat *data;
  497.    GLuint comps;
  498.    GLsizei numBytes;
  499.  
  500.    comps = _mesa_evaluator_components(target);
  501.    if (!comps) {
  502.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
  503.       return;
  504.    }
  505.  
  506.    map1d = get_1d_map(ctx, target);
  507.    map2d = get_2d_map(ctx, target);
  508.    assert(map1d || map2d);
  509.  
  510.    switch (query) {
  511.       case GL_COEFF:
  512.          if (map1d) {
  513.             data = map1d->Points;
  514.             n = map1d->Order * comps;
  515.          }
  516.          else {
  517.             data = map2d->Points;
  518.             n = map2d->Uorder * map2d->Vorder * comps;
  519.          }
  520.          if (data) {
  521.             numBytes = n * sizeof *v;
  522.             if (bufSize < numBytes)
  523.                goto overflow;
  524.             for (i=0;i<n;i++) {
  525.                v[i] = data[i];
  526.             }
  527.          }
  528.          break;
  529.       case GL_ORDER:
  530.          if (map1d) {
  531.             numBytes = 1 * sizeof *v;
  532.             if (bufSize < numBytes)
  533.                goto overflow;
  534.             v[0] = (GLdouble) map1d->Order;
  535.          }
  536.          else {
  537.             numBytes = 2 * sizeof *v;
  538.             if (bufSize < numBytes)
  539.                goto overflow;
  540.             v[0] = (GLdouble) map2d->Uorder;
  541.             v[1] = (GLdouble) map2d->Vorder;
  542.          }
  543.          break;
  544.       case GL_DOMAIN:
  545.          if (map1d) {
  546.             numBytes = 2 * sizeof *v;
  547.             if (bufSize < numBytes)
  548.               goto overflow;
  549.             v[0] = (GLdouble) map1d->u1;
  550.             v[1] = (GLdouble) map1d->u2;
  551.          }
  552.          else {
  553.             numBytes = 4 * sizeof *v;
  554.             if (bufSize < numBytes)
  555.                goto overflow;
  556.             v[0] = (GLdouble) map2d->u1;
  557.             v[1] = (GLdouble) map2d->u2;
  558.             v[2] = (GLdouble) map2d->v1;
  559.             v[3] = (GLdouble) map2d->v2;
  560.          }
  561.          break;
  562.       default:
  563.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
  564.    }
  565.    return;
  566.  
  567. overflow:
  568.    _mesa_error( ctx, GL_INVALID_OPERATION,
  569.                "glGetnMapdvARB(out of bounds: bufSize is %d,"
  570.                " but %d bytes are required)", bufSize, numBytes );
  571. }
  572.  
  573. void GLAPIENTRY
  574. _mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v )
  575. {
  576.    _mesa_GetnMapdvARB(target, query, INT_MAX, v);
  577. }
  578.  
  579. void GLAPIENTRY
  580. _mesa_GetnMapfvARB( GLenum target, GLenum query, GLsizei bufSize, GLfloat *v )
  581. {
  582.    GET_CURRENT_CONTEXT(ctx);
  583.    struct gl_1d_map *map1d;
  584.    struct gl_2d_map *map2d;
  585.    GLint i, n;
  586.    GLfloat *data;
  587.    GLuint comps;
  588.    GLsizei numBytes;
  589.  
  590.    comps = _mesa_evaluator_components(target);
  591.    if (!comps) {
  592.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
  593.       return;
  594.    }
  595.  
  596.    map1d = get_1d_map(ctx, target);
  597.    map2d = get_2d_map(ctx, target);
  598.    assert(map1d || map2d);
  599.  
  600.    switch (query) {
  601.       case GL_COEFF:
  602.          if (map1d) {
  603.             data = map1d->Points;
  604.             n = map1d->Order * comps;
  605.          }
  606.          else {
  607.             data = map2d->Points;
  608.             n = map2d->Uorder * map2d->Vorder * comps;
  609.          }
  610.          if (data) {
  611.             numBytes = n * sizeof *v;
  612.             if (bufSize < numBytes)
  613.                goto overflow;
  614.             for (i=0;i<n;i++) {
  615.                v[i] = data[i];
  616.             }
  617.          }
  618.          break;
  619.       case GL_ORDER:
  620.          if (map1d) {
  621.             numBytes = 1 * sizeof *v;
  622.             if (bufSize < numBytes)
  623.                goto overflow;
  624.             v[0] = (GLfloat) map1d->Order;
  625.          }
  626.          else {
  627.             numBytes = 2 * sizeof *v;
  628.             if (bufSize < numBytes)
  629.                goto overflow;
  630.             v[0] = (GLfloat) map2d->Uorder;
  631.             v[1] = (GLfloat) map2d->Vorder;
  632.          }
  633.          break;
  634.       case GL_DOMAIN:
  635.          if (map1d) {
  636.             numBytes = 2 * sizeof *v;
  637.             if (bufSize < numBytes)
  638.                goto overflow;
  639.             v[0] = map1d->u1;
  640.             v[1] = map1d->u2;
  641.          }
  642.          else {
  643.             numBytes = 4 * sizeof *v;
  644.             if (bufSize < numBytes)
  645.                goto overflow;
  646.             v[0] = map2d->u1;
  647.             v[1] = map2d->u2;
  648.             v[2] = map2d->v1;
  649.             v[3] = map2d->v2;
  650.          }
  651.          break;
  652.       default:
  653.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
  654.    }
  655.    return;
  656.  
  657. overflow:
  658.    _mesa_error( ctx, GL_INVALID_OPERATION,
  659.                "glGetnMapfvARB(out of bounds: bufSize is %d,"
  660.                " but %d bytes are required)", bufSize, numBytes );
  661. }
  662.  
  663.  
  664. void GLAPIENTRY
  665. _mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v )
  666. {
  667.    _mesa_GetnMapfvARB(target, query, INT_MAX, v);
  668. }
  669.  
  670.  
  671. void GLAPIENTRY
  672. _mesa_GetnMapivARB( GLenum target, GLenum query, GLsizei bufSize, GLint *v )
  673. {
  674.    GET_CURRENT_CONTEXT(ctx);
  675.    struct gl_1d_map *map1d;
  676.    struct gl_2d_map *map2d;
  677.    GLuint i, n;
  678.    GLfloat *data;
  679.    GLuint comps;
  680.    GLsizei numBytes;
  681.  
  682.    comps = _mesa_evaluator_components(target);
  683.    if (!comps) {
  684.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
  685.       return;
  686.    }
  687.  
  688.    map1d = get_1d_map(ctx, target);
  689.    map2d = get_2d_map(ctx, target);
  690.    assert(map1d || map2d);
  691.  
  692.    switch (query) {
  693.       case GL_COEFF:
  694.          if (map1d) {
  695.             data = map1d->Points;
  696.             n = map1d->Order * comps;
  697.          }
  698.          else {
  699.             data = map2d->Points;
  700.             n = map2d->Uorder * map2d->Vorder * comps;
  701.          }
  702.          if (data) {
  703.             numBytes = n * sizeof *v;
  704.             if (bufSize < numBytes)
  705.                goto overflow;
  706.             for (i=0;i<n;i++) {
  707.                v[i] = IROUND(data[i]);
  708.             }
  709.          }
  710.          break;
  711.       case GL_ORDER:
  712.          if (map1d) {
  713.             numBytes = 1 * sizeof *v;
  714.             if (bufSize < numBytes)
  715.                goto overflow;
  716.             v[0] = map1d->Order;
  717.          }
  718.          else {
  719.             numBytes = 2 * sizeof *v;
  720.             if (bufSize < numBytes)
  721.                goto overflow;
  722.             v[0] = map2d->Uorder;
  723.             v[1] = map2d->Vorder;
  724.          }
  725.          break;
  726.       case GL_DOMAIN:
  727.          if (map1d) {
  728.             numBytes = 2 * sizeof *v;
  729.             if (bufSize < numBytes)
  730.                goto overflow;
  731.             v[0] = IROUND(map1d->u1);
  732.             v[1] = IROUND(map1d->u2);
  733.          }
  734.          else {
  735.             numBytes = 4 * sizeof *v;
  736.             if (bufSize < numBytes)
  737.                goto overflow;
  738.             v[0] = IROUND(map2d->u1);
  739.             v[1] = IROUND(map2d->u2);
  740.             v[2] = IROUND(map2d->v1);
  741.             v[3] = IROUND(map2d->v2);
  742.          }
  743.          break;
  744.       default:
  745.          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
  746.    }
  747.    return;
  748.  
  749. overflow:
  750.    _mesa_error( ctx, GL_INVALID_OPERATION,
  751.                "glGetnMapivARB(out of bounds: bufSize is %d,"
  752.                " but %d bytes are required)", bufSize, numBytes );
  753. }
  754.  
  755.  
  756. void GLAPIENTRY
  757. _mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
  758. {
  759.    _mesa_GetnMapivARB(target, query, INT_MAX, v);
  760. }
  761.  
  762.  
  763. void GLAPIENTRY
  764. _mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 )
  765. {
  766.    GET_CURRENT_CONTEXT(ctx);
  767.  
  768.    if (un<1) {
  769.       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
  770.       return;
  771.    }
  772.    FLUSH_VERTICES(ctx, _NEW_EVAL);
  773.    ctx->Eval.MapGrid1un = un;
  774.    ctx->Eval.MapGrid1u1 = u1;
  775.    ctx->Eval.MapGrid1u2 = u2;
  776.    ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
  777. }
  778.  
  779.  
  780. void GLAPIENTRY
  781. _mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
  782. {
  783.    _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
  784. }
  785.  
  786.  
  787. void GLAPIENTRY
  788. _mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
  789.                  GLint vn, GLfloat v1, GLfloat v2 )
  790. {
  791.    GET_CURRENT_CONTEXT(ctx);
  792.  
  793.    if (un<1) {
  794.       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
  795.       return;
  796.    }
  797.    if (vn<1) {
  798.       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
  799.       return;
  800.    }
  801.  
  802.    FLUSH_VERTICES(ctx, _NEW_EVAL);
  803.    ctx->Eval.MapGrid2un = un;
  804.    ctx->Eval.MapGrid2u1 = u1;
  805.    ctx->Eval.MapGrid2u2 = u2;
  806.    ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
  807.    ctx->Eval.MapGrid2vn = vn;
  808.    ctx->Eval.MapGrid2v1 = v1;
  809.    ctx->Eval.MapGrid2v2 = v2;
  810.    ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
  811. }
  812.  
  813.  
  814. void GLAPIENTRY
  815. _mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
  816.                  GLint vn, GLdouble v1, GLdouble v2 )
  817. {
  818.    _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
  819.                     vn, (GLfloat) v1, (GLfloat) v2 );
  820. }
  821.  
  822.  
  823. void
  824. _mesa_install_eval_vtxfmt(struct _glapi_table *disp,
  825.                           const GLvertexformat *vfmt)
  826. {
  827.    SET_EvalCoord1f(disp, vfmt->EvalCoord1f);
  828.    SET_EvalCoord1fv(disp, vfmt->EvalCoord1fv);
  829.    SET_EvalCoord2f(disp, vfmt->EvalCoord2f);
  830.    SET_EvalCoord2fv(disp, vfmt->EvalCoord2fv);
  831.    SET_EvalPoint1(disp, vfmt->EvalPoint1);
  832.    SET_EvalPoint2(disp, vfmt->EvalPoint2);
  833. }
  834.  
  835.  
  836. /**********************************************************************/
  837. /*****                      Initialization                        *****/
  838. /**********************************************************************/
  839.  
  840. /**
  841.  * Initialize a 1-D evaluator map.
  842.  */
  843. static void
  844. init_1d_map( struct gl_1d_map *map, int n, const float *initial )
  845. {
  846.    map->Order = 1;
  847.    map->u1 = 0.0;
  848.    map->u2 = 1.0;
  849.    map->Points = malloc(n * sizeof(GLfloat));
  850.    if (map->Points) {
  851.       GLint i;
  852.       for (i=0;i<n;i++)
  853.          map->Points[i] = initial[i];
  854.    }
  855. }
  856.  
  857.  
  858. /**
  859.  * Initialize a 2-D evaluator map
  860.  */
  861. static void
  862. init_2d_map( struct gl_2d_map *map, int n, const float *initial )
  863. {
  864.    map->Uorder = 1;
  865.    map->Vorder = 1;
  866.    map->u1 = 0.0;
  867.    map->u2 = 1.0;
  868.    map->v1 = 0.0;
  869.    map->v2 = 1.0;
  870.    map->Points = malloc(n * sizeof(GLfloat));
  871.    if (map->Points) {
  872.       GLint i;
  873.       for (i=0;i<n;i++)
  874.          map->Points[i] = initial[i];
  875.    }
  876. }
  877.  
  878.  
  879. void _mesa_init_eval( struct gl_context *ctx )
  880. {
  881.    /* Evaluators group */
  882.    ctx->Eval.Map1Color4 = GL_FALSE;
  883.    ctx->Eval.Map1Index = GL_FALSE;
  884.    ctx->Eval.Map1Normal = GL_FALSE;
  885.    ctx->Eval.Map1TextureCoord1 = GL_FALSE;
  886.    ctx->Eval.Map1TextureCoord2 = GL_FALSE;
  887.    ctx->Eval.Map1TextureCoord3 = GL_FALSE;
  888.    ctx->Eval.Map1TextureCoord4 = GL_FALSE;
  889.    ctx->Eval.Map1Vertex3 = GL_FALSE;
  890.    ctx->Eval.Map1Vertex4 = GL_FALSE;
  891.    ctx->Eval.Map2Color4 = GL_FALSE;
  892.    ctx->Eval.Map2Index = GL_FALSE;
  893.    ctx->Eval.Map2Normal = GL_FALSE;
  894.    ctx->Eval.Map2TextureCoord1 = GL_FALSE;
  895.    ctx->Eval.Map2TextureCoord2 = GL_FALSE;
  896.    ctx->Eval.Map2TextureCoord3 = GL_FALSE;
  897.    ctx->Eval.Map2TextureCoord4 = GL_FALSE;
  898.    ctx->Eval.Map2Vertex3 = GL_FALSE;
  899.    ctx->Eval.Map2Vertex4 = GL_FALSE;
  900.    ctx->Eval.AutoNormal = GL_FALSE;
  901.    ctx->Eval.MapGrid1un = 1;
  902.    ctx->Eval.MapGrid1u1 = 0.0;
  903.    ctx->Eval.MapGrid1u2 = 1.0;
  904.    ctx->Eval.MapGrid2un = 1;
  905.    ctx->Eval.MapGrid2vn = 1;
  906.    ctx->Eval.MapGrid2u1 = 0.0;
  907.    ctx->Eval.MapGrid2u2 = 1.0;
  908.    ctx->Eval.MapGrid2v1 = 0.0;
  909.    ctx->Eval.MapGrid2v2 = 1.0;
  910.  
  911.    /* Evaluator data */
  912.    {
  913.       static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
  914.       static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
  915.       static GLfloat index[1] = { 1.0 };
  916.       static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
  917.       static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
  918.  
  919.       init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex );
  920.       init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex );
  921.       init_1d_map( &ctx->EvalMap.Map1Index, 1, index );
  922.       init_1d_map( &ctx->EvalMap.Map1Color4, 4, color );
  923.       init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal );
  924.       init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord );
  925.       init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord );
  926.       init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord );
  927.       init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord );
  928.  
  929.       init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex );
  930.       init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex );
  931.       init_2d_map( &ctx->EvalMap.Map2Index, 1, index );
  932.       init_2d_map( &ctx->EvalMap.Map2Color4, 4, color );
  933.       init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal );
  934.       init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord );
  935.       init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord );
  936.       init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord );
  937.       init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord );
  938.    }
  939. }
  940.  
  941.  
  942. void _mesa_free_eval_data( struct gl_context *ctx )
  943. {
  944.    /* Free evaluator data */
  945.    free(ctx->EvalMap.Map1Vertex3.Points);
  946.    free(ctx->EvalMap.Map1Vertex4.Points);
  947.    free(ctx->EvalMap.Map1Index.Points);
  948.    free(ctx->EvalMap.Map1Color4.Points);
  949.    free(ctx->EvalMap.Map1Normal.Points);
  950.    free(ctx->EvalMap.Map1Texture1.Points);
  951.    free(ctx->EvalMap.Map1Texture2.Points);
  952.    free(ctx->EvalMap.Map1Texture3.Points);
  953.    free(ctx->EvalMap.Map1Texture4.Points);
  954.  
  955.    free(ctx->EvalMap.Map2Vertex3.Points);
  956.    free(ctx->EvalMap.Map2Vertex4.Points);
  957.    free(ctx->EvalMap.Map2Index.Points);
  958.    free(ctx->EvalMap.Map2Color4.Points);
  959.    free(ctx->EvalMap.Map2Normal.Points);
  960.    free(ctx->EvalMap.Map2Texture1.Points);
  961.    free(ctx->EvalMap.Map2Texture2.Points);
  962.    free(ctx->EvalMap.Map2Texture3.Points);
  963.    free(ctx->EvalMap.Map2Texture4.Points);
  964. }
  965.