polygon.c revision 01e04c3f
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 */ 5301e04c3fSmrgstatic ALWAYS_INLINE void 5401e04c3fSmrgcull_face(struct gl_context *ctx, GLenum mode, bool no_error) 557117f1b4Smrg{ 5601e04c3fSmrg if (ctx->Polygon.CullFaceMode == mode) 577117f1b4Smrg return; 587117f1b4Smrg 5901e04c3fSmrg if (!no_error && 6001e04c3fSmrg mode != GL_FRONT && mode != GL_BACK && mode != GL_FRONT_AND_BACK) { 6101e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glCullFace"); 627117f1b4Smrg return; 6301e04c3fSmrg } 647117f1b4Smrg 6501e04c3fSmrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewPolygonState ? 0 : _NEW_POLYGON); 6601e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewPolygonState; 677117f1b4Smrg ctx->Polygon.CullFaceMode = mode; 687117f1b4Smrg 697117f1b4Smrg if (ctx->Driver.CullFace) 7001e04c3fSmrg ctx->Driver.CullFace(ctx, mode); 7101e04c3fSmrg} 7201e04c3fSmrg 7301e04c3fSmrg 7401e04c3fSmrgvoid GLAPIENTRY 7501e04c3fSmrg_mesa_CullFace_no_error(GLenum mode) 7601e04c3fSmrg{ 7701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 7801e04c3fSmrg cull_face(ctx, mode, true); 7901e04c3fSmrg} 8001e04c3fSmrg 8101e04c3fSmrg 8201e04c3fSmrgvoid GLAPIENTRY 8301e04c3fSmrg_mesa_CullFace(GLenum mode) 8401e04c3fSmrg{ 8501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 8601e04c3fSmrg 8701e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 8801e04c3fSmrg _mesa_debug(ctx, "glCullFace %s\n", _mesa_enum_to_string(mode)); 8901e04c3fSmrg 9001e04c3fSmrg cull_face(ctx, mode, false); 917117f1b4Smrg} 927117f1b4Smrg 937117f1b4Smrg 947117f1b4Smrg/** 9501e04c3fSmrg * Define front- and back-facing 967117f1b4Smrg * 977117f1b4Smrg * \param mode orientation of front-facing polygons. 987117f1b4Smrg * 997117f1b4Smrg * \sa glFrontFace(). 1007117f1b4Smrg * 1017117f1b4Smrg * Verifies the parameter and updates gl_polygon_attrib::FrontFace. On change 1027117f1b4Smrg * flushes the vertices and notifies the driver via 1037117f1b4Smrg * the dd_function_table::FrontFace callback. 1047117f1b4Smrg */ 10501e04c3fSmrgstatic ALWAYS_INLINE void 10601e04c3fSmrgfront_face(struct gl_context *ctx, GLenum mode, bool no_error) 1077117f1b4Smrg{ 10801e04c3fSmrg if (ctx->Polygon.FrontFace == mode) 1097117f1b4Smrg return; 1107117f1b4Smrg 11101e04c3fSmrg if (!no_error && mode != GL_CW && mode != GL_CCW) { 11201e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glFrontFace"); 1137117f1b4Smrg return; 11401e04c3fSmrg } 1157117f1b4Smrg 11601e04c3fSmrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewPolygonState ? 0 : _NEW_POLYGON); 11701e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewPolygonState; 1187117f1b4Smrg ctx->Polygon.FrontFace = mode; 1197117f1b4Smrg 1207117f1b4Smrg if (ctx->Driver.FrontFace) 12101e04c3fSmrg ctx->Driver.FrontFace(ctx, mode); 12201e04c3fSmrg} 12301e04c3fSmrg 12401e04c3fSmrg 12501e04c3fSmrgvoid GLAPIENTRY 12601e04c3fSmrg_mesa_FrontFace_no_error(GLenum mode) 12701e04c3fSmrg{ 12801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 12901e04c3fSmrg front_face(ctx, mode, true); 13001e04c3fSmrg} 13101e04c3fSmrg 13201e04c3fSmrg 13301e04c3fSmrgvoid GLAPIENTRY 13401e04c3fSmrg_mesa_FrontFace(GLenum mode) 13501e04c3fSmrg{ 13601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 13701e04c3fSmrg 13801e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 13901e04c3fSmrg _mesa_debug(ctx, "glFrontFace %s\n", _mesa_enum_to_string(mode)); 14001e04c3fSmrg 14101e04c3fSmrg front_face(ctx, mode, false); 1427117f1b4Smrg} 1437117f1b4Smrg 1447117f1b4Smrg 1457117f1b4Smrg/** 1467117f1b4Smrg * Set the polygon rasterization mode. 1477117f1b4Smrg * 1487117f1b4Smrg * \param face the polygons which \p mode applies to. 1497117f1b4Smrg * \param mode how polygons should be rasterized. 1507117f1b4Smrg * 15101e04c3fSmrg * \sa glPolygonMode(). 15201e04c3fSmrg * 1537117f1b4Smrg * Verifies the parameters and updates gl_polygon_attrib::FrontMode and 1547117f1b4Smrg * gl_polygon_attrib::BackMode. On change flushes the vertices and notifies the 1557117f1b4Smrg * driver via the dd_function_table::PolygonMode callback. 1567117f1b4Smrg */ 15701e04c3fSmrgstatic ALWAYS_INLINE void 15801e04c3fSmrgpolygon_mode(struct gl_context *ctx, GLenum face, GLenum mode, bool no_error) 1597117f1b4Smrg{ 16001e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 1617117f1b4Smrg _mesa_debug(ctx, "glPolygonMode %s %s\n", 16201e04c3fSmrg _mesa_enum_to_string(face), 16301e04c3fSmrg _mesa_enum_to_string(mode)); 16401e04c3fSmrg 16501e04c3fSmrg if (!no_error) { 16601e04c3fSmrg switch (mode) { 16701e04c3fSmrg case GL_POINT: 16801e04c3fSmrg case GL_LINE: 16901e04c3fSmrg case GL_FILL: 17001e04c3fSmrg break; 17101e04c3fSmrg case GL_FILL_RECTANGLE_NV: 17201e04c3fSmrg if (ctx->Extensions.NV_fill_rectangle) 17301e04c3fSmrg break; 17401e04c3fSmrg /* fall-through */ 17501e04c3fSmrg default: 17601e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glPolygonMode(mode)"); 17701e04c3fSmrg return; 17801e04c3fSmrg } 1797117f1b4Smrg } 1807117f1b4Smrg 1817117f1b4Smrg switch (face) { 1827117f1b4Smrg case GL_FRONT: 18301e04c3fSmrg if (!no_error && ctx->API == API_OPENGL_CORE) { 184af69d88dSmrg _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" ); 185af69d88dSmrg return; 186af69d88dSmrg } 1877117f1b4Smrg if (ctx->Polygon.FrontMode == mode) 18801e04c3fSmrg return; 18901e04c3fSmrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewPolygonState ? 0 : _NEW_POLYGON); 19001e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewPolygonState; 1917117f1b4Smrg ctx->Polygon.FrontMode = mode; 1927117f1b4Smrg break; 1937117f1b4Smrg case GL_FRONT_AND_BACK: 19401e04c3fSmrg if (ctx->Polygon.FrontMode == mode && ctx->Polygon.BackMode == mode) 19501e04c3fSmrg return; 19601e04c3fSmrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewPolygonState ? 0 : _NEW_POLYGON); 19701e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewPolygonState; 1987117f1b4Smrg ctx->Polygon.FrontMode = mode; 1997117f1b4Smrg ctx->Polygon.BackMode = mode; 2007117f1b4Smrg break; 2017117f1b4Smrg case GL_BACK: 20201e04c3fSmrg if (!no_error && ctx->API == API_OPENGL_CORE) { 203af69d88dSmrg _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" ); 204af69d88dSmrg return; 205af69d88dSmrg } 2067117f1b4Smrg if (ctx->Polygon.BackMode == mode) 20701e04c3fSmrg return; 20801e04c3fSmrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewPolygonState ? 0 : _NEW_POLYGON); 20901e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewPolygonState; 2107117f1b4Smrg ctx->Polygon.BackMode = mode; 2117117f1b4Smrg break; 2127117f1b4Smrg default: 21301e04c3fSmrg if (!no_error) 21401e04c3fSmrg _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" ); 2157117f1b4Smrg return; 2167117f1b4Smrg } 2177117f1b4Smrg 2187117f1b4Smrg if (ctx->Driver.PolygonMode) 2197117f1b4Smrg ctx->Driver.PolygonMode(ctx, face, mode); 2207117f1b4Smrg} 2217117f1b4Smrg 2227117f1b4Smrg 22301e04c3fSmrgvoid GLAPIENTRY 22401e04c3fSmrg_mesa_PolygonMode_no_error(GLenum face, GLenum mode) 2257117f1b4Smrg{ 22601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 22701e04c3fSmrg polygon_mode(ctx, face, mode, true); 22801e04c3fSmrg} 2294a49301eSmrg 2304a49301eSmrg 23101e04c3fSmrgvoid GLAPIENTRY 23201e04c3fSmrg_mesa_PolygonMode(GLenum face, GLenum mode) 23301e04c3fSmrg{ 23401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 23501e04c3fSmrg polygon_mode(ctx, face, mode, false); 2367117f1b4Smrg} 2377117f1b4Smrg 2387117f1b4Smrg 2397117f1b4Smrg/** 2407117f1b4Smrg * Called by glPolygonStipple. 2417117f1b4Smrg */ 2427117f1b4Smrgvoid GLAPIENTRY 24301e04c3fSmrg_mesa_PolygonStipple(const GLubyte *pattern) 2447117f1b4Smrg{ 2457117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 2467117f1b4Smrg 24701e04c3fSmrg if (MESA_VERBOSE & VERBOSE_API) 2487117f1b4Smrg _mesa_debug(ctx, "glPolygonStipple\n"); 2497117f1b4Smrg 25001e04c3fSmrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewPolygonStipple ? 0 : 25101e04c3fSmrg _NEW_POLYGONSTIPPLE); 25201e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewPolygonStipple; 2537117f1b4Smrg 25401e04c3fSmrg pattern = _mesa_map_validate_pbo_source(ctx, 2, 25501e04c3fSmrg &ctx->Unpack, 32, 32, 1, 25601e04c3fSmrg GL_COLOR_INDEX, GL_BITMAP, 25701e04c3fSmrg INT_MAX, pattern, 25801e04c3fSmrg "glPolygonStipple"); 25901e04c3fSmrg if (!pattern) 26001e04c3fSmrg return; 26101e04c3fSmrg 26201e04c3fSmrg _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack); 26301e04c3fSmrg 26401e04c3fSmrg _mesa_unmap_pbo_source(ctx, &ctx->Unpack); 2657117f1b4Smrg 2667117f1b4Smrg if (ctx->Driver.PolygonStipple) 2677117f1b4Smrg ctx->Driver.PolygonStipple(ctx, pattern); 2687117f1b4Smrg} 2697117f1b4Smrg 2707117f1b4Smrg 2717117f1b4Smrg/** 2727117f1b4Smrg * Called by glPolygonStipple. 2737117f1b4Smrg */ 2747117f1b4Smrgvoid GLAPIENTRY 2753464ebd5Sriastradh_mesa_GetnPolygonStippleARB( GLsizei bufSize, GLubyte *dest ) 2767117f1b4Smrg{ 2777117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 2787117f1b4Smrg 2797117f1b4Smrg if (MESA_VERBOSE&VERBOSE_API) 2807117f1b4Smrg _mesa_debug(ctx, "glGetPolygonStipple\n"); 2817117f1b4Smrg 2824a49301eSmrg dest = _mesa_map_validate_pbo_dest(ctx, 2, 2834a49301eSmrg &ctx->Pack, 32, 32, 1, 2843464ebd5Sriastradh GL_COLOR_INDEX, GL_BITMAP, 2853464ebd5Sriastradh bufSize, dest, "glGetPolygonStipple"); 2864a49301eSmrg if (!dest) 2874a49301eSmrg return; 2884a49301eSmrg 2894a49301eSmrg _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack); 2904a49301eSmrg 2914a49301eSmrg _mesa_unmap_pbo_dest(ctx, &ctx->Pack); 2927117f1b4Smrg} 2937117f1b4Smrg 2947117f1b4Smrg 2953464ebd5Sriastradhvoid GLAPIENTRY 2963464ebd5Sriastradh_mesa_GetPolygonStipple( GLubyte *dest ) 2973464ebd5Sriastradh{ 2983464ebd5Sriastradh _mesa_GetnPolygonStippleARB(INT_MAX, dest); 2993464ebd5Sriastradh} 3003464ebd5Sriastradh 30101e04c3fSmrgvoid 30201e04c3fSmrg_mesa_polygon_offset_clamp(struct gl_context *ctx, 30301e04c3fSmrg GLfloat factor, GLfloat units, GLfloat clamp) 3047117f1b4Smrg{ 3057117f1b4Smrg if (ctx->Polygon.OffsetFactor == factor && 30601e04c3fSmrg ctx->Polygon.OffsetUnits == units && 30701e04c3fSmrg ctx->Polygon.OffsetClamp == clamp) 3087117f1b4Smrg return; 3097117f1b4Smrg 31001e04c3fSmrg FLUSH_VERTICES(ctx, ctx->DriverFlags.NewPolygonState ? 0 : _NEW_POLYGON); 31101e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewPolygonState; 3127117f1b4Smrg ctx->Polygon.OffsetFactor = factor; 3137117f1b4Smrg ctx->Polygon.OffsetUnits = units; 31401e04c3fSmrg ctx->Polygon.OffsetClamp = clamp; 3157117f1b4Smrg 3167117f1b4Smrg if (ctx->Driver.PolygonOffset) 31701e04c3fSmrg ctx->Driver.PolygonOffset( ctx, factor, units, clamp ); 3187117f1b4Smrg} 3197117f1b4Smrg 3207117f1b4Smrgvoid GLAPIENTRY 32101e04c3fSmrg_mesa_PolygonOffset( GLfloat factor, GLfloat units ) 3227117f1b4Smrg{ 3237117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 32401e04c3fSmrg 32501e04c3fSmrg if (MESA_VERBOSE&VERBOSE_API) 32601e04c3fSmrg _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units); 32701e04c3fSmrg 32801e04c3fSmrg _mesa_polygon_offset_clamp(ctx, factor, units, 0.0); 3297117f1b4Smrg} 3307117f1b4Smrg 33101e04c3fSmrgvoid GLAPIENTRY 33201e04c3fSmrg_mesa_PolygonOffsetClampEXT( GLfloat factor, GLfloat units, GLfloat clamp ) 33301e04c3fSmrg{ 33401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 33501e04c3fSmrg 33601e04c3fSmrg if (!ctx->Extensions.ARB_polygon_offset_clamp) { 33701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 33801e04c3fSmrg "unsupported function (%s) called", "glPolygonOffsetClamp"); 33901e04c3fSmrg return; 34001e04c3fSmrg } 3417117f1b4Smrg 34201e04c3fSmrg if (MESA_VERBOSE&VERBOSE_API) 34301e04c3fSmrg _mesa_debug(ctx, "glPolygonOffsetClamp %f %f %f\n", factor, units, clamp); 34401e04c3fSmrg 34501e04c3fSmrg _mesa_polygon_offset_clamp(ctx, factor, units, clamp); 34601e04c3fSmrg} 3477117f1b4Smrg 3487117f1b4Smrg/**********************************************************************/ 3497117f1b4Smrg/** \name Initialization */ 3507117f1b4Smrg/*@{*/ 3517117f1b4Smrg 3527117f1b4Smrg/** 3537117f1b4Smrg * Initialize the context polygon state. 3547117f1b4Smrg * 3557117f1b4Smrg * \param ctx GL context. 3567117f1b4Smrg * 3573464ebd5Sriastradh * Initializes __struct gl_contextRec::Polygon and __struct gl_contextRec::PolygonStipple 3587117f1b4Smrg * attribute groups. 3597117f1b4Smrg */ 3603464ebd5Sriastradhvoid _mesa_init_polygon( struct gl_context * ctx ) 3617117f1b4Smrg{ 3627117f1b4Smrg /* Polygon group */ 3637117f1b4Smrg ctx->Polygon.CullFlag = GL_FALSE; 3647117f1b4Smrg ctx->Polygon.CullFaceMode = GL_BACK; 3657117f1b4Smrg ctx->Polygon.FrontFace = GL_CCW; 3667117f1b4Smrg ctx->Polygon.FrontMode = GL_FILL; 3677117f1b4Smrg ctx->Polygon.BackMode = GL_FILL; 3687117f1b4Smrg ctx->Polygon.SmoothFlag = GL_FALSE; 3697117f1b4Smrg ctx->Polygon.StippleFlag = GL_FALSE; 3707117f1b4Smrg ctx->Polygon.OffsetFactor = 0.0F; 3717117f1b4Smrg ctx->Polygon.OffsetUnits = 0.0F; 37201e04c3fSmrg ctx->Polygon.OffsetClamp = 0.0F; 3737117f1b4Smrg ctx->Polygon.OffsetPoint = GL_FALSE; 3747117f1b4Smrg ctx->Polygon.OffsetLine = GL_FALSE; 3757117f1b4Smrg ctx->Polygon.OffsetFill = GL_FALSE; 3767117f1b4Smrg 3777117f1b4Smrg 3787117f1b4Smrg /* Polygon Stipple group */ 379cdc920a0Smrg memset( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) ); 3807117f1b4Smrg} 3817117f1b4Smrg 3827117f1b4Smrg/*@}*/ 383