Home | History | Annotate | Download | only in main
      1 /**
      2  * \file polygon.c
      3  * Polygon operations.
      4  */
      5 
      6 /*
      7  * Mesa 3-D graphics library
      8  * Version:  6.5.1
      9  *
     10  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
     11  *
     12  * Permission is hereby granted, free of charge, to any person obtaining a
     13  * copy of this software and associated documentation files (the "Software"),
     14  * to deal in the Software without restriction, including without limitation
     15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     16  * and/or sell copies of the Software, and to permit persons to whom the
     17  * Software is furnished to do so, subject to the following conditions:
     18  *
     19  * The above copyright notice and this permission notice shall be included
     20  * in all copies or substantial portions of the Software.
     21  *
     22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     25  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     26  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     28  */
     29 
     30 
     31 #include "glheader.h"
     32 #include "imports.h"
     33 #include "context.h"
     34 #include "image.h"
     35 #include "enums.h"
     36 #include "pack.h"
     37 #include "pbo.h"
     38 #include "polygon.h"
     39 #include "mtypes.h"
     40 
     41 
     42 /**
     43  * Specify whether to cull front- or back-facing facets.
     44  *
     45  * \param mode culling mode.
     46  *
     47  * \sa glCullFace().
     48  *
     49  * Verifies the parameter and updates gl_polygon_attrib::CullFaceMode. On
     50  * change, flushes the vertices and notifies the driver via
     51  * the dd_function_table::CullFace callback.
     52  */
     53 void GLAPIENTRY
     54 _mesa_CullFace( GLenum mode )
     55 {
     56    GET_CURRENT_CONTEXT(ctx);
     57    ASSERT_OUTSIDE_BEGIN_END(ctx);
     58 
     59    if (MESA_VERBOSE&VERBOSE_API)
     60       _mesa_debug(ctx, "glCullFace %s\n", _mesa_lookup_enum_by_nr(mode));
     61 
     62    if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) {
     63       _mesa_error( ctx, GL_INVALID_ENUM, "glCullFace" );
     64       return;
     65    }
     66 
     67    if (ctx->Polygon.CullFaceMode == mode)
     68       return;
     69 
     70    FLUSH_VERTICES(ctx, _NEW_POLYGON);
     71    ctx->Polygon.CullFaceMode = mode;
     72 
     73    if (ctx->Driver.CullFace)
     74       ctx->Driver.CullFace( ctx, mode );
     75 }
     76 
     77 
     78 /**
     79  * Define front- and back-facing
     80  *
     81  * \param mode orientation of front-facing polygons.
     82  *
     83  * \sa glFrontFace().
     84  *
     85  * Verifies the parameter and updates gl_polygon_attrib::FrontFace. On change
     86  * flushes the vertices and notifies the driver via
     87  * the dd_function_table::FrontFace callback.
     88  */
     89 void GLAPIENTRY
     90 _mesa_FrontFace( GLenum mode )
     91 {
     92    GET_CURRENT_CONTEXT(ctx);
     93    ASSERT_OUTSIDE_BEGIN_END(ctx);
     94 
     95    if (MESA_VERBOSE&VERBOSE_API)
     96       _mesa_debug(ctx, "glFrontFace %s\n", _mesa_lookup_enum_by_nr(mode));
     97 
     98    if (mode!=GL_CW && mode!=GL_CCW) {
     99       _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" );
    100       return;
    101    }
    102 
    103    if (ctx->Polygon.FrontFace == mode)
    104       return;
    105 
    106    FLUSH_VERTICES(ctx, _NEW_POLYGON);
    107    ctx->Polygon.FrontFace = mode;
    108 
    109    ctx->Polygon._FrontBit = (GLboolean) (mode == GL_CW);
    110 
    111    if (ctx->Driver.FrontFace)
    112       ctx->Driver.FrontFace( ctx, mode );
    113 }
    114 
    115 
    116 /**
    117  * Set the polygon rasterization mode.
    118  *
    119  * \param face the polygons which \p mode applies to.
    120  * \param mode how polygons should be rasterized.
    121  *
    122  * \sa glPolygonMode().
    123  *
    124  * Verifies the parameters and updates gl_polygon_attrib::FrontMode and
    125  * gl_polygon_attrib::BackMode. On change flushes the vertices and notifies the
    126  * driver via the dd_function_table::PolygonMode callback.
    127  */
    128 void GLAPIENTRY
    129 _mesa_PolygonMode( GLenum face, GLenum mode )
    130 {
    131    GET_CURRENT_CONTEXT(ctx);
    132    ASSERT_OUTSIDE_BEGIN_END(ctx);
    133 
    134    if (MESA_VERBOSE&VERBOSE_API)
    135       _mesa_debug(ctx, "glPolygonMode %s %s\n",
    136                   _mesa_lookup_enum_by_nr(face),
    137                   _mesa_lookup_enum_by_nr(mode));
    138 
    139    if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) {
    140       _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" );
    141       return;
    142    }
    143 
    144    switch (face) {
    145    case GL_FRONT:
    146       if (ctx->API == API_OPENGL_CORE) {
    147          _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
    148          return;
    149       }
    150       if (ctx->Polygon.FrontMode == mode)
    151 	 return;
    152       FLUSH_VERTICES(ctx, _NEW_POLYGON);
    153       ctx->Polygon.FrontMode = mode;
    154       break;
    155    case GL_FRONT_AND_BACK:
    156       if (ctx->Polygon.FrontMode == mode &&
    157 	  ctx->Polygon.BackMode == mode)
    158 	 return;
    159       FLUSH_VERTICES(ctx, _NEW_POLYGON);
    160       ctx->Polygon.FrontMode = mode;
    161       ctx->Polygon.BackMode = mode;
    162       break;
    163    case GL_BACK:
    164       if (ctx->API == API_OPENGL_CORE) {
    165          _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
    166          return;
    167       }
    168       if (ctx->Polygon.BackMode == mode)
    169 	 return;
    170       FLUSH_VERTICES(ctx, _NEW_POLYGON);
    171       ctx->Polygon.BackMode = mode;
    172       break;
    173    default:
    174       _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
    175       return;
    176    }
    177 
    178    if (ctx->Polygon.FrontMode == GL_FILL && ctx->Polygon.BackMode == GL_FILL)
    179       ctx->_TriangleCaps &= ~DD_TRI_UNFILLED;
    180    else
    181       ctx->_TriangleCaps |= DD_TRI_UNFILLED;
    182 
    183    if (ctx->Driver.PolygonMode)
    184       ctx->Driver.PolygonMode(ctx, face, mode);
    185 }
    186 
    187 #if _HAVE_FULL_GL
    188 
    189 
    190 /**
    191  * This routine updates the ctx->Polygon.Stipple state.
    192  * If we're getting the stipple data from a PBO, we map the buffer
    193  * in order to access the data.
    194  * In any case, we obey the current pixel unpacking parameters when fetching
    195  * the stipple data.
    196  *
    197  * In the future, this routine should be used as a fallback, called via
    198  * ctx->Driver.PolygonStipple().  We'll have to update all the DRI drivers
    199  * too.
    200  */
    201 void
    202 _mesa_polygon_stipple(struct gl_context *ctx, const GLubyte *pattern)
    203 {
    204    pattern = _mesa_map_validate_pbo_source(ctx, 2,
    205                                            &ctx->Unpack, 32, 32, 1,
    206                                            GL_COLOR_INDEX, GL_BITMAP,
    207                                            INT_MAX, pattern,
    208                                            "glPolygonStipple");
    209    if (!pattern)
    210       return;
    211 
    212    _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack);
    213 
    214    _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
    215 }
    216 
    217 
    218 /**
    219  * Called by glPolygonStipple.
    220  */
    221 void GLAPIENTRY
    222 _mesa_PolygonStipple( const GLubyte *pattern )
    223 {
    224    GET_CURRENT_CONTEXT(ctx);
    225    ASSERT_OUTSIDE_BEGIN_END(ctx);
    226 
    227    if (MESA_VERBOSE&VERBOSE_API)
    228       _mesa_debug(ctx, "glPolygonStipple\n");
    229 
    230    FLUSH_VERTICES(ctx, _NEW_POLYGONSTIPPLE);
    231 
    232    _mesa_polygon_stipple(ctx, pattern);
    233 
    234    if (ctx->Driver.PolygonStipple)
    235       ctx->Driver.PolygonStipple(ctx, pattern);
    236 }
    237 
    238 
    239 /**
    240  * Called by glPolygonStipple.
    241  */
    242 void GLAPIENTRY
    243 _mesa_GetnPolygonStippleARB( GLsizei bufSize, GLubyte *dest )
    244 {
    245    GET_CURRENT_CONTEXT(ctx);
    246    ASSERT_OUTSIDE_BEGIN_END(ctx);
    247 
    248    if (MESA_VERBOSE&VERBOSE_API)
    249       _mesa_debug(ctx, "glGetPolygonStipple\n");
    250 
    251    dest = _mesa_map_validate_pbo_dest(ctx, 2,
    252                                       &ctx->Pack, 32, 32, 1,
    253                                       GL_COLOR_INDEX, GL_BITMAP,
    254                                       bufSize, dest, "glGetPolygonStipple");
    255    if (!dest)
    256       return;
    257 
    258    _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack);
    259 
    260    _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
    261 }
    262 
    263 
    264 void GLAPIENTRY
    265 _mesa_GetPolygonStipple( GLubyte *dest )
    266 {
    267    _mesa_GetnPolygonStippleARB(INT_MAX, dest);
    268 }
    269 
    270 
    271 void GLAPIENTRY
    272 _mesa_PolygonOffset( GLfloat factor, GLfloat units )
    273 {
    274    GET_CURRENT_CONTEXT(ctx);
    275    ASSERT_OUTSIDE_BEGIN_END(ctx);
    276 
    277    if (MESA_VERBOSE&VERBOSE_API)
    278       _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units);
    279 
    280    if (ctx->Polygon.OffsetFactor == factor &&
    281        ctx->Polygon.OffsetUnits == units)
    282       return;
    283 
    284    FLUSH_VERTICES(ctx, _NEW_POLYGON);
    285    ctx->Polygon.OffsetFactor = factor;
    286    ctx->Polygon.OffsetUnits = units;
    287 
    288    if (ctx->Driver.PolygonOffset)
    289       ctx->Driver.PolygonOffset( ctx, factor, units );
    290 }
    291 
    292 
    293 void GLAPIENTRY
    294 _mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias )
    295 {
    296    GET_CURRENT_CONTEXT(ctx);
    297    /* XXX mult by DepthMaxF here??? */
    298    _mesa_PolygonOffset(factor, bias * ctx->DrawBuffer->_DepthMaxF );
    299 }
    300 
    301 #endif
    302 
    303 
    304 /**********************************************************************/
    305 /** \name Initialization */
    306 /*@{*/
    307 
    308 /**
    309  * Initialize the context polygon state.
    310  *
    311  * \param ctx GL context.
    312  *
    313  * Initializes __struct gl_contextRec::Polygon and __struct gl_contextRec::PolygonStipple
    314  * attribute groups.
    315  */
    316 void _mesa_init_polygon( struct gl_context * ctx )
    317 {
    318    /* Polygon group */
    319    ctx->Polygon.CullFlag = GL_FALSE;
    320    ctx->Polygon.CullFaceMode = GL_BACK;
    321    ctx->Polygon.FrontFace = GL_CCW;
    322    ctx->Polygon._FrontBit = 0;
    323    ctx->Polygon.FrontMode = GL_FILL;
    324    ctx->Polygon.BackMode = GL_FILL;
    325    ctx->Polygon.SmoothFlag = GL_FALSE;
    326    ctx->Polygon.StippleFlag = GL_FALSE;
    327    ctx->Polygon.OffsetFactor = 0.0F;
    328    ctx->Polygon.OffsetUnits = 0.0F;
    329    ctx->Polygon.OffsetPoint = GL_FALSE;
    330    ctx->Polygon.OffsetLine = GL_FALSE;
    331    ctx->Polygon.OffsetFill = GL_FALSE;
    332 
    333 
    334    /* Polygon Stipple group */
    335    memset( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) );
    336 }
    337 
    338 /*@}*/
    339