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