1 /** 2 * \file points.c 3 * Point operations. 4 */ 5 6 /* 7 * Mesa 3-D graphics library 8 * 9 * Copyright (C) 1999-2007 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 "context.h" 33 #include "macros.h" 34 #include "points.h" 35 #include "mtypes.h" 36 37 38 /** 39 * Set current point size. 40 * \param size point diameter in pixels 41 * \sa glPointSize(). 42 */ 43 void GLAPIENTRY 44 _mesa_PointSize( GLfloat size ) 45 { 46 GET_CURRENT_CONTEXT(ctx); 47 48 if (size <= 0.0F) { 49 _mesa_error( ctx, GL_INVALID_VALUE, "glPointSize" ); 50 return; 51 } 52 53 if (ctx->Point.Size == size) 54 return; 55 56 FLUSH_VERTICES(ctx, _NEW_POINT); 57 ctx->Point.Size = size; 58 59 if (ctx->Driver.PointSize) 60 ctx->Driver.PointSize(ctx, size); 61 } 62 63 64 void GLAPIENTRY 65 _mesa_PointParameteri( GLenum pname, GLint param ) 66 { 67 GLfloat p[3]; 68 p[0] = (GLfloat) param; 69 p[1] = p[2] = 0.0F; 70 _mesa_PointParameterfv(pname, p); 71 } 72 73 74 void GLAPIENTRY 75 _mesa_PointParameteriv( GLenum pname, const GLint *params ) 76 { 77 GLfloat p[3]; 78 p[0] = (GLfloat) params[0]; 79 if (pname == GL_DISTANCE_ATTENUATION_EXT) { 80 p[1] = (GLfloat) params[1]; 81 p[2] = (GLfloat) params[2]; 82 } 83 _mesa_PointParameterfv(pname, p); 84 } 85 86 87 void GLAPIENTRY 88 _mesa_PointParameterf( GLenum pname, GLfloat param) 89 { 90 GLfloat p[3]; 91 p[0] = param; 92 p[1] = p[2] = 0.0F; 93 _mesa_PointParameterfv(pname, p); 94 } 95 96 97 void GLAPIENTRY 98 _mesa_PointParameterfv( GLenum pname, const GLfloat *params) 99 { 100 GET_CURRENT_CONTEXT(ctx); 101 102 /* Drivers that support point sprites must also support point parameters. 103 * If point parameters aren't supported, then this function shouldn't even 104 * exist. 105 */ 106 assert(!(ctx->Extensions.ARB_point_sprite 107 || ctx->Extensions.NV_point_sprite) 108 || ctx->Extensions.EXT_point_parameters); 109 110 if (!ctx->Extensions.EXT_point_parameters) { 111 _mesa_error(ctx, GL_INVALID_OPERATION, 112 "unsupported function called (unsupported extension)"); 113 return; 114 } 115 116 switch (pname) { 117 case GL_DISTANCE_ATTENUATION_EXT: 118 if (TEST_EQ_3V(ctx->Point.Params, params)) 119 return; 120 FLUSH_VERTICES(ctx, _NEW_POINT); 121 COPY_3V(ctx->Point.Params, params); 122 ctx->Point._Attenuated = (ctx->Point.Params[0] != 1.0F || 123 ctx->Point.Params[1] != 0.0F || 124 ctx->Point.Params[2] != 0.0F); 125 break; 126 case GL_POINT_SIZE_MIN_EXT: 127 if (params[0] < 0.0F) { 128 _mesa_error( ctx, GL_INVALID_VALUE, 129 "glPointParameterf[v]{EXT,ARB}(param)" ); 130 return; 131 } 132 if (ctx->Point.MinSize == params[0]) 133 return; 134 FLUSH_VERTICES(ctx, _NEW_POINT); 135 ctx->Point.MinSize = params[0]; 136 break; 137 case GL_POINT_SIZE_MAX_EXT: 138 if (params[0] < 0.0F) { 139 _mesa_error( ctx, GL_INVALID_VALUE, 140 "glPointParameterf[v]{EXT,ARB}(param)" ); 141 return; 142 } 143 if (ctx->Point.MaxSize == params[0]) 144 return; 145 FLUSH_VERTICES(ctx, _NEW_POINT); 146 ctx->Point.MaxSize = params[0]; 147 break; 148 case GL_POINT_FADE_THRESHOLD_SIZE_EXT: 149 if (params[0] < 0.0F) { 150 _mesa_error( ctx, GL_INVALID_VALUE, 151 "glPointParameterf[v]{EXT,ARB}(param)" ); 152 return; 153 } 154 if (ctx->Point.Threshold == params[0]) 155 return; 156 FLUSH_VERTICES(ctx, _NEW_POINT); 157 ctx->Point.Threshold = params[0]; 158 break; 159 case GL_POINT_SPRITE_R_MODE_NV: 160 /* This is one area where ARB_point_sprite and NV_point_sprite 161 * differ. In ARB_point_sprite the POINT_SPRITE_R_MODE is 162 * always ZERO. NV_point_sprite adds the S and R modes. 163 */ 164 if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_point_sprite) { 165 GLenum value = (GLenum) params[0]; 166 if (value != GL_ZERO && value != GL_S && value != GL_R) { 167 _mesa_error(ctx, GL_INVALID_VALUE, 168 "glPointParameterf[v]{EXT,ARB}(param)"); 169 return; 170 } 171 if (ctx->Point.SpriteRMode == value) 172 return; 173 FLUSH_VERTICES(ctx, _NEW_POINT); 174 ctx->Point.SpriteRMode = value; 175 } 176 else { 177 _mesa_error(ctx, GL_INVALID_ENUM, 178 "glPointParameterf[v]{EXT,ARB}(pname)"); 179 return; 180 } 181 break; 182 case GL_POINT_SPRITE_COORD_ORIGIN: 183 /* GL_POINT_SPRITE_COORD_ORIGIN was added to point sprites when the 184 * extension was merged into OpenGL 2.0. 185 */ 186 if ((ctx->API == API_OPENGL_COMPAT && ctx->Version >= 20) 187 || ctx->API == API_OPENGL_CORE) { 188 GLenum value = (GLenum) params[0]; 189 if (value != GL_LOWER_LEFT && value != GL_UPPER_LEFT) { 190 _mesa_error(ctx, GL_INVALID_VALUE, 191 "glPointParameterf[v]{EXT,ARB}(param)"); 192 return; 193 } 194 if (ctx->Point.SpriteOrigin == value) 195 return; 196 FLUSH_VERTICES(ctx, _NEW_POINT); 197 ctx->Point.SpriteOrigin = value; 198 } 199 else { 200 _mesa_error(ctx, GL_INVALID_ENUM, 201 "glPointParameterf[v]{EXT,ARB}(pname)"); 202 return; 203 } 204 break; 205 default: 206 _mesa_error( ctx, GL_INVALID_ENUM, 207 "glPointParameterf[v]{EXT,ARB}(pname)" ); 208 return; 209 } 210 211 if (ctx->Driver.PointParameterfv) 212 ctx->Driver.PointParameterfv(ctx, pname, params); 213 } 214 215 216 217 /** 218 * Initialize the context point state. 219 * 220 * \param ctx GL context. 221 * 222 * Initializes __struct gl_contextRec::Point and point related constants in 223 * __struct gl_contextRec::Const. 224 */ 225 void 226 _mesa_init_point(struct gl_context *ctx) 227 { 228 ctx->Point.SmoothFlag = GL_FALSE; 229 ctx->Point.Size = 1.0; 230 ctx->Point.Params[0] = 1.0; 231 ctx->Point.Params[1] = 0.0; 232 ctx->Point.Params[2] = 0.0; 233 ctx->Point._Attenuated = GL_FALSE; 234 ctx->Point.MinSize = 0.0; 235 ctx->Point.MaxSize 236 = MAX2(ctx->Const.MaxPointSize, ctx->Const.MaxPointSizeAA); 237 ctx->Point.Threshold = 1.0; 238 239 /* Page 403 (page 423 of the PDF) of the OpenGL 3.0 spec says: 240 * 241 * "Non-sprite points (section 3.4) - Enable/Disable targets 242 * POINT_SMOOTH and POINT_SPRITE, and all associated state. Point 243 * rasterization is always performed as though POINT_SPRITE were 244 * enabled." 245 * 246 * In a core context, the state will default to true, and the setters and 247 * getters are disabled. 248 */ 249 ctx->Point.PointSprite = (ctx->API == API_OPENGL_CORE || 250 ctx->API == API_OPENGLES2); 251 252 ctx->Point.SpriteRMode = GL_ZERO; /* GL_NV_point_sprite (only!) */ 253 ctx->Point.SpriteOrigin = GL_UPPER_LEFT; /* GL_ARB_point_sprite */ 254 ctx->Point.CoordReplace = 0; /* GL_ARB/NV_point_sprite */ 255 } 256