polygon.c revision af69d88d
17117f1b4Smrg/**
27117f1b4Smrg * \file polygon.c
37117f1b4Smrg * Polygon operations.
47117f1b4Smrg */
57117f1b4Smrg
67117f1b4Smrg/*
77117f1b4Smrg * Mesa 3-D graphics library
87117f1b4Smrg *
97117f1b4Smrg * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
107117f1b4Smrg *
117117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
127117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
137117f1b4Smrg * to deal in the Software without restriction, including without limitation
147117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
157117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
167117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
177117f1b4Smrg *
187117f1b4Smrg * The above copyright notice and this permission notice shall be included
197117f1b4Smrg * in all copies or substantial portions of the Software.
207117f1b4Smrg *
217117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
227117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
237117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
287117f1b4Smrg */
297117f1b4Smrg
307117f1b4Smrg
317117f1b4Smrg#include "glheader.h"
327117f1b4Smrg#include "imports.h"
337117f1b4Smrg#include "context.h"
347117f1b4Smrg#include "image.h"
357117f1b4Smrg#include "enums.h"
363464ebd5Sriastradh#include "pack.h"
373464ebd5Sriastradh#include "pbo.h"
387117f1b4Smrg#include "polygon.h"
397117f1b4Smrg#include "mtypes.h"
407117f1b4Smrg
417117f1b4Smrg
427117f1b4Smrg/**
437117f1b4Smrg * Specify whether to cull front- or back-facing facets.
447117f1b4Smrg *
457117f1b4Smrg * \param mode culling mode.
467117f1b4Smrg *
477117f1b4Smrg * \sa glCullFace().
487117f1b4Smrg *
497117f1b4Smrg * Verifies the parameter and updates gl_polygon_attrib::CullFaceMode. On
507117f1b4Smrg * change, flushes the vertices and notifies the driver via
517117f1b4Smrg * the dd_function_table::CullFace callback.
527117f1b4Smrg */
537117f1b4Smrgvoid GLAPIENTRY
547117f1b4Smrg_mesa_CullFace( GLenum mode )
557117f1b4Smrg{
567117f1b4Smrg   GET_CURRENT_CONTEXT(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
937117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
947117f1b4Smrg      _mesa_debug(ctx, "glFrontFace %s\n", _mesa_lookup_enum_by_nr(mode));
957117f1b4Smrg
967117f1b4Smrg   if (mode!=GL_CW && mode!=GL_CCW) {
977117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" );
987117f1b4Smrg      return;
997117f1b4Smrg   }
1007117f1b4Smrg
1017117f1b4Smrg   if (ctx->Polygon.FrontFace == mode)
1027117f1b4Smrg      return;
1037117f1b4Smrg
1047117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_POLYGON);
1057117f1b4Smrg   ctx->Polygon.FrontFace = mode;
1067117f1b4Smrg
1077117f1b4Smrg   ctx->Polygon._FrontBit = (GLboolean) (mode == GL_CW);
1087117f1b4Smrg
1097117f1b4Smrg   if (ctx->Driver.FrontFace)
1107117f1b4Smrg      ctx->Driver.FrontFace( ctx, mode );
1117117f1b4Smrg}
1127117f1b4Smrg
1137117f1b4Smrg
1147117f1b4Smrg/**
1157117f1b4Smrg * Set the polygon rasterization mode.
1167117f1b4Smrg *
1177117f1b4Smrg * \param face the polygons which \p mode applies to.
1187117f1b4Smrg * \param mode how polygons should be rasterized.
1197117f1b4Smrg *
1207117f1b4Smrg * \sa glPolygonMode().
1217117f1b4Smrg *
1227117f1b4Smrg * Verifies the parameters and updates gl_polygon_attrib::FrontMode and
1237117f1b4Smrg * gl_polygon_attrib::BackMode. On change flushes the vertices and notifies the
1247117f1b4Smrg * driver via the dd_function_table::PolygonMode callback.
1257117f1b4Smrg */
1267117f1b4Smrgvoid GLAPIENTRY
1277117f1b4Smrg_mesa_PolygonMode( GLenum face, GLenum mode )
1287117f1b4Smrg{
1297117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1307117f1b4Smrg
1317117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
1327117f1b4Smrg      _mesa_debug(ctx, "glPolygonMode %s %s\n",
1337117f1b4Smrg                  _mesa_lookup_enum_by_nr(face),
1347117f1b4Smrg                  _mesa_lookup_enum_by_nr(mode));
1357117f1b4Smrg
1367117f1b4Smrg   if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) {
1377117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" );
1387117f1b4Smrg      return;
1397117f1b4Smrg   }
1407117f1b4Smrg
1417117f1b4Smrg   switch (face) {
1427117f1b4Smrg   case GL_FRONT:
143af69d88dSmrg      if (ctx->API == API_OPENGL_CORE) {
144af69d88dSmrg         _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
145af69d88dSmrg         return;
146af69d88dSmrg      }
1477117f1b4Smrg      if (ctx->Polygon.FrontMode == mode)
1487117f1b4Smrg	 return;
1497117f1b4Smrg      FLUSH_VERTICES(ctx, _NEW_POLYGON);
1507117f1b4Smrg      ctx->Polygon.FrontMode = mode;
1517117f1b4Smrg      break;
1527117f1b4Smrg   case GL_FRONT_AND_BACK:
1537117f1b4Smrg      if (ctx->Polygon.FrontMode == mode &&
1547117f1b4Smrg	  ctx->Polygon.BackMode == mode)
1557117f1b4Smrg	 return;
1567117f1b4Smrg      FLUSH_VERTICES(ctx, _NEW_POLYGON);
1577117f1b4Smrg      ctx->Polygon.FrontMode = mode;
1587117f1b4Smrg      ctx->Polygon.BackMode = mode;
1597117f1b4Smrg      break;
1607117f1b4Smrg   case GL_BACK:
161af69d88dSmrg      if (ctx->API == API_OPENGL_CORE) {
162af69d88dSmrg         _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
163af69d88dSmrg         return;
164af69d88dSmrg      }
1657117f1b4Smrg      if (ctx->Polygon.BackMode == mode)
1667117f1b4Smrg	 return;
1677117f1b4Smrg      FLUSH_VERTICES(ctx, _NEW_POLYGON);
1687117f1b4Smrg      ctx->Polygon.BackMode = mode;
1697117f1b4Smrg      break;
1707117f1b4Smrg   default:
1717117f1b4Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
1727117f1b4Smrg      return;
1737117f1b4Smrg   }
1747117f1b4Smrg
1757117f1b4Smrg   if (ctx->Driver.PolygonMode)
1767117f1b4Smrg      ctx->Driver.PolygonMode(ctx, face, mode);
1777117f1b4Smrg}
1787117f1b4Smrg
1797117f1b4Smrg
1807117f1b4Smrg/**
1817117f1b4Smrg * This routine updates the ctx->Polygon.Stipple state.
1827117f1b4Smrg * If we're getting the stipple data from a PBO, we map the buffer
1837117f1b4Smrg * in order to access the data.
1847117f1b4Smrg * In any case, we obey the current pixel unpacking parameters when fetching
1857117f1b4Smrg * the stipple data.
1867117f1b4Smrg *
1877117f1b4Smrg * In the future, this routine should be used as a fallback, called via
1887117f1b4Smrg * ctx->Driver.PolygonStipple().  We'll have to update all the DRI drivers
1897117f1b4Smrg * too.
1907117f1b4Smrg */
1917117f1b4Smrgvoid
1923464ebd5Sriastradh_mesa_polygon_stipple(struct gl_context *ctx, const GLubyte *pattern)
1937117f1b4Smrg{
1944a49301eSmrg   pattern = _mesa_map_validate_pbo_source(ctx, 2,
1954a49301eSmrg                                           &ctx->Unpack, 32, 32, 1,
1963464ebd5Sriastradh                                           GL_COLOR_INDEX, GL_BITMAP,
1973464ebd5Sriastradh                                           INT_MAX, 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
2167117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
2177117f1b4Smrg      _mesa_debug(ctx, "glPolygonStipple\n");
2187117f1b4Smrg
2197117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_POLYGONSTIPPLE);
2207117f1b4Smrg
2217117f1b4Smrg   _mesa_polygon_stipple(ctx, pattern);
2227117f1b4Smrg
2237117f1b4Smrg   if (ctx->Driver.PolygonStipple)
2247117f1b4Smrg      ctx->Driver.PolygonStipple(ctx, pattern);
2257117f1b4Smrg}
2267117f1b4Smrg
2277117f1b4Smrg
2287117f1b4Smrg/**
2297117f1b4Smrg * Called by glPolygonStipple.
2307117f1b4Smrg */
2317117f1b4Smrgvoid GLAPIENTRY
2323464ebd5Sriastradh_mesa_GetnPolygonStippleARB( GLsizei bufSize, GLubyte *dest )
2337117f1b4Smrg{
2347117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2357117f1b4Smrg
2367117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
2377117f1b4Smrg      _mesa_debug(ctx, "glGetPolygonStipple\n");
2387117f1b4Smrg
2394a49301eSmrg   dest = _mesa_map_validate_pbo_dest(ctx, 2,
2404a49301eSmrg                                      &ctx->Pack, 32, 32, 1,
2413464ebd5Sriastradh                                      GL_COLOR_INDEX, GL_BITMAP,
2423464ebd5Sriastradh                                      bufSize, dest, "glGetPolygonStipple");
2434a49301eSmrg   if (!dest)
2444a49301eSmrg      return;
2454a49301eSmrg
2464a49301eSmrg   _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack);
2474a49301eSmrg
2484a49301eSmrg   _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
2497117f1b4Smrg}
2507117f1b4Smrg
2517117f1b4Smrg
2523464ebd5Sriastradhvoid GLAPIENTRY
2533464ebd5Sriastradh_mesa_GetPolygonStipple( GLubyte *dest )
2543464ebd5Sriastradh{
2553464ebd5Sriastradh   _mesa_GetnPolygonStippleARB(INT_MAX, dest);
2563464ebd5Sriastradh}
2573464ebd5Sriastradh
2583464ebd5Sriastradh
2597117f1b4Smrgvoid GLAPIENTRY
2607117f1b4Smrg_mesa_PolygonOffset( GLfloat factor, GLfloat units )
2617117f1b4Smrg{
2627117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2637117f1b4Smrg
2647117f1b4Smrg   if (MESA_VERBOSE&VERBOSE_API)
2657117f1b4Smrg      _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units);
2667117f1b4Smrg
2677117f1b4Smrg   if (ctx->Polygon.OffsetFactor == factor &&
2687117f1b4Smrg       ctx->Polygon.OffsetUnits == units)
2697117f1b4Smrg      return;
2707117f1b4Smrg
2717117f1b4Smrg   FLUSH_VERTICES(ctx, _NEW_POLYGON);
2727117f1b4Smrg   ctx->Polygon.OffsetFactor = factor;
2737117f1b4Smrg   ctx->Polygon.OffsetUnits = units;
2747117f1b4Smrg
2757117f1b4Smrg   if (ctx->Driver.PolygonOffset)
2767117f1b4Smrg      ctx->Driver.PolygonOffset( ctx, factor, units );
2777117f1b4Smrg}
2787117f1b4Smrg
2797117f1b4Smrg
2807117f1b4Smrgvoid GLAPIENTRY
2817117f1b4Smrg_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias )
2827117f1b4Smrg{
2837117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2847117f1b4Smrg   /* XXX mult by DepthMaxF here??? */
2857117f1b4Smrg   _mesa_PolygonOffset(factor, bias * ctx->DrawBuffer->_DepthMaxF );
2867117f1b4Smrg}
2877117f1b4Smrg
2887117f1b4Smrg
2897117f1b4Smrg
2907117f1b4Smrg/**********************************************************************/
2917117f1b4Smrg/** \name Initialization */
2927117f1b4Smrg/*@{*/
2937117f1b4Smrg
2947117f1b4Smrg/**
2957117f1b4Smrg * Initialize the context polygon state.
2967117f1b4Smrg *
2977117f1b4Smrg * \param ctx GL context.
2987117f1b4Smrg *
2993464ebd5Sriastradh * Initializes __struct gl_contextRec::Polygon and __struct gl_contextRec::PolygonStipple
3007117f1b4Smrg * attribute groups.
3017117f1b4Smrg */
3023464ebd5Sriastradhvoid _mesa_init_polygon( struct gl_context * ctx )
3037117f1b4Smrg{
3047117f1b4Smrg   /* Polygon group */
3057117f1b4Smrg   ctx->Polygon.CullFlag = GL_FALSE;
3067117f1b4Smrg   ctx->Polygon.CullFaceMode = GL_BACK;
3077117f1b4Smrg   ctx->Polygon.FrontFace = GL_CCW;
3087117f1b4Smrg   ctx->Polygon._FrontBit = 0;
3097117f1b4Smrg   ctx->Polygon.FrontMode = GL_FILL;
3107117f1b4Smrg   ctx->Polygon.BackMode = GL_FILL;
3117117f1b4Smrg   ctx->Polygon.SmoothFlag = GL_FALSE;
3127117f1b4Smrg   ctx->Polygon.StippleFlag = GL_FALSE;
3137117f1b4Smrg   ctx->Polygon.OffsetFactor = 0.0F;
3147117f1b4Smrg   ctx->Polygon.OffsetUnits = 0.0F;
3157117f1b4Smrg   ctx->Polygon.OffsetPoint = GL_FALSE;
3167117f1b4Smrg   ctx->Polygon.OffsetLine = GL_FALSE;
3177117f1b4Smrg   ctx->Polygon.OffsetFill = GL_FALSE;
3187117f1b4Smrg
3197117f1b4Smrg
3207117f1b4Smrg   /* Polygon Stipple group */
321cdc920a0Smrg   memset( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) );
3227117f1b4Smrg}
3237117f1b4Smrg
3247117f1b4Smrg/*@}*/
325