Home | History | Annotate | Download | only in main
      1 
      2 /*
      3  * Mesa 3-D graphics library
      4  * Version:  5.1
      5  *
      6  * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the "Software"),
     10  * to deal in the Software without restriction, including without limitation
     11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     12  * and/or sell copies of the Software, and to permit persons to whom the
     13  * Software is furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included
     16  * in all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     22  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     23  * CONNECTION WITH THE SOFTWARE OR THE USE OR 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 "colormac.h"
     43 #include "context.h"
     44 #include "eval.h"
     45 #include "macros.h"
     46 #include "mfeatures.h"
     47 #include "mtypes.h"
     48 #include "main/dispatch.h"
     49 
     50 
     51 #if FEATURE_evaluators
     52 
     53 
     54 /*
     55  * Return the number of components per control point for any type of
     56  * evaluator.  Return 0 if bad target.
     57  * See table 5.1 in the OpenGL 1.2 spec.
     58  */
     59 GLuint _mesa_evaluator_components( GLenum target )
     60 {
     61    switch (target) {
     62       case GL_MAP1_VERTEX_3:		return 3;
     63       case GL_MAP1_VERTEX_4:		return 4;
     64       case GL_MAP1_INDEX:		return 1;
     65       case GL_MAP1_COLOR_4:		return 4;
     66       case GL_MAP1_NORMAL:		return 3;
     67       case GL_MAP1_TEXTURE_COORD_1:	return 1;
     68       case GL_MAP1_TEXTURE_COORD_2:	return 2;
     69       case GL_MAP1_TEXTURE_COORD_3:	return 3;
     70       case GL_MAP1_TEXTURE_COORD_4:	return 4;
     71       case GL_MAP2_VERTEX_3:		return 3;
     72       case GL_MAP2_VERTEX_4:		return 4;
     73       case GL_MAP2_INDEX:		return 1;
     74       case GL_MAP2_COLOR_4:		return 4;
     75       case GL_MAP2_NORMAL:		return 3;
     76       case GL_MAP2_TEXTURE_COORD_1:	return 1;
     77       case GL_MAP2_TEXTURE_COORD_2:	return 2;
     78       case GL_MAP2_TEXTURE_COORD_3:	return 3;
     79       case GL_MAP2_TEXTURE_COORD_4:	return 4;
     80       default:				break;
     81    }
     82 
     83    /* XXX need to check for the vertex program extension
     84    if (!ctx->Extensions.NV_vertex_program)
     85       return 0;
     86    */
     87 
     88    if (target >= GL_MAP1_VERTEX_ATTRIB0_4_NV &&
     89        target <= GL_MAP1_VERTEX_ATTRIB15_4_NV)
     90       return 4;
     91 
     92    if (target >= GL_MAP2_VERTEX_ATTRIB0_4_NV &&
     93        target <= GL_MAP2_VERTEX_ATTRIB15_4_NV)
     94       return 4;
     95 
     96    return 0;
     97 }
     98 
     99 
    100 /*
    101  * Return pointer to the gl_1d_map struct for the named target.
    102  */
    103 static struct gl_1d_map *
    104 get_1d_map( struct gl_context *ctx, GLenum target )
    105 {
    106    switch (target) {
    107       case GL_MAP1_VERTEX_3:
    108          return &ctx->EvalMap.Map1Vertex3;
    109       case GL_MAP1_VERTEX_4:
    110          return &ctx->EvalMap.Map1Vertex4;
    111       case GL_MAP1_INDEX:
    112          return &ctx->EvalMap.Map1Index;
    113       case GL_MAP1_COLOR_4:
    114          return &ctx->EvalMap.Map1Color4;
    115       case GL_MAP1_NORMAL:
    116          return &ctx->EvalMap.Map1Normal;
    117       case GL_MAP1_TEXTURE_COORD_1:
    118          return &ctx->EvalMap.Map1Texture1;
    119       case GL_MAP1_TEXTURE_COORD_2:
    120          return &ctx->EvalMap.Map1Texture2;
    121       case GL_MAP1_TEXTURE_COORD_3:
    122          return &ctx->EvalMap.Map1Texture3;
    123       case GL_MAP1_TEXTURE_COORD_4:
    124          return &ctx->EvalMap.Map1Texture4;
    125       case GL_MAP1_VERTEX_ATTRIB0_4_NV:
    126       case GL_MAP1_VERTEX_ATTRIB1_4_NV:
    127       case GL_MAP1_VERTEX_ATTRIB2_4_NV:
    128       case GL_MAP1_VERTEX_ATTRIB3_4_NV:
    129       case GL_MAP1_VERTEX_ATTRIB4_4_NV:
    130       case GL_MAP1_VERTEX_ATTRIB5_4_NV:
    131       case GL_MAP1_VERTEX_ATTRIB6_4_NV:
    132       case GL_MAP1_VERTEX_ATTRIB7_4_NV:
    133       case GL_MAP1_VERTEX_ATTRIB8_4_NV:
    134       case GL_MAP1_VERTEX_ATTRIB9_4_NV:
    135       case GL_MAP1_VERTEX_ATTRIB10_4_NV:
    136       case GL_MAP1_VERTEX_ATTRIB11_4_NV:
    137       case GL_MAP1_VERTEX_ATTRIB12_4_NV:
    138       case GL_MAP1_VERTEX_ATTRIB13_4_NV:
    139       case GL_MAP1_VERTEX_ATTRIB14_4_NV:
    140       case GL_MAP1_VERTEX_ATTRIB15_4_NV:
    141          if (!ctx->Extensions.NV_vertex_program)
    142             return NULL;
    143          return &ctx->EvalMap.Map1Attrib[target - GL_MAP1_VERTEX_ATTRIB0_4_NV];
    144       default:
    145          return NULL;
    146    }
    147 }
    148 
    149 
    150 /*
    151  * Return pointer to the gl_2d_map struct for the named target.
    152  */
    153 static struct gl_2d_map *
    154 get_2d_map( struct gl_context *ctx, GLenum target )
    155 {
    156    switch (target) {
    157       case GL_MAP2_VERTEX_3:
    158          return &ctx->EvalMap.Map2Vertex3;
    159       case GL_MAP2_VERTEX_4:
    160          return &ctx->EvalMap.Map2Vertex4;
    161       case GL_MAP2_INDEX:
    162          return &ctx->EvalMap.Map2Index;
    163       case GL_MAP2_COLOR_4:
    164          return &ctx->EvalMap.Map2Color4;
    165       case GL_MAP2_NORMAL:
    166          return &ctx->EvalMap.Map2Normal;
    167       case GL_MAP2_TEXTURE_COORD_1:
    168          return &ctx->EvalMap.Map2Texture1;
    169       case GL_MAP2_TEXTURE_COORD_2:
    170          return &ctx->EvalMap.Map2Texture2;
    171       case GL_MAP2_TEXTURE_COORD_3:
    172          return &ctx->EvalMap.Map2Texture3;
    173       case GL_MAP2_TEXTURE_COORD_4:
    174          return &ctx->EvalMap.Map2Texture4;
    175       case GL_MAP2_VERTEX_ATTRIB0_4_NV:
    176       case GL_MAP2_VERTEX_ATTRIB1_4_NV:
    177       case GL_MAP2_VERTEX_ATTRIB2_4_NV:
    178       case GL_MAP2_VERTEX_ATTRIB3_4_NV:
    179       case GL_MAP2_VERTEX_ATTRIB4_4_NV:
    180       case GL_MAP2_VERTEX_ATTRIB5_4_NV:
    181       case GL_MAP2_VERTEX_ATTRIB6_4_NV:
    182       case GL_MAP2_VERTEX_ATTRIB7_4_NV:
    183       case GL_MAP2_VERTEX_ATTRIB8_4_NV:
    184       case GL_MAP2_VERTEX_ATTRIB9_4_NV:
    185       case GL_MAP2_VERTEX_ATTRIB10_4_NV:
    186       case GL_MAP2_VERTEX_ATTRIB11_4_NV:
    187       case GL_MAP2_VERTEX_ATTRIB12_4_NV:
    188       case GL_MAP2_VERTEX_ATTRIB13_4_NV:
    189       case GL_MAP2_VERTEX_ATTRIB14_4_NV:
    190       case GL_MAP2_VERTEX_ATTRIB15_4_NV:
    191          if (!ctx->Extensions.NV_vertex_program)
    192             return NULL;
    193          return &ctx->EvalMap.Map2Attrib[target - GL_MAP2_VERTEX_ATTRIB0_4_NV];
    194       default:
    195          return NULL;
    196    }
    197 }
    198 
    199 
    200 /**********************************************************************/
    201 /***            Copy and deallocate control points                  ***/
    202 /**********************************************************************/
    203 
    204 
    205 /*
    206  * Copy 1-parametric evaluator control points from user-specified
    207  * memory space to a buffer of contiguous control points.
    208  * \param see glMap1f for details
    209  * \return pointer to buffer of contiguous control points or NULL if out
    210  *          of memory.
    211  */
    212 GLfloat *_mesa_copy_map_points1f( GLenum target, GLint ustride, GLint uorder,
    213                                   const GLfloat *points )
    214 {
    215    GLfloat *buffer, *p;
    216    GLint i, k, size = _mesa_evaluator_components(target);
    217 
    218    if (!points || !size)
    219       return NULL;
    220 
    221    buffer = (GLfloat *) MALLOC(uorder * size * sizeof(GLfloat));
    222 
    223    if (buffer)
    224       for (i = 0, p = buffer; i < uorder; i++, points += ustride)
    225 	for (k = 0; k < size; k++)
    226 	  *p++ = points[k];
    227 
    228    return buffer;
    229 }
    230 
    231 
    232 
    233 /*
    234  * Same as above but convert doubles to floats.
    235  */
    236 GLfloat *_mesa_copy_map_points1d( GLenum target, GLint ustride, GLint uorder,
    237                                   const GLdouble *points )
    238 {
    239    GLfloat *buffer, *p;
    240    GLint i, k, size = _mesa_evaluator_components(target);
    241 
    242    if (!points || !size)
    243       return NULL;
    244 
    245    buffer = (GLfloat *) MALLOC(uorder * size * sizeof(GLfloat));
    246 
    247    if (buffer)
    248       for (i = 0, p = buffer; i < uorder; i++, points += ustride)
    249 	for (k = 0; k < size; k++)
    250 	  *p++ = (GLfloat) points[k];
    251 
    252    return buffer;
    253 }
    254 
    255 
    256 
    257 /*
    258  * Copy 2-parametric evaluator control points from user-specified
    259  * memory space to a buffer of contiguous control points.
    260  * Additional memory is allocated to be used by the horner and
    261  * de Casteljau evaluation schemes.
    262  *
    263  * \param see glMap2f for details
    264  * \return pointer to buffer of contiguous control points or NULL if out
    265  *          of memory.
    266  */
    267 GLfloat *_mesa_copy_map_points2f( GLenum target,
    268                                   GLint ustride, GLint uorder,
    269                                   GLint vstride, GLint vorder,
    270                                   const GLfloat *points )
    271 {
    272    GLfloat *buffer, *p;
    273    GLint i, j, k, size, dsize, hsize;
    274    GLint uinc;
    275 
    276    size = _mesa_evaluator_components(target);
    277 
    278    if (!points || size==0) {
    279       return NULL;
    280    }
    281 
    282    /* max(uorder, vorder) additional points are used in      */
    283    /* horner evaluation and uorder*vorder additional */
    284    /* values are needed for de Casteljau                     */
    285    dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
    286    hsize = (uorder > vorder ? uorder : vorder)*size;
    287 
    288    if(hsize>dsize)
    289      buffer = (GLfloat *) MALLOC((uorder*vorder*size+hsize)*sizeof(GLfloat));
    290    else
    291      buffer = (GLfloat *) MALLOC((uorder*vorder*size+dsize)*sizeof(GLfloat));
    292 
    293    /* compute the increment value for the u-loop */
    294    uinc = ustride - vorder*vstride;
    295 
    296    if (buffer)
    297       for (i=0, p=buffer; i<uorder; i++, points += uinc)
    298 	 for (j=0; j<vorder; j++, points += vstride)
    299 	    for (k=0; k<size; k++)
    300 	       *p++ = points[k];
    301 
    302    return buffer;
    303 }
    304 
    305 
    306 
    307 /*
    308  * Same as above but convert doubles to floats.
    309  */
    310 GLfloat *_mesa_copy_map_points2d(GLenum target,
    311                                  GLint ustride, GLint uorder,
    312                                  GLint vstride, GLint vorder,
    313                                  const GLdouble *points )
    314 {
    315    GLfloat *buffer, *p;
    316    GLint i, j, k, size, hsize, dsize;
    317    GLint uinc;
    318 
    319    size = _mesa_evaluator_components(target);
    320 
    321    if (!points || size==0) {
    322       return NULL;
    323    }
    324 
    325    /* max(uorder, vorder) additional points are used in      */
    326    /* horner evaluation and uorder*vorder additional */
    327    /* values are needed for de Casteljau                     */
    328    dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
    329    hsize = (uorder > vorder ? uorder : vorder)*size;
    330 
    331    if(hsize>dsize)
    332      buffer = (GLfloat *) MALLOC((uorder*vorder*size+hsize)*sizeof(GLfloat));
    333    else
    334      buffer = (GLfloat *) MALLOC((uorder*vorder*size+dsize)*sizeof(GLfloat));
    335 
    336    /* compute the increment value for the u-loop */
    337    uinc = ustride - vorder*vstride;
    338 
    339    if (buffer)
    340       for (i=0, p=buffer; i<uorder; i++, points += uinc)
    341 	 for (j=0; j<vorder; j++, points += vstride)
    342 	    for (k=0; k<size; k++)
    343 	       *p++ = (GLfloat) points[k];
    344 
    345    return buffer;
    346 }
    347 
    348 
    349 
    350 
    351 /**********************************************************************/
    352 /***                      API entry points                          ***/
    353 /**********************************************************************/
    354 
    355 
    356 /*
    357  * This does the work of glMap1[fd].
    358  */
    359 static void
    360 map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
    361      GLint uorder, const GLvoid *points, GLenum type )
    362 {
    363    GET_CURRENT_CONTEXT(ctx);
    364    GLint k;
    365    GLfloat *pnts;
    366    struct gl_1d_map *map = NULL;
    367 
    368    ASSERT_OUTSIDE_BEGIN_END(ctx);
    369    ASSERT(type == GL_FLOAT || type == GL_DOUBLE);
    370 
    371    if (u1 == u2) {
    372       _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
    373       return;
    374    }
    375    if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
    376       _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
    377       return;
    378    }
    379    if (!points) {
    380       _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(points)" );
    381       return;
    382    }
    383 
    384    k = _mesa_evaluator_components( target );
    385    if (k == 0) {
    386       _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
    387    }
    388 
    389    if (ustride < k) {
    390       _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
    391       return;
    392    }
    393 
    394    if (ctx->Texture.CurrentUnit != 0) {
    395       /* See OpenGL 1.2.1 spec, section F.2.13 */
    396       _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
    397       return;
    398    }
    399 
    400    map = get_1d_map(ctx, target);
    401    if (!map) {
    402       _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
    403       return;
    404    }
    405 
    406    /* make copy of the control points */
    407    if (type == GL_FLOAT)
    408       pnts = _mesa_copy_map_points1f(target, ustride, uorder, (GLfloat*) points);
    409    else
    410       pnts = _mesa_copy_map_points1d(target, ustride, uorder, (GLdouble*) points);
    411 
    412 
    413    FLUSH_VERTICES(ctx, _NEW_EVAL);
    414    map->Order = uorder;
    415    map->u1 = u1;
    416    map->u2 = u2;
    417    map->du = 1.0F / (u2 - u1);
    418    if (map->Points)
    419       FREE( map->Points );
    420    map->Points = pnts;
    421 }
    422 
    423 
    424 
    425 static void GLAPIENTRY
    426 _mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride,
    427              GLint order, const GLfloat *points )
    428 {
    429    map1(target, u1, u2, stride, order, points, GL_FLOAT);
    430 }
    431 
    432 
    433 static void GLAPIENTRY
    434 _mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride,
    435              GLint order, const GLdouble *points )
    436 {
    437    map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE);
    438 }
    439 
    440 
    441 static void
    442 map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
    443       GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
    444       const GLvoid *points, GLenum type )
    445 {
    446    GET_CURRENT_CONTEXT(ctx);
    447    GLint k;
    448    GLfloat *pnts;
    449    struct gl_2d_map *map = NULL;
    450 
    451    ASSERT_OUTSIDE_BEGIN_END(ctx);
    452    ASSERT(type == GL_FLOAT || type == GL_DOUBLE);
    453 
    454    if (u1==u2) {
    455       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
    456       return;
    457    }
    458 
    459    if (v1==v2) {
    460       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
    461       return;
    462    }
    463 
    464    if (uorder<1 || uorder>MAX_EVAL_ORDER) {
    465       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
    466       return;
    467    }
    468 
    469    if (vorder<1 || vorder>MAX_EVAL_ORDER) {
    470       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
    471       return;
    472    }
    473 
    474    k = _mesa_evaluator_components( target );
    475    if (k==0) {
    476       _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
    477    }
    478 
    479    if (ustride < k) {
    480       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
    481       return;
    482    }
    483    if (vstride < k) {
    484       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
    485       return;
    486    }
    487 
    488    if (ctx->Texture.CurrentUnit != 0) {
    489       /* See OpenGL 1.2.1 spec, section F.2.13 */
    490       _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
    491       return;
    492    }
    493 
    494    map = get_2d_map(ctx, target);
    495    if (!map) {
    496       _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
    497       return;
    498    }
    499 
    500    /* make copy of the control points */
    501    if (type == GL_FLOAT)
    502       pnts = _mesa_copy_map_points2f(target, ustride, uorder,
    503                                   vstride, vorder, (GLfloat*) points);
    504    else
    505       pnts = _mesa_copy_map_points2d(target, ustride, uorder,
    506                                   vstride, vorder, (GLdouble*) points);
    507 
    508 
    509    FLUSH_VERTICES(ctx, _NEW_EVAL);
    510    map->Uorder = uorder;
    511    map->u1 = u1;
    512    map->u2 = u2;
    513    map->du = 1.0F / (u2 - u1);
    514    map->Vorder = vorder;
    515    map->v1 = v1;
    516    map->v2 = v2;
    517    map->dv = 1.0F / (v2 - v1);
    518    if (map->Points)
    519       FREE( map->Points );
    520    map->Points = pnts;
    521 }
    522 
    523 
    524 static void GLAPIENTRY
    525 _mesa_Map2f( GLenum target,
    526              GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
    527              GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
    528              const GLfloat *points)
    529 {
    530    map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder,
    531         points, GL_FLOAT);
    532 }
    533 
    534 
    535 static void GLAPIENTRY
    536 _mesa_Map2d( GLenum target,
    537              GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
    538              GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
    539              const GLdouble *points )
    540 {
    541    map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder,
    542 	(GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE);
    543 }
    544 
    545 
    546 
    547 static void GLAPIENTRY
    548 _mesa_GetnMapdvARB( GLenum target, GLenum query, GLsizei bufSize, GLdouble *v )
    549 {
    550    GET_CURRENT_CONTEXT(ctx);
    551    struct gl_1d_map *map1d;
    552    struct gl_2d_map *map2d;
    553    GLint i, n;
    554    GLfloat *data;
    555    GLuint comps;
    556    GLsizei numBytes;
    557 
    558    ASSERT_OUTSIDE_BEGIN_END(ctx);
    559 
    560    comps = _mesa_evaluator_components(target);
    561    if (!comps) {
    562       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
    563       return;
    564    }
    565 
    566    map1d = get_1d_map(ctx, target);
    567    map2d = get_2d_map(ctx, target);
    568    ASSERT(map1d || map2d);
    569 
    570    switch (query) {
    571       case GL_COEFF:
    572          if (map1d) {
    573             data = map1d->Points;
    574             n = map1d->Order * comps;
    575          }
    576          else {
    577             data = map2d->Points;
    578             n = map2d->Uorder * map2d->Vorder * comps;
    579          }
    580 	 if (data) {
    581             numBytes = n * sizeof *v;
    582             if (bufSize < numBytes)
    583                goto overflow;
    584 	    for (i=0;i<n;i++) {
    585 	       v[i] = data[i];
    586 	    }
    587 	 }
    588          break;
    589       case GL_ORDER:
    590          if (map1d) {
    591             numBytes = 1 * sizeof *v;
    592             if (bufSize < numBytes)
    593                goto overflow;
    594             v[0] = (GLdouble) map1d->Order;
    595          }
    596          else {
    597             numBytes = 2 * sizeof *v;
    598             if (bufSize < numBytes)
    599                goto overflow;
    600             v[0] = (GLdouble) map2d->Uorder;
    601             v[1] = (GLdouble) map2d->Vorder;
    602          }
    603          break;
    604       case GL_DOMAIN:
    605          if (map1d) {
    606             numBytes = 2 * sizeof *v;
    607             if (bufSize < numBytes)
    608               goto overflow;
    609             v[0] = (GLdouble) map1d->u1;
    610             v[1] = (GLdouble) map1d->u2;
    611          }
    612          else {
    613             numBytes = 4 * sizeof *v;
    614             if (bufSize < numBytes)
    615                goto overflow;
    616             v[0] = (GLdouble) map2d->u1;
    617             v[1] = (GLdouble) map2d->u2;
    618             v[2] = (GLdouble) map2d->v1;
    619             v[3] = (GLdouble) map2d->v2;
    620          }
    621          break;
    622       default:
    623          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
    624    }
    625    return;
    626 
    627 overflow:
    628    _mesa_error( ctx, GL_INVALID_OPERATION,
    629                "glGetnMapdvARB(out of bounds: bufSize is %d,"
    630                " but %d bytes are required)", bufSize, numBytes );
    631 }
    632 
    633 static void GLAPIENTRY
    634 _mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v )
    635 {
    636    _mesa_GetnMapdvARB(target, query, INT_MAX, v);
    637 }
    638 
    639 static void GLAPIENTRY
    640 _mesa_GetnMapfvARB( GLenum target, GLenum query, GLsizei bufSize, GLfloat *v )
    641 {
    642    GET_CURRENT_CONTEXT(ctx);
    643    struct gl_1d_map *map1d;
    644    struct gl_2d_map *map2d;
    645    GLint i, n;
    646    GLfloat *data;
    647    GLuint comps;
    648    GLsizei numBytes;
    649 
    650    ASSERT_OUTSIDE_BEGIN_END(ctx);
    651 
    652    comps = _mesa_evaluator_components(target);
    653    if (!comps) {
    654       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
    655       return;
    656    }
    657 
    658    map1d = get_1d_map(ctx, target);
    659    map2d = get_2d_map(ctx, target);
    660    ASSERT(map1d || map2d);
    661 
    662    switch (query) {
    663       case GL_COEFF:
    664          if (map1d) {
    665             data = map1d->Points;
    666             n = map1d->Order * comps;
    667          }
    668          else {
    669             data = map2d->Points;
    670             n = map2d->Uorder * map2d->Vorder * comps;
    671          }
    672 	 if (data) {
    673             numBytes = n * sizeof *v;
    674             if (bufSize < numBytes)
    675                goto overflow;
    676 	    for (i=0;i<n;i++) {
    677 	       v[i] = data[i];
    678 	    }
    679 	 }
    680          break;
    681       case GL_ORDER:
    682          if (map1d) {
    683             numBytes = 1 * sizeof *v;
    684             if (bufSize < numBytes)
    685                goto overflow;
    686             v[0] = (GLfloat) map1d->Order;
    687          }
    688          else {
    689             numBytes = 2 * sizeof *v;
    690             if (bufSize < numBytes)
    691                goto overflow;
    692             v[0] = (GLfloat) map2d->Uorder;
    693             v[1] = (GLfloat) map2d->Vorder;
    694          }
    695          break;
    696       case GL_DOMAIN:
    697          if (map1d) {
    698             numBytes = 2 * sizeof *v;
    699             if (bufSize < numBytes)
    700                goto overflow;
    701             v[0] = map1d->u1;
    702             v[1] = map1d->u2;
    703          }
    704          else {
    705             numBytes = 4 * sizeof *v;
    706             if (bufSize < numBytes)
    707                goto overflow;
    708             v[0] = map2d->u1;
    709             v[1] = map2d->u2;
    710             v[2] = map2d->v1;
    711             v[3] = map2d->v2;
    712          }
    713          break;
    714       default:
    715          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
    716    }
    717    return;
    718 
    719 overflow:
    720    _mesa_error( ctx, GL_INVALID_OPERATION,
    721                "glGetnMapfvARB(out of bounds: bufSize is %d,"
    722                " but %d bytes are required)", bufSize, numBytes );
    723 }
    724 
    725 
    726 static void GLAPIENTRY
    727 _mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v )
    728 {
    729    _mesa_GetnMapfvARB(target, query, INT_MAX, v);
    730 }
    731 
    732 
    733 static void GLAPIENTRY
    734 _mesa_GetnMapivARB( GLenum target, GLenum query, GLsizei bufSize, GLint *v )
    735 {
    736    GET_CURRENT_CONTEXT(ctx);
    737    struct gl_1d_map *map1d;
    738    struct gl_2d_map *map2d;
    739    GLuint i, n;
    740    GLfloat *data;
    741    GLuint comps;
    742    GLsizei numBytes;
    743 
    744    ASSERT_OUTSIDE_BEGIN_END(ctx);
    745 
    746    comps = _mesa_evaluator_components(target);
    747    if (!comps) {
    748       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
    749       return;
    750    }
    751 
    752    map1d = get_1d_map(ctx, target);
    753    map2d = get_2d_map(ctx, target);
    754    ASSERT(map1d || map2d);
    755 
    756    switch (query) {
    757       case GL_COEFF:
    758          if (map1d) {
    759             data = map1d->Points;
    760             n = map1d->Order * comps;
    761          }
    762          else {
    763             data = map2d->Points;
    764             n = map2d->Uorder * map2d->Vorder * comps;
    765          }
    766 	 if (data) {
    767             numBytes = n * sizeof *v;
    768             if (bufSize < numBytes)
    769                goto overflow;
    770 	    for (i=0;i<n;i++) {
    771 	       v[i] = IROUND(data[i]);
    772 	    }
    773 	 }
    774          break;
    775       case GL_ORDER:
    776          if (map1d) {
    777             numBytes = 1 * sizeof *v;
    778             if (bufSize < numBytes)
    779                goto overflow;
    780             v[0] = map1d->Order;
    781          }
    782          else {
    783             numBytes = 2 * sizeof *v;
    784             if (bufSize < numBytes)
    785                goto overflow;
    786             v[0] = map2d->Uorder;
    787             v[1] = map2d->Vorder;
    788          }
    789          break;
    790       case GL_DOMAIN:
    791          if (map1d) {
    792             numBytes = 2 * sizeof *v;
    793             if (bufSize < numBytes)
    794                goto overflow;
    795             v[0] = IROUND(map1d->u1);
    796             v[1] = IROUND(map1d->u2);
    797          }
    798          else {
    799             numBytes = 4 * sizeof *v;
    800             if (bufSize < numBytes)
    801                goto overflow;
    802             v[0] = IROUND(map2d->u1);
    803             v[1] = IROUND(map2d->u2);
    804             v[2] = IROUND(map2d->v1);
    805             v[3] = IROUND(map2d->v2);
    806          }
    807          break;
    808       default:
    809          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
    810    }
    811    return;
    812 
    813 overflow:
    814    _mesa_error( ctx, GL_INVALID_OPERATION,
    815                "glGetnMapivARB(out of bounds: bufSize is %d,"
    816                " but %d bytes are required)", bufSize, numBytes );
    817 }
    818 
    819 
    820 static void GLAPIENTRY
    821 _mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
    822 {
    823    _mesa_GetnMapivARB(target, query, INT_MAX, v);
    824 }
    825 
    826 
    827 static void GLAPIENTRY
    828 _mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 )
    829 {
    830    GET_CURRENT_CONTEXT(ctx);
    831    ASSERT_OUTSIDE_BEGIN_END(ctx);
    832 
    833    if (un<1) {
    834       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
    835       return;
    836    }
    837    FLUSH_VERTICES(ctx, _NEW_EVAL);
    838    ctx->Eval.MapGrid1un = un;
    839    ctx->Eval.MapGrid1u1 = u1;
    840    ctx->Eval.MapGrid1u2 = u2;
    841    ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
    842 }
    843 
    844 
    845 static void GLAPIENTRY
    846 _mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
    847 {
    848    _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
    849 }
    850 
    851 
    852 static void GLAPIENTRY
    853 _mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
    854                  GLint vn, GLfloat v1, GLfloat v2 )
    855 {
    856    GET_CURRENT_CONTEXT(ctx);
    857    ASSERT_OUTSIDE_BEGIN_END(ctx);
    858 
    859    if (un<1) {
    860       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
    861       return;
    862    }
    863    if (vn<1) {
    864       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
    865       return;
    866    }
    867 
    868    FLUSH_VERTICES(ctx, _NEW_EVAL);
    869    ctx->Eval.MapGrid2un = un;
    870    ctx->Eval.MapGrid2u1 = u1;
    871    ctx->Eval.MapGrid2u2 = u2;
    872    ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
    873    ctx->Eval.MapGrid2vn = vn;
    874    ctx->Eval.MapGrid2v1 = v1;
    875    ctx->Eval.MapGrid2v2 = v2;
    876    ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
    877 }
    878 
    879 
    880 static void GLAPIENTRY
    881 _mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
    882                  GLint vn, GLdouble v1, GLdouble v2 )
    883 {
    884    _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
    885 		    vn, (GLfloat) v1, (GLfloat) v2 );
    886 }
    887 
    888 
    889 void
    890 _mesa_install_eval_vtxfmt(struct _glapi_table *disp,
    891                           const GLvertexformat *vfmt)
    892 {
    893    SET_EvalCoord1f(disp, vfmt->EvalCoord1f);
    894    SET_EvalCoord1fv(disp, vfmt->EvalCoord1fv);
    895    SET_EvalCoord2f(disp, vfmt->EvalCoord2f);
    896    SET_EvalCoord2fv(disp, vfmt->EvalCoord2fv);
    897    SET_EvalPoint1(disp, vfmt->EvalPoint1);
    898    SET_EvalPoint2(disp, vfmt->EvalPoint2);
    899 
    900    SET_EvalMesh1(disp, vfmt->EvalMesh1);
    901    SET_EvalMesh2(disp, vfmt->EvalMesh2);
    902 }
    903 
    904 
    905 void
    906 _mesa_init_eval_dispatch(struct _glapi_table *disp)
    907 {
    908    SET_GetMapdv(disp, _mesa_GetMapdv);
    909    SET_GetMapfv(disp, _mesa_GetMapfv);
    910    SET_GetMapiv(disp, _mesa_GetMapiv);
    911    SET_Map1d(disp, _mesa_Map1d);
    912    SET_Map1f(disp, _mesa_Map1f);
    913    SET_Map2d(disp, _mesa_Map2d);
    914    SET_Map2f(disp, _mesa_Map2f);
    915    SET_MapGrid1d(disp, _mesa_MapGrid1d);
    916    SET_MapGrid1f(disp, _mesa_MapGrid1f);
    917    SET_MapGrid2d(disp, _mesa_MapGrid2d);
    918    SET_MapGrid2f(disp, _mesa_MapGrid2f);
    919 
    920    /* GL_ARB_robustness */
    921    SET_GetnMapdvARB(disp, _mesa_GetnMapdvARB);
    922    SET_GetnMapfvARB(disp, _mesa_GetnMapfvARB);
    923    SET_GetnMapivARB(disp, _mesa_GetnMapivARB);
    924 }
    925 
    926 
    927 #endif /* FEATURE_evaluators */
    928 
    929 
    930 /**********************************************************************/
    931 /*****                      Initialization                        *****/
    932 /**********************************************************************/
    933 
    934 /**
    935  * Initialize a 1-D evaluator map.
    936  */
    937 static void
    938 init_1d_map( struct gl_1d_map *map, int n, const float *initial )
    939 {
    940    map->Order = 1;
    941    map->u1 = 0.0;
    942    map->u2 = 1.0;
    943    map->Points = (GLfloat *) MALLOC(n * sizeof(GLfloat));
    944    if (map->Points) {
    945       GLint i;
    946       for (i=0;i<n;i++)
    947          map->Points[i] = initial[i];
    948    }
    949 }
    950 
    951 
    952 /**
    953  * Initialize a 2-D evaluator map
    954  */
    955 static void
    956 init_2d_map( struct gl_2d_map *map, int n, const float *initial )
    957 {
    958    map->Uorder = 1;
    959    map->Vorder = 1;
    960    map->u1 = 0.0;
    961    map->u2 = 1.0;
    962    map->v1 = 0.0;
    963    map->v2 = 1.0;
    964    map->Points = (GLfloat *) MALLOC(n * sizeof(GLfloat));
    965    if (map->Points) {
    966       GLint i;
    967       for (i=0;i<n;i++)
    968          map->Points[i] = initial[i];
    969    }
    970 }
    971 
    972 
    973 void _mesa_init_eval( struct gl_context *ctx )
    974 {
    975    int i;
    976 
    977    /* Evaluators group */
    978    ctx->Eval.Map1Color4 = GL_FALSE;
    979    ctx->Eval.Map1Index = GL_FALSE;
    980    ctx->Eval.Map1Normal = GL_FALSE;
    981    ctx->Eval.Map1TextureCoord1 = GL_FALSE;
    982    ctx->Eval.Map1TextureCoord2 = GL_FALSE;
    983    ctx->Eval.Map1TextureCoord3 = GL_FALSE;
    984    ctx->Eval.Map1TextureCoord4 = GL_FALSE;
    985    ctx->Eval.Map1Vertex3 = GL_FALSE;
    986    ctx->Eval.Map1Vertex4 = GL_FALSE;
    987    memset(ctx->Eval.Map1Attrib, 0, sizeof(ctx->Eval.Map1Attrib));
    988    ctx->Eval.Map2Color4 = GL_FALSE;
    989    ctx->Eval.Map2Index = GL_FALSE;
    990    ctx->Eval.Map2Normal = GL_FALSE;
    991    ctx->Eval.Map2TextureCoord1 = GL_FALSE;
    992    ctx->Eval.Map2TextureCoord2 = GL_FALSE;
    993    ctx->Eval.Map2TextureCoord3 = GL_FALSE;
    994    ctx->Eval.Map2TextureCoord4 = GL_FALSE;
    995    ctx->Eval.Map2Vertex3 = GL_FALSE;
    996    ctx->Eval.Map2Vertex4 = GL_FALSE;
    997    memset(ctx->Eval.Map2Attrib, 0, sizeof(ctx->Eval.Map2Attrib));
    998    ctx->Eval.AutoNormal = GL_FALSE;
    999    ctx->Eval.MapGrid1un = 1;
   1000    ctx->Eval.MapGrid1u1 = 0.0;
   1001    ctx->Eval.MapGrid1u2 = 1.0;
   1002    ctx->Eval.MapGrid2un = 1;
   1003    ctx->Eval.MapGrid2vn = 1;
   1004    ctx->Eval.MapGrid2u1 = 0.0;
   1005    ctx->Eval.MapGrid2u2 = 1.0;
   1006    ctx->Eval.MapGrid2v1 = 0.0;
   1007    ctx->Eval.MapGrid2v2 = 1.0;
   1008 
   1009    /* Evaluator data */
   1010    {
   1011       static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
   1012       static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
   1013       static GLfloat index[1] = { 1.0 };
   1014       static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
   1015       static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
   1016       static GLfloat attrib[4] = { 0.0, 0.0, 0.0, 1.0 };
   1017 
   1018       init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex );
   1019       init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex );
   1020       init_1d_map( &ctx->EvalMap.Map1Index, 1, index );
   1021       init_1d_map( &ctx->EvalMap.Map1Color4, 4, color );
   1022       init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal );
   1023       init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord );
   1024       init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord );
   1025       init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord );
   1026       init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord );
   1027       for (i = 0; i < 16; i++)
   1028          init_1d_map( ctx->EvalMap.Map1Attrib + i, 4, attrib );
   1029 
   1030       init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex );
   1031       init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex );
   1032       init_2d_map( &ctx->EvalMap.Map2Index, 1, index );
   1033       init_2d_map( &ctx->EvalMap.Map2Color4, 4, color );
   1034       init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal );
   1035       init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord );
   1036       init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord );
   1037       init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord );
   1038       init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord );
   1039       for (i = 0; i < 16; i++)
   1040          init_2d_map( ctx->EvalMap.Map2Attrib + i, 4, attrib );
   1041    }
   1042 }
   1043 
   1044 
   1045 void _mesa_free_eval_data( struct gl_context *ctx )
   1046 {
   1047    int i;
   1048 
   1049    /* Free evaluator data */
   1050    if (ctx->EvalMap.Map1Vertex3.Points)
   1051       FREE( ctx->EvalMap.Map1Vertex3.Points );
   1052    if (ctx->EvalMap.Map1Vertex4.Points)
   1053       FREE( ctx->EvalMap.Map1Vertex4.Points );
   1054    if (ctx->EvalMap.Map1Index.Points)
   1055       FREE( ctx->EvalMap.Map1Index.Points );
   1056    if (ctx->EvalMap.Map1Color4.Points)
   1057       FREE( ctx->EvalMap.Map1Color4.Points );
   1058    if (ctx->EvalMap.Map1Normal.Points)
   1059       FREE( ctx->EvalMap.Map1Normal.Points );
   1060    if (ctx->EvalMap.Map1Texture1.Points)
   1061       FREE( ctx->EvalMap.Map1Texture1.Points );
   1062    if (ctx->EvalMap.Map1Texture2.Points)
   1063       FREE( ctx->EvalMap.Map1Texture2.Points );
   1064    if (ctx->EvalMap.Map1Texture3.Points)
   1065       FREE( ctx->EvalMap.Map1Texture3.Points );
   1066    if (ctx->EvalMap.Map1Texture4.Points)
   1067       FREE( ctx->EvalMap.Map1Texture4.Points );
   1068    for (i = 0; i < 16; i++)
   1069       FREE((ctx->EvalMap.Map1Attrib[i].Points));
   1070 
   1071    if (ctx->EvalMap.Map2Vertex3.Points)
   1072       FREE( ctx->EvalMap.Map2Vertex3.Points );
   1073    if (ctx->EvalMap.Map2Vertex4.Points)
   1074       FREE( ctx->EvalMap.Map2Vertex4.Points );
   1075    if (ctx->EvalMap.Map2Index.Points)
   1076       FREE( ctx->EvalMap.Map2Index.Points );
   1077    if (ctx->EvalMap.Map2Color4.Points)
   1078       FREE( ctx->EvalMap.Map2Color4.Points );
   1079    if (ctx->EvalMap.Map2Normal.Points)
   1080       FREE( ctx->EvalMap.Map2Normal.Points );
   1081    if (ctx->EvalMap.Map2Texture1.Points)
   1082       FREE( ctx->EvalMap.Map2Texture1.Points );
   1083    if (ctx->EvalMap.Map2Texture2.Points)
   1084       FREE( ctx->EvalMap.Map2Texture2.Points );
   1085    if (ctx->EvalMap.Map2Texture3.Points)
   1086       FREE( ctx->EvalMap.Map2Texture3.Points );
   1087    if (ctx->EvalMap.Map2Texture4.Points)
   1088       FREE( ctx->EvalMap.Map2Texture4.Points );
   1089    for (i = 0; i < 16; i++)
   1090       FREE((ctx->EvalMap.Map2Attrib[i].Points));
   1091 }
   1092