polygon.c revision 848b8605
1848b8605Smrg/** 2848b8605Smrg * \file polygon.c 3848b8605Smrg * Polygon operations. 4848b8605Smrg */ 5848b8605Smrg 6848b8605Smrg/* 7848b8605Smrg * Mesa 3-D graphics library 8848b8605Smrg * 9848b8605Smrg * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 10848b8605Smrg * 11848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 12848b8605Smrg * copy of this software and associated documentation files (the "Software"), 13848b8605Smrg * to deal in the Software without restriction, including without limitation 14848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 16848b8605Smrg * Software is furnished to do so, subject to the following conditions: 17848b8605Smrg * 18848b8605Smrg * The above copyright notice and this permission notice shall be included 19848b8605Smrg * in all copies or substantial portions of the Software. 20848b8605Smrg * 21848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 28848b8605Smrg */ 29848b8605Smrg 30848b8605Smrg 31848b8605Smrg#include "glheader.h" 32848b8605Smrg#include "imports.h" 33848b8605Smrg#include "context.h" 34848b8605Smrg#include "image.h" 35848b8605Smrg#include "enums.h" 36848b8605Smrg#include "pack.h" 37848b8605Smrg#include "pbo.h" 38848b8605Smrg#include "polygon.h" 39848b8605Smrg#include "mtypes.h" 40848b8605Smrg 41848b8605Smrg 42848b8605Smrg/** 43848b8605Smrg * Specify whether to cull front- or back-facing facets. 44848b8605Smrg * 45848b8605Smrg * \param mode culling mode. 46848b8605Smrg * 47848b8605Smrg * \sa glCullFace(). 48848b8605Smrg * 49848b8605Smrg * Verifies the parameter and updates gl_polygon_attrib::CullFaceMode. On 50848b8605Smrg * change, flushes the vertices and notifies the driver via 51848b8605Smrg * the dd_function_table::CullFace callback. 52848b8605Smrg */ 53848b8605Smrgvoid GLAPIENTRY 54848b8605Smrg_mesa_CullFace( GLenum mode ) 55848b8605Smrg{ 56848b8605Smrg GET_CURRENT_CONTEXT(ctx); 57848b8605Smrg 58848b8605Smrg if (MESA_VERBOSE&VERBOSE_API) 59848b8605Smrg _mesa_debug(ctx, "glCullFace %s\n", _mesa_lookup_enum_by_nr(mode)); 60848b8605Smrg 61848b8605Smrg if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) { 62848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glCullFace" ); 63848b8605Smrg return; 64848b8605Smrg } 65848b8605Smrg 66848b8605Smrg if (ctx->Polygon.CullFaceMode == mode) 67848b8605Smrg return; 68848b8605Smrg 69848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POLYGON); 70848b8605Smrg ctx->Polygon.CullFaceMode = mode; 71848b8605Smrg 72848b8605Smrg if (ctx->Driver.CullFace) 73848b8605Smrg ctx->Driver.CullFace( ctx, mode ); 74848b8605Smrg} 75848b8605Smrg 76848b8605Smrg 77848b8605Smrg/** 78848b8605Smrg * Define front- and back-facing 79848b8605Smrg * 80848b8605Smrg * \param mode orientation of front-facing polygons. 81848b8605Smrg * 82848b8605Smrg * \sa glFrontFace(). 83848b8605Smrg * 84848b8605Smrg * Verifies the parameter and updates gl_polygon_attrib::FrontFace. On change 85848b8605Smrg * flushes the vertices and notifies the driver via 86848b8605Smrg * the dd_function_table::FrontFace callback. 87848b8605Smrg */ 88848b8605Smrgvoid GLAPIENTRY 89848b8605Smrg_mesa_FrontFace( GLenum mode ) 90848b8605Smrg{ 91848b8605Smrg GET_CURRENT_CONTEXT(ctx); 92848b8605Smrg 93848b8605Smrg if (MESA_VERBOSE&VERBOSE_API) 94848b8605Smrg _mesa_debug(ctx, "glFrontFace %s\n", _mesa_lookup_enum_by_nr(mode)); 95848b8605Smrg 96848b8605Smrg if (mode!=GL_CW && mode!=GL_CCW) { 97848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" ); 98848b8605Smrg return; 99848b8605Smrg } 100848b8605Smrg 101848b8605Smrg if (ctx->Polygon.FrontFace == mode) 102848b8605Smrg return; 103848b8605Smrg 104848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POLYGON); 105848b8605Smrg ctx->Polygon.FrontFace = mode; 106848b8605Smrg 107848b8605Smrg ctx->Polygon._FrontBit = (GLboolean) (mode == GL_CW); 108848b8605Smrg 109848b8605Smrg if (ctx->Driver.FrontFace) 110848b8605Smrg ctx->Driver.FrontFace( ctx, mode ); 111848b8605Smrg} 112848b8605Smrg 113848b8605Smrg 114848b8605Smrg/** 115848b8605Smrg * Set the polygon rasterization mode. 116848b8605Smrg * 117848b8605Smrg * \param face the polygons which \p mode applies to. 118848b8605Smrg * \param mode how polygons should be rasterized. 119848b8605Smrg * 120848b8605Smrg * \sa glPolygonMode(). 121848b8605Smrg * 122848b8605Smrg * Verifies the parameters and updates gl_polygon_attrib::FrontMode and 123848b8605Smrg * gl_polygon_attrib::BackMode. On change flushes the vertices and notifies the 124848b8605Smrg * driver via the dd_function_table::PolygonMode callback. 125848b8605Smrg */ 126848b8605Smrgvoid GLAPIENTRY 127848b8605Smrg_mesa_PolygonMode( GLenum face, GLenum mode ) 128848b8605Smrg{ 129848b8605Smrg GET_CURRENT_CONTEXT(ctx); 130848b8605Smrg 131848b8605Smrg if (MESA_VERBOSE&VERBOSE_API) 132848b8605Smrg _mesa_debug(ctx, "glPolygonMode %s %s\n", 133848b8605Smrg _mesa_lookup_enum_by_nr(face), 134848b8605Smrg _mesa_lookup_enum_by_nr(mode)); 135848b8605Smrg 136848b8605Smrg if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) { 137848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" ); 138848b8605Smrg return; 139848b8605Smrg } 140848b8605Smrg 141848b8605Smrg switch (face) { 142848b8605Smrg case GL_FRONT: 143848b8605Smrg if (ctx->API == API_OPENGL_CORE) { 144848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" ); 145848b8605Smrg return; 146848b8605Smrg } 147848b8605Smrg if (ctx->Polygon.FrontMode == mode) 148848b8605Smrg return; 149848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POLYGON); 150848b8605Smrg ctx->Polygon.FrontMode = mode; 151848b8605Smrg break; 152848b8605Smrg case GL_FRONT_AND_BACK: 153848b8605Smrg if (ctx->Polygon.FrontMode == mode && 154848b8605Smrg ctx->Polygon.BackMode == mode) 155848b8605Smrg return; 156848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POLYGON); 157848b8605Smrg ctx->Polygon.FrontMode = mode; 158848b8605Smrg ctx->Polygon.BackMode = mode; 159848b8605Smrg break; 160848b8605Smrg case GL_BACK: 161848b8605Smrg if (ctx->API == API_OPENGL_CORE) { 162848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" ); 163848b8605Smrg return; 164848b8605Smrg } 165848b8605Smrg if (ctx->Polygon.BackMode == mode) 166848b8605Smrg return; 167848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POLYGON); 168848b8605Smrg ctx->Polygon.BackMode = mode; 169848b8605Smrg break; 170848b8605Smrg default: 171848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" ); 172848b8605Smrg return; 173848b8605Smrg } 174848b8605Smrg 175848b8605Smrg if (ctx->Driver.PolygonMode) 176848b8605Smrg ctx->Driver.PolygonMode(ctx, face, mode); 177848b8605Smrg} 178848b8605Smrg 179848b8605Smrg 180848b8605Smrg/** 181848b8605Smrg * This routine updates the ctx->Polygon.Stipple state. 182848b8605Smrg * If we're getting the stipple data from a PBO, we map the buffer 183848b8605Smrg * in order to access the data. 184848b8605Smrg * In any case, we obey the current pixel unpacking parameters when fetching 185848b8605Smrg * the stipple data. 186848b8605Smrg * 187848b8605Smrg * In the future, this routine should be used as a fallback, called via 188848b8605Smrg * ctx->Driver.PolygonStipple(). We'll have to update all the DRI drivers 189848b8605Smrg * too. 190848b8605Smrg */ 191848b8605Smrgvoid 192848b8605Smrg_mesa_polygon_stipple(struct gl_context *ctx, const GLubyte *pattern) 193848b8605Smrg{ 194848b8605Smrg pattern = _mesa_map_validate_pbo_source(ctx, 2, 195848b8605Smrg &ctx->Unpack, 32, 32, 1, 196848b8605Smrg GL_COLOR_INDEX, GL_BITMAP, 197848b8605Smrg INT_MAX, pattern, 198848b8605Smrg "glPolygonStipple"); 199848b8605Smrg if (!pattern) 200848b8605Smrg return; 201848b8605Smrg 202848b8605Smrg _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack); 203848b8605Smrg 204848b8605Smrg _mesa_unmap_pbo_source(ctx, &ctx->Unpack); 205848b8605Smrg} 206848b8605Smrg 207848b8605Smrg 208848b8605Smrg/** 209848b8605Smrg * Called by glPolygonStipple. 210848b8605Smrg */ 211848b8605Smrgvoid GLAPIENTRY 212848b8605Smrg_mesa_PolygonStipple( const GLubyte *pattern ) 213848b8605Smrg{ 214848b8605Smrg GET_CURRENT_CONTEXT(ctx); 215848b8605Smrg 216848b8605Smrg if (MESA_VERBOSE&VERBOSE_API) 217848b8605Smrg _mesa_debug(ctx, "glPolygonStipple\n"); 218848b8605Smrg 219848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POLYGONSTIPPLE); 220848b8605Smrg 221848b8605Smrg _mesa_polygon_stipple(ctx, pattern); 222848b8605Smrg 223848b8605Smrg if (ctx->Driver.PolygonStipple) 224848b8605Smrg ctx->Driver.PolygonStipple(ctx, pattern); 225848b8605Smrg} 226848b8605Smrg 227848b8605Smrg 228848b8605Smrg/** 229848b8605Smrg * Called by glPolygonStipple. 230848b8605Smrg */ 231848b8605Smrgvoid GLAPIENTRY 232848b8605Smrg_mesa_GetnPolygonStippleARB( GLsizei bufSize, GLubyte *dest ) 233848b8605Smrg{ 234848b8605Smrg GET_CURRENT_CONTEXT(ctx); 235848b8605Smrg 236848b8605Smrg if (MESA_VERBOSE&VERBOSE_API) 237848b8605Smrg _mesa_debug(ctx, "glGetPolygonStipple\n"); 238848b8605Smrg 239848b8605Smrg dest = _mesa_map_validate_pbo_dest(ctx, 2, 240848b8605Smrg &ctx->Pack, 32, 32, 1, 241848b8605Smrg GL_COLOR_INDEX, GL_BITMAP, 242848b8605Smrg bufSize, dest, "glGetPolygonStipple"); 243848b8605Smrg if (!dest) 244848b8605Smrg return; 245848b8605Smrg 246848b8605Smrg _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack); 247848b8605Smrg 248848b8605Smrg _mesa_unmap_pbo_dest(ctx, &ctx->Pack); 249848b8605Smrg} 250848b8605Smrg 251848b8605Smrg 252848b8605Smrgvoid GLAPIENTRY 253848b8605Smrg_mesa_GetPolygonStipple( GLubyte *dest ) 254848b8605Smrg{ 255848b8605Smrg _mesa_GetnPolygonStippleARB(INT_MAX, dest); 256848b8605Smrg} 257848b8605Smrg 258848b8605Smrg 259848b8605Smrgvoid GLAPIENTRY 260848b8605Smrg_mesa_PolygonOffset( GLfloat factor, GLfloat units ) 261848b8605Smrg{ 262848b8605Smrg GET_CURRENT_CONTEXT(ctx); 263848b8605Smrg 264848b8605Smrg if (MESA_VERBOSE&VERBOSE_API) 265848b8605Smrg _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units); 266848b8605Smrg 267848b8605Smrg if (ctx->Polygon.OffsetFactor == factor && 268848b8605Smrg ctx->Polygon.OffsetUnits == units) 269848b8605Smrg return; 270848b8605Smrg 271848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POLYGON); 272848b8605Smrg ctx->Polygon.OffsetFactor = factor; 273848b8605Smrg ctx->Polygon.OffsetUnits = units; 274848b8605Smrg 275848b8605Smrg if (ctx->Driver.PolygonOffset) 276848b8605Smrg ctx->Driver.PolygonOffset( ctx, factor, units ); 277848b8605Smrg} 278848b8605Smrg 279848b8605Smrg 280848b8605Smrgvoid GLAPIENTRY 281848b8605Smrg_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias ) 282848b8605Smrg{ 283848b8605Smrg GET_CURRENT_CONTEXT(ctx); 284848b8605Smrg /* XXX mult by DepthMaxF here??? */ 285848b8605Smrg _mesa_PolygonOffset(factor, bias * ctx->DrawBuffer->_DepthMaxF ); 286848b8605Smrg} 287848b8605Smrg 288848b8605Smrg 289848b8605Smrg 290848b8605Smrg/**********************************************************************/ 291848b8605Smrg/** \name Initialization */ 292848b8605Smrg/*@{*/ 293848b8605Smrg 294848b8605Smrg/** 295848b8605Smrg * Initialize the context polygon state. 296848b8605Smrg * 297848b8605Smrg * \param ctx GL context. 298848b8605Smrg * 299848b8605Smrg * Initializes __struct gl_contextRec::Polygon and __struct gl_contextRec::PolygonStipple 300848b8605Smrg * attribute groups. 301848b8605Smrg */ 302848b8605Smrgvoid _mesa_init_polygon( struct gl_context * ctx ) 303848b8605Smrg{ 304848b8605Smrg /* Polygon group */ 305848b8605Smrg ctx->Polygon.CullFlag = GL_FALSE; 306848b8605Smrg ctx->Polygon.CullFaceMode = GL_BACK; 307848b8605Smrg ctx->Polygon.FrontFace = GL_CCW; 308848b8605Smrg ctx->Polygon._FrontBit = 0; 309848b8605Smrg ctx->Polygon.FrontMode = GL_FILL; 310848b8605Smrg ctx->Polygon.BackMode = GL_FILL; 311848b8605Smrg ctx->Polygon.SmoothFlag = GL_FALSE; 312848b8605Smrg ctx->Polygon.StippleFlag = GL_FALSE; 313848b8605Smrg ctx->Polygon.OffsetFactor = 0.0F; 314848b8605Smrg ctx->Polygon.OffsetUnits = 0.0F; 315848b8605Smrg ctx->Polygon.OffsetPoint = GL_FALSE; 316848b8605Smrg ctx->Polygon.OffsetLine = GL_FALSE; 317848b8605Smrg ctx->Polygon.OffsetFill = GL_FALSE; 318848b8605Smrg 319848b8605Smrg 320848b8605Smrg /* Polygon Stipple group */ 321848b8605Smrg memset( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) ); 322848b8605Smrg} 323848b8605Smrg 324848b8605Smrg/*@}*/ 325