polygon.c revision cdc920a0
17117f1b4Smrg/**
27117f1b4Smrg * \file polygon.c
37117f1b4Smrg * Polygon operations.
47117f1b4Smrg */
57117f1b4Smrg
67117f1b4Smrg/*
77117f1b4Smrg * Mesa 3-D graphics library
87117f1b4Smrg * Version:  6.5.1
97117f1b4Smrg *
107117f1b4Smrg * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
117117f1b4Smrg *
127117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
137117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
147117f1b4Smrg * to deal in the Software without restriction, including without limitation
157117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
167117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
177117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
187117f1b4Smrg *
197117f1b4Smrg * The above copyright notice and this permission notice shall be included
207117f1b4Smrg * in all copies or substantial portions of the Software.
217117f1b4Smrg *
227117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
237117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
247117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
257117f1b4Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
267117f1b4Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
277117f1b4Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
287117f1b4Smrg */
297117f1b4Smrg
307117f1b4Smrg
317117f1b4Smrg#include "glheader.h"
327117f1b4Smrg#include "imports.h"
337117f1b4Smrg#include "bufferobj.h"
347117f1b4Smrg#include "context.h"
357117f1b4Smrg#include "image.h"
367117f1b4Smrg#include "enums.h"
377117f1b4Smrg#include "polygon.h"
387117f1b4Smrg#include "mtypes.h"
397117f1b4Smrg
407117f1b4Smrg
417117f1b4Smrg/**
427117f1b4Smrg * Specify whether to cull front- or back-facing facets.
437117f1b4Smrg *
447117f1b4Smrg * \param mode culling mode.
457117f1b4Smrg *
467117f1b4Smrg * \sa glCullFace().
477117f1b4Smrg *
487117f1b4Smrg * Verifies the parameter and updates gl_polygon_attrib::CullFaceMode. On
497117f1b4Smrg * change, flushes the vertices and notifies the driver via
507117f1b4Smrg * the dd_function_table::CullFace callback.
517117f1b4Smrg */
527117f1b4Smrgvoid GLAPIENTRY
537117f1b4Smrg_mesa_CullFace( GLenum mode )
547117f1b4Smrg{
557117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
567117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
577117f1b4Smrg
587117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
597117f1b4Smrg      _mesa_debug(ctx, "glCullFace %s\n", _mesa_lookup_enum_by_nr(mode));
607117f1b4Smrg
617117f1b4Smrg   if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) {
627117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glCullFace" );
637117f1b4Smrg      return;
647117f1b4Smrg   }
657117f1b4Smrg
667117f1b4Smrg   if (ctx->Polygon.CullFaceMode == mode)
677117f1b4Smrg      return;
687117f1b4Smrg
697117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_POLYGON);
707117f1b4Smrg   ctx->Polygon.CullFaceMode = mode;
717117f1b4Smrg
727117f1b4Smrg   if (ctx->Driver.CullFace)
737117f1b4Smrg      ctx->Driver.CullFace( ctx, mode );
747117f1b4Smrg}
757117f1b4Smrg
767117f1b4Smrg
777117f1b4Smrg/**
787117f1b4Smrg * Define front- and back-facing
797117f1b4Smrg *
807117f1b4Smrg * \param mode orientation of front-facing polygons.
817117f1b4Smrg *
827117f1b4Smrg * \sa glFrontFace().
837117f1b4Smrg *
847117f1b4Smrg * Verifies the parameter and updates gl_polygon_attrib::FrontFace. On change
857117f1b4Smrg * flushes the vertices and notifies the driver via
867117f1b4Smrg * the dd_function_table::FrontFace callback.
877117f1b4Smrg */
887117f1b4Smrgvoid GLAPIENTRY
897117f1b4Smrg_mesa_FrontFace( GLenum mode )
907117f1b4Smrg{
917117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
927117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
937117f1b4Smrg
947117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
957117f1b4Smrg      _mesa_debug(ctx, "glFrontFace %s\n", _mesa_lookup_enum_by_nr(mode));
967117f1b4Smrg
977117f1b4Smrg   if (mode!=GL_CW && mode!=GL_CCW) {
987117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" );
997117f1b4Smrg      return;
1007117f1b4Smrg   }
1017117f1b4Smrg
1027117f1b4Smrg   if (ctx->Polygon.FrontFace == mode)
1037117f1b4Smrg      return;
1047117f1b4Smrg
1057117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_POLYGON);
1067117f1b4Smrg   ctx->Polygon.FrontFace = mode;
1077117f1b4Smrg
1087117f1b4Smrg   ctx->Polygon._FrontBit = (GLboolean) (mode == GL_CW);
1097117f1b4Smrg
1107117f1b4Smrg   if (ctx->Driver.FrontFace)
1117117f1b4Smrg      ctx->Driver.FrontFace( ctx, mode );
1127117f1b4Smrg}
1137117f1b4Smrg
1147117f1b4Smrg
1157117f1b4Smrg/**
1167117f1b4Smrg * Set the polygon rasterization mode.
1177117f1b4Smrg *
1187117f1b4Smrg * \param face the polygons which \p mode applies to.
1197117f1b4Smrg * \param mode how polygons should be rasterized.
1207117f1b4Smrg *
1217117f1b4Smrg * \sa glPolygonMode().
1227117f1b4Smrg *
1237117f1b4Smrg * Verifies the parameters and updates gl_polygon_attrib::FrontMode and
1247117f1b4Smrg * gl_polygon_attrib::BackMode. On change flushes the vertices and notifies the
1257117f1b4Smrg * driver via the dd_function_table::PolygonMode callback.
1267117f1b4Smrg */
1277117f1b4Smrgvoid GLAPIENTRY
1287117f1b4Smrg_mesa_PolygonMode( GLenum face, GLenum mode )
1297117f1b4Smrg{
1307117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1317117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1327117f1b4Smrg
1337117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
1347117f1b4Smrg      _mesa_debug(ctx, "glPolygonMode %s %s\n",
1357117f1b4Smrg                  _mesa_lookup_enum_by_nr(face),
1367117f1b4Smrg                  _mesa_lookup_enum_by_nr(mode));
1377117f1b4Smrg
1387117f1b4Smrg   if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) {
1397117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" );
1407117f1b4Smrg      return;
1417117f1b4Smrg   }
1427117f1b4Smrg
1437117f1b4Smrg   switch (face) {
1447117f1b4Smrg   case GL_FRONT:
1457117f1b4Smrg      if (ctx->Polygon.FrontMode == mode)
1467117f1b4Smrg	 return;
1477117f1b4Smrg      FLUSH_VERTICES(ctx, _NEW_POLYGON);
1487117f1b4Smrg      ctx->Polygon.FrontMode = mode;
1497117f1b4Smrg      break;
1507117f1b4Smrg   case GL_FRONT_AND_BACK:
1517117f1b4Smrg      if (ctx->Polygon.FrontMode == mode &&
1527117f1b4Smrg	  ctx->Polygon.BackMode == mode)
1537117f1b4Smrg	 return;
1547117f1b4Smrg      FLUSH_VERTICES(ctx, _NEW_POLYGON);
1557117f1b4Smrg      ctx->Polygon.FrontMode = mode;
1567117f1b4Smrg      ctx->Polygon.BackMode = mode;
1577117f1b4Smrg      break;
1587117f1b4Smrg   case GL_BACK:
1597117f1b4Smrg      if (ctx->Polygon.BackMode == mode)
1607117f1b4Smrg	 return;
1617117f1b4Smrg      FLUSH_VERTICES(ctx, _NEW_POLYGON);
1627117f1b4Smrg      ctx->Polygon.BackMode = mode;
1637117f1b4Smrg      break;
1647117f1b4Smrg   default:
1657117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
1667117f1b4Smrg      return;
1677117f1b4Smrg   }
1687117f1b4Smrg
1697117f1b4Smrg   if (ctx->Polygon.FrontMode == GL_FILL && ctx->Polygon.BackMode == GL_FILL)
1707117f1b4Smrg      ctx->_TriangleCaps &= ~DD_TRI_UNFILLED;
1717117f1b4Smrg   else
1727117f1b4Smrg      ctx->_TriangleCaps |= DD_TRI_UNFILLED;
1737117f1b4Smrg
1747117f1b4Smrg   if (ctx->Driver.PolygonMode)
1757117f1b4Smrg      ctx->Driver.PolygonMode(ctx, face, mode);
1767117f1b4Smrg}
1777117f1b4Smrg
1787117f1b4Smrg#if _HAVE_FULL_GL
1797117f1b4Smrg
1807117f1b4Smrg
1817117f1b4Smrg/**
1827117f1b4Smrg * This routine updates the ctx->Polygon.Stipple state.
1837117f1b4Smrg * If we're getting the stipple data from a PBO, we map the buffer
1847117f1b4Smrg * in order to access the data.
1857117f1b4Smrg * In any case, we obey the current pixel unpacking parameters when fetching
1867117f1b4Smrg * the stipple data.
1877117f1b4Smrg *
1887117f1b4Smrg * In the future, this routine should be used as a fallback, called via
1897117f1b4Smrg * ctx->Driver.PolygonStipple().  We'll have to update all the DRI drivers
1907117f1b4Smrg * too.
1917117f1b4Smrg */
1927117f1b4Smrgvoid
1937117f1b4Smrg_mesa_polygon_stipple(GLcontext *ctx, const GLubyte *pattern)
1947117f1b4Smrg{
1954a49301eSmrg   pattern = _mesa_map_validate_pbo_source(ctx, 2,
1964a49301eSmrg                                           &ctx->Unpack, 32, 32, 1,
1974a49301eSmrg                                           GL_COLOR_INDEX, GL_BITMAP, pattern,
1984a49301eSmrg                                           "glPolygonStipple");
1994a49301eSmrg   if (!pattern)
2004a49301eSmrg      return;
2014a49301eSmrg
2024a49301eSmrg   _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack);
2034a49301eSmrg
2044a49301eSmrg   _mesa_unmap_pbo_source(ctx, &ctx->Unpack);
2057117f1b4Smrg}
2067117f1b4Smrg
2077117f1b4Smrg
2087117f1b4Smrg/**
2097117f1b4Smrg * Called by glPolygonStipple.
2107117f1b4Smrg */
2117117f1b4Smrgvoid GLAPIENTRY
2127117f1b4Smrg_mesa_PolygonStipple( const GLubyte *pattern )
2137117f1b4Smrg{
2147117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2157117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
2167117f1b4Smrg
2177117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
2187117f1b4Smrg      _mesa_debug(ctx, "glPolygonStipple\n");
2197117f1b4Smrg
2207117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_POLYGONSTIPPLE);
2217117f1b4Smrg
2227117f1b4Smrg   _mesa_polygon_stipple(ctx, pattern);
2237117f1b4Smrg
2247117f1b4Smrg   if (ctx->Driver.PolygonStipple)
2257117f1b4Smrg      ctx->Driver.PolygonStipple(ctx, pattern);
2267117f1b4Smrg}
2277117f1b4Smrg
2287117f1b4Smrg
2297117f1b4Smrg/**
2307117f1b4Smrg * Called by glPolygonStipple.
2317117f1b4Smrg */
2327117f1b4Smrgvoid GLAPIENTRY
2337117f1b4Smrg_mesa_GetPolygonStipple( GLubyte *dest )
2347117f1b4Smrg{
2357117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2367117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
2377117f1b4Smrg
2387117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
2397117f1b4Smrg      _mesa_debug(ctx, "glGetPolygonStipple\n");
2407117f1b4Smrg
2414a49301eSmrg   dest = _mesa_map_validate_pbo_dest(ctx, 2,
2424a49301eSmrg                                      &ctx->Pack, 32, 32, 1,
2434a49301eSmrg                                      GL_COLOR_INDEX, GL_BITMAP, dest,
2444a49301eSmrg                                      "glGetPolygonStipple");
2454a49301eSmrg   if (!dest)
2464a49301eSmrg      return;
2474a49301eSmrg
2484a49301eSmrg   _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack);
2494a49301eSmrg
2504a49301eSmrg   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
2517117f1b4Smrg}
2527117f1b4Smrg
2537117f1b4Smrg
2547117f1b4Smrgvoid GLAPIENTRY
2557117f1b4Smrg_mesa_PolygonOffset( GLfloat factor, GLfloat units )
2567117f1b4Smrg{
2577117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2587117f1b4Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
2597117f1b4Smrg
2607117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
2617117f1b4Smrg      _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units);
2627117f1b4Smrg
2637117f1b4Smrg   if (ctx->Polygon.OffsetFactor == factor &&
2647117f1b4Smrg       ctx->Polygon.OffsetUnits == units)
2657117f1b4Smrg      return;
2667117f1b4Smrg
2677117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_POLYGON);
2687117f1b4Smrg   ctx->Polygon.OffsetFactor = factor;
2697117f1b4Smrg   ctx->Polygon.OffsetUnits = units;
2707117f1b4Smrg
2717117f1b4Smrg   if (ctx->Driver.PolygonOffset)
2727117f1b4Smrg      ctx->Driver.PolygonOffset( ctx, factor, units );
2737117f1b4Smrg}
2747117f1b4Smrg
2757117f1b4Smrg
2767117f1b4Smrgvoid GLAPIENTRY
2777117f1b4Smrg_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias )
2787117f1b4Smrg{
2797117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2807117f1b4Smrg   /* XXX mult by DepthMaxF here??? */
2817117f1b4Smrg   _mesa_PolygonOffset(factor, bias * ctx->DrawBuffer->_DepthMaxF );
2827117f1b4Smrg}
2837117f1b4Smrg
2847117f1b4Smrg#endif
2857117f1b4Smrg
2867117f1b4Smrg
2877117f1b4Smrg/**********************************************************************/
2887117f1b4Smrg/** \name Initialization */
2897117f1b4Smrg/*@{*/
2907117f1b4Smrg
2917117f1b4Smrg/**
2927117f1b4Smrg * Initialize the context polygon state.
2937117f1b4Smrg *
2947117f1b4Smrg * \param ctx GL context.
2957117f1b4Smrg *
2967117f1b4Smrg * Initializes __GLcontextRec::Polygon and __GLcontextRec::PolygonStipple
2977117f1b4Smrg * attribute groups.
2987117f1b4Smrg */
2997117f1b4Smrgvoid _mesa_init_polygon( GLcontext * ctx )
3007117f1b4Smrg{
3017117f1b4Smrg   /* Polygon group */
3027117f1b4Smrg   ctx->Polygon.CullFlag = GL_FALSE;
3037117f1b4Smrg   ctx->Polygon.CullFaceMode = GL_BACK;
3047117f1b4Smrg   ctx->Polygon.FrontFace = GL_CCW;
3057117f1b4Smrg   ctx->Polygon._FrontBit = 0;
3067117f1b4Smrg   ctx->Polygon.FrontMode = GL_FILL;
3077117f1b4Smrg   ctx->Polygon.BackMode = GL_FILL;
3087117f1b4Smrg   ctx->Polygon.SmoothFlag = GL_FALSE;
3097117f1b4Smrg   ctx->Polygon.StippleFlag = GL_FALSE;
3107117f1b4Smrg   ctx->Polygon.OffsetFactor = 0.0F;
3117117f1b4Smrg   ctx->Polygon.OffsetUnits = 0.0F;
3127117f1b4Smrg   ctx->Polygon.OffsetPoint = GL_FALSE;
3137117f1b4Smrg   ctx->Polygon.OffsetLine = GL_FALSE;
3147117f1b4Smrg   ctx->Polygon.OffsetFill = GL_FALSE;
3157117f1b4Smrg
3167117f1b4Smrg
3177117f1b4Smrg   /* Polygon Stipple group */
318cdc920a0Smrg   memset( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) );
3197117f1b4Smrg}
3207117f1b4Smrg
3217117f1b4Smrg/*@}*/
322