1848b8605Smrg/** 2848b8605Smrg * \file points.c 3848b8605Smrg * Point operations. 4848b8605Smrg */ 5848b8605Smrg 6848b8605Smrg/* 7848b8605Smrg * Mesa 3-D graphics library 8848b8605Smrg * 9848b8605Smrg * Copyright (C) 1999-2007 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 "context.h" 33848b8605Smrg#include "macros.h" 34848b8605Smrg#include "points.h" 35848b8605Smrg#include "mtypes.h" 36848b8605Smrg 37848b8605Smrg 38848b8605Smrg/** 39848b8605Smrg * Set current point size. 40848b8605Smrg * \param size point diameter in pixels 41848b8605Smrg * \sa glPointSize(). 42848b8605Smrg */ 43b8e80941Smrgstatic ALWAYS_INLINE void 44b8e80941Smrgpoint_size(struct gl_context *ctx, GLfloat size, bool no_error) 45848b8605Smrg{ 46b8e80941Smrg if (ctx->Point.Size == size) 47848b8605Smrg return; 48848b8605Smrg 49b8e80941Smrg if (!no_error && size <= 0.0F) { 50b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glPointSize"); 51848b8605Smrg return; 52b8e80941Smrg } 53848b8605Smrg 54848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POINT); 55848b8605Smrg ctx->Point.Size = size; 56848b8605Smrg 57848b8605Smrg if (ctx->Driver.PointSize) 58848b8605Smrg ctx->Driver.PointSize(ctx, size); 59848b8605Smrg} 60848b8605Smrg 61848b8605Smrg 62b8e80941Smrgvoid GLAPIENTRY 63b8e80941Smrg_mesa_PointSize_no_error(GLfloat size) 64b8e80941Smrg{ 65b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 66b8e80941Smrg point_size(ctx, size, true); 67b8e80941Smrg} 68b8e80941Smrg 69b8e80941Smrg 70b8e80941Smrgvoid GLAPIENTRY 71b8e80941Smrg_mesa_PointSize( GLfloat size ) 72b8e80941Smrg{ 73b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 74b8e80941Smrg point_size(ctx, size, false); 75b8e80941Smrg} 76b8e80941Smrg 77b8e80941Smrg 78848b8605Smrgvoid GLAPIENTRY 79848b8605Smrg_mesa_PointParameteri( GLenum pname, GLint param ) 80848b8605Smrg{ 81848b8605Smrg GLfloat p[3]; 82848b8605Smrg p[0] = (GLfloat) param; 83848b8605Smrg p[1] = p[2] = 0.0F; 84848b8605Smrg _mesa_PointParameterfv(pname, p); 85848b8605Smrg} 86848b8605Smrg 87848b8605Smrg 88848b8605Smrgvoid GLAPIENTRY 89848b8605Smrg_mesa_PointParameteriv( GLenum pname, const GLint *params ) 90848b8605Smrg{ 91848b8605Smrg GLfloat p[3]; 92848b8605Smrg p[0] = (GLfloat) params[0]; 93848b8605Smrg if (pname == GL_DISTANCE_ATTENUATION_EXT) { 94848b8605Smrg p[1] = (GLfloat) params[1]; 95848b8605Smrg p[2] = (GLfloat) params[2]; 96848b8605Smrg } 97848b8605Smrg _mesa_PointParameterfv(pname, p); 98848b8605Smrg} 99848b8605Smrg 100848b8605Smrg 101848b8605Smrgvoid GLAPIENTRY 102848b8605Smrg_mesa_PointParameterf( GLenum pname, GLfloat param) 103848b8605Smrg{ 104848b8605Smrg GLfloat p[3]; 105848b8605Smrg p[0] = param; 106848b8605Smrg p[1] = p[2] = 0.0F; 107848b8605Smrg _mesa_PointParameterfv(pname, p); 108848b8605Smrg} 109848b8605Smrg 110848b8605Smrg 111848b8605Smrgvoid GLAPIENTRY 112848b8605Smrg_mesa_PointParameterfv( GLenum pname, const GLfloat *params) 113848b8605Smrg{ 114848b8605Smrg GET_CURRENT_CONTEXT(ctx); 115848b8605Smrg 116848b8605Smrg /* Drivers that support point sprites must also support point parameters. 117848b8605Smrg * If point parameters aren't supported, then this function shouldn't even 118848b8605Smrg * exist. 119848b8605Smrg */ 120b8e80941Smrg assert(!(ctx->Extensions.ARB_point_sprite 121848b8605Smrg || ctx->Extensions.NV_point_sprite) 122848b8605Smrg || ctx->Extensions.EXT_point_parameters); 123848b8605Smrg 124848b8605Smrg if (!ctx->Extensions.EXT_point_parameters) { 125848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 126848b8605Smrg "unsupported function called (unsupported extension)"); 127848b8605Smrg return; 128848b8605Smrg } 129848b8605Smrg 130848b8605Smrg switch (pname) { 131848b8605Smrg case GL_DISTANCE_ATTENUATION_EXT: 132848b8605Smrg if (TEST_EQ_3V(ctx->Point.Params, params)) 133848b8605Smrg return; 134848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POINT); 135848b8605Smrg COPY_3V(ctx->Point.Params, params); 136b8e80941Smrg ctx->Point._Attenuated = (ctx->Point.Params[0] != 1.0F || 137b8e80941Smrg ctx->Point.Params[1] != 0.0F || 138b8e80941Smrg ctx->Point.Params[2] != 0.0F); 139848b8605Smrg break; 140848b8605Smrg case GL_POINT_SIZE_MIN_EXT: 141848b8605Smrg if (params[0] < 0.0F) { 142848b8605Smrg _mesa_error( ctx, GL_INVALID_VALUE, 143848b8605Smrg "glPointParameterf[v]{EXT,ARB}(param)" ); 144848b8605Smrg return; 145848b8605Smrg } 146848b8605Smrg if (ctx->Point.MinSize == params[0]) 147848b8605Smrg return; 148848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POINT); 149848b8605Smrg ctx->Point.MinSize = params[0]; 150848b8605Smrg break; 151848b8605Smrg case GL_POINT_SIZE_MAX_EXT: 152848b8605Smrg if (params[0] < 0.0F) { 153848b8605Smrg _mesa_error( ctx, GL_INVALID_VALUE, 154848b8605Smrg "glPointParameterf[v]{EXT,ARB}(param)" ); 155848b8605Smrg return; 156848b8605Smrg } 157848b8605Smrg if (ctx->Point.MaxSize == params[0]) 158848b8605Smrg return; 159848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POINT); 160848b8605Smrg ctx->Point.MaxSize = params[0]; 161848b8605Smrg break; 162848b8605Smrg case GL_POINT_FADE_THRESHOLD_SIZE_EXT: 163848b8605Smrg if (params[0] < 0.0F) { 164848b8605Smrg _mesa_error( ctx, GL_INVALID_VALUE, 165848b8605Smrg "glPointParameterf[v]{EXT,ARB}(param)" ); 166848b8605Smrg return; 167848b8605Smrg } 168848b8605Smrg if (ctx->Point.Threshold == params[0]) 169848b8605Smrg return; 170848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POINT); 171848b8605Smrg ctx->Point.Threshold = params[0]; 172848b8605Smrg break; 173848b8605Smrg case GL_POINT_SPRITE_R_MODE_NV: 174848b8605Smrg /* This is one area where ARB_point_sprite and NV_point_sprite 175848b8605Smrg * differ. In ARB_point_sprite the POINT_SPRITE_R_MODE is 176848b8605Smrg * always ZERO. NV_point_sprite adds the S and R modes. 177848b8605Smrg */ 178848b8605Smrg if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_point_sprite) { 179848b8605Smrg GLenum value = (GLenum) params[0]; 180848b8605Smrg if (value != GL_ZERO && value != GL_S && value != GL_R) { 181848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 182848b8605Smrg "glPointParameterf[v]{EXT,ARB}(param)"); 183848b8605Smrg return; 184848b8605Smrg } 185848b8605Smrg if (ctx->Point.SpriteRMode == value) 186848b8605Smrg return; 187848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POINT); 188848b8605Smrg ctx->Point.SpriteRMode = value; 189848b8605Smrg } 190848b8605Smrg else { 191848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, 192848b8605Smrg "glPointParameterf[v]{EXT,ARB}(pname)"); 193848b8605Smrg return; 194848b8605Smrg } 195848b8605Smrg break; 196848b8605Smrg case GL_POINT_SPRITE_COORD_ORIGIN: 197848b8605Smrg /* GL_POINT_SPRITE_COORD_ORIGIN was added to point sprites when the 198848b8605Smrg * extension was merged into OpenGL 2.0. 199848b8605Smrg */ 200848b8605Smrg if ((ctx->API == API_OPENGL_COMPAT && ctx->Version >= 20) 201848b8605Smrg || ctx->API == API_OPENGL_CORE) { 202848b8605Smrg GLenum value = (GLenum) params[0]; 203848b8605Smrg if (value != GL_LOWER_LEFT && value != GL_UPPER_LEFT) { 204848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 205848b8605Smrg "glPointParameterf[v]{EXT,ARB}(param)"); 206848b8605Smrg return; 207848b8605Smrg } 208848b8605Smrg if (ctx->Point.SpriteOrigin == value) 209848b8605Smrg return; 210848b8605Smrg FLUSH_VERTICES(ctx, _NEW_POINT); 211848b8605Smrg ctx->Point.SpriteOrigin = value; 212848b8605Smrg } 213848b8605Smrg else { 214848b8605Smrg _mesa_error(ctx, GL_INVALID_ENUM, 215848b8605Smrg "glPointParameterf[v]{EXT,ARB}(pname)"); 216848b8605Smrg return; 217848b8605Smrg } 218848b8605Smrg break; 219848b8605Smrg default: 220848b8605Smrg _mesa_error( ctx, GL_INVALID_ENUM, 221848b8605Smrg "glPointParameterf[v]{EXT,ARB}(pname)" ); 222848b8605Smrg return; 223848b8605Smrg } 224848b8605Smrg 225848b8605Smrg if (ctx->Driver.PointParameterfv) 226b8e80941Smrg ctx->Driver.PointParameterfv(ctx, pname, params); 227848b8605Smrg} 228848b8605Smrg 229848b8605Smrg 230848b8605Smrg 231848b8605Smrg/** 232848b8605Smrg * Initialize the context point state. 233848b8605Smrg * 234848b8605Smrg * \param ctx GL context. 235848b8605Smrg * 236848b8605Smrg * Initializes __struct gl_contextRec::Point and point related constants in 237848b8605Smrg * __struct gl_contextRec::Const. 238848b8605Smrg */ 239848b8605Smrgvoid 240848b8605Smrg_mesa_init_point(struct gl_context *ctx) 241848b8605Smrg{ 242848b8605Smrg ctx->Point.SmoothFlag = GL_FALSE; 243848b8605Smrg ctx->Point.Size = 1.0; 244848b8605Smrg ctx->Point.Params[0] = 1.0; 245848b8605Smrg ctx->Point.Params[1] = 0.0; 246848b8605Smrg ctx->Point.Params[2] = 0.0; 247848b8605Smrg ctx->Point._Attenuated = GL_FALSE; 248848b8605Smrg ctx->Point.MinSize = 0.0; 249848b8605Smrg ctx->Point.MaxSize 250848b8605Smrg = MAX2(ctx->Const.MaxPointSize, ctx->Const.MaxPointSizeAA); 251848b8605Smrg ctx->Point.Threshold = 1.0; 252848b8605Smrg 253848b8605Smrg /* Page 403 (page 423 of the PDF) of the OpenGL 3.0 spec says: 254848b8605Smrg * 255848b8605Smrg * "Non-sprite points (section 3.4) - Enable/Disable targets 256848b8605Smrg * POINT_SMOOTH and POINT_SPRITE, and all associated state. Point 257848b8605Smrg * rasterization is always performed as though POINT_SPRITE were 258848b8605Smrg * enabled." 259848b8605Smrg * 260848b8605Smrg * In a core context, the state will default to true, and the setters and 261848b8605Smrg * getters are disabled. 262848b8605Smrg */ 263848b8605Smrg ctx->Point.PointSprite = (ctx->API == API_OPENGL_CORE || 264848b8605Smrg ctx->API == API_OPENGLES2); 265848b8605Smrg 266848b8605Smrg ctx->Point.SpriteRMode = GL_ZERO; /* GL_NV_point_sprite (only!) */ 267848b8605Smrg ctx->Point.SpriteOrigin = GL_UPPER_LEFT; /* GL_ARB_point_sprite */ 268b8e80941Smrg ctx->Point.CoordReplace = 0; /* GL_ARB/NV_point_sprite */ 269848b8605Smrg} 270