Home | History | Annotate | Download | only in main
      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 (at) cip.informatik.uni-erlangen.de) and
     30  * Volker Weiss (vrweiss (at) 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