polygon.c revision c407c6d58891dbb1fcdfc6ef17e6001b53d7e040
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 */ 53void 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_lookup_enum_by_nr(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 */ 88void 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_lookup_enum_by_nr(mode)); 95 96 if (mode!=GL_CW && mode!=GL_CCW) { 97 _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" ); 98 return; 99 } 100 101 if (ctx->Polygon.FrontFace == mode) 102 return; 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 */ 124void 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_lookup_enum_by_nr(face), 132 _mesa_lookup_enum_by_nr(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 */ 181void 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 */ 211void 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 232void GLAPIENTRY 233_mesa_GetPolygonStipple( GLubyte *dest ) 234{ 235 _mesa_GetnPolygonStippleARB(INT_MAX, dest); 236} 237 238 239void GLAPIENTRY 240_mesa_PolygonOffset( GLfloat factor, GLfloat units ) 241{ 242 GET_CURRENT_CONTEXT(ctx); 243 244 if (MESA_VERBOSE&VERBOSE_API) 245 _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units); 246 247 if (ctx->Polygon.OffsetFactor == factor && 248 ctx->Polygon.OffsetUnits == units) 249 return; 250 251 FLUSH_VERTICES(ctx, _NEW_POLYGON); 252 ctx->Polygon.OffsetFactor = factor; 253 ctx->Polygon.OffsetUnits = units; 254 255 if (ctx->Driver.PolygonOffset) 256 ctx->Driver.PolygonOffset( ctx, factor, units ); 257} 258 259 260void GLAPIENTRY 261_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias ) 262{ 263 GET_CURRENT_CONTEXT(ctx); 264 /* XXX mult by DepthMaxF here??? */ 265 _mesa_PolygonOffset(factor, bias * ctx->DrawBuffer->_DepthMaxF ); 266} 267 268 269 270/**********************************************************************/ 271/** \name Initialization */ 272/*@{*/ 273 274/** 275 * Initialize the context polygon state. 276 * 277 * \param ctx GL context. 278 * 279 * Initializes __struct gl_contextRec::Polygon and __struct gl_contextRec::PolygonStipple 280 * attribute groups. 281 */ 282void _mesa_init_polygon( struct gl_context * ctx ) 283{ 284 /* Polygon group */ 285 ctx->Polygon.CullFlag = GL_FALSE; 286 ctx->Polygon.CullFaceMode = GL_BACK; 287 ctx->Polygon.FrontFace = GL_CCW; 288 ctx->Polygon._FrontBit = 0; 289 ctx->Polygon.FrontMode = GL_FILL; 290 ctx->Polygon.BackMode = GL_FILL; 291 ctx->Polygon.SmoothFlag = GL_FALSE; 292 ctx->Polygon.StippleFlag = GL_FALSE; 293 ctx->Polygon.OffsetFactor = 0.0F; 294 ctx->Polygon.OffsetUnits = 0.0F; 295 ctx->Polygon.OffsetPoint = GL_FALSE; 296 ctx->Polygon.OffsetLine = GL_FALSE; 297 ctx->Polygon.OffsetFill = GL_FALSE; 298 299 300 /* Polygon Stipple group */ 301 memset( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) ); 302} 303 304/*@}*/ 305