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