1 /**
2  * \file points.c
3  * Point operations.
4  */
5 
6 /*
7  * Mesa 3-D graphics library
8  * Version:  7.1
9  *
10  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
25  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR 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
_mesa_PointSize(GLfloat size)44 _mesa_PointSize( GLfloat size )
45 {
46    GET_CURRENT_CONTEXT(ctx);
47    ASSERT_OUTSIDE_BEGIN_END(ctx);
48 
49    if (size <= 0.0) {
50       _mesa_error( ctx, GL_INVALID_VALUE, "glPointSize" );
51       return;
52    }
53 
54    if (ctx->Point.Size == size)
55       return;
56 
57    FLUSH_VERTICES(ctx, _NEW_POINT);
58    ctx->Point.Size = size;
59 
60    if (ctx->Driver.PointSize)
61       ctx->Driver.PointSize(ctx, size);
62 }
63 
64 
65 #if _HAVE_FULL_GL
66 
67 
68 void GLAPIENTRY
_mesa_PointParameteri(GLenum pname,GLint param)69 _mesa_PointParameteri( GLenum pname, GLint param )
70 {
71    GLfloat p[3];
72    p[0] = (GLfloat) param;
73    p[1] = p[2] = 0.0F;
74    _mesa_PointParameterfv(pname, p);
75 }
76 
77 
78 void GLAPIENTRY
_mesa_PointParameteriv(GLenum pname,const GLint * params)79 _mesa_PointParameteriv( GLenum pname, const GLint *params )
80 {
81    GLfloat p[3];
82    p[0] = (GLfloat) params[0];
83    if (pname == GL_DISTANCE_ATTENUATION_EXT) {
84       p[1] = (GLfloat) params[1];
85       p[2] = (GLfloat) params[2];
86    }
87    _mesa_PointParameterfv(pname, p);
88 }
89 
90 
91 void GLAPIENTRY
_mesa_PointParameterf(GLenum pname,GLfloat param)92 _mesa_PointParameterf( GLenum pname, GLfloat param)
93 {
94    GLfloat p[3];
95    p[0] = param;
96    p[1] = p[2] = 0.0F;
97    _mesa_PointParameterfv(pname, p);
98 }
99 
100 
101 void GLAPIENTRY
_mesa_PointParameterfv(GLenum pname,const GLfloat * params)102 _mesa_PointParameterfv( GLenum pname, const GLfloat *params)
103 {
104    GET_CURRENT_CONTEXT(ctx);
105    ASSERT_OUTSIDE_BEGIN_END(ctx);
106 
107    /* Drivers that support point sprites must also support point parameters.
108     * If point parameters aren't supported, then this function shouldn't even
109     * exist.
110     */
111    ASSERT(!(ctx->Extensions.ARB_point_sprite
112             || ctx->Extensions.NV_point_sprite)
113           || ctx->Extensions.EXT_point_parameters);
114 
115    if (!ctx->Extensions.EXT_point_parameters) {
116       _mesa_error(ctx, GL_INVALID_OPERATION,
117                   "unsupported function called (unsupported extension)");
118       return;
119    }
120 
121    switch (pname) {
122       case GL_DISTANCE_ATTENUATION_EXT:
123          if (TEST_EQ_3V(ctx->Point.Params, params))
124             return;
125          FLUSH_VERTICES(ctx, _NEW_POINT);
126          COPY_3V(ctx->Point.Params, params);
127          ctx->Point._Attenuated = (ctx->Point.Params[0] != 1.0 ||
128                                    ctx->Point.Params[1] != 0.0 ||
129                                    ctx->Point.Params[2] != 0.0);
130 
131          if (ctx->Point._Attenuated)
132             ctx->_TriangleCaps |= DD_POINT_ATTEN;
133          else
134             ctx->_TriangleCaps &= ~DD_POINT_ATTEN;
135          break;
136       case GL_POINT_SIZE_MIN_EXT:
137          if (params[0] < 0.0F) {
138             _mesa_error( ctx, GL_INVALID_VALUE,
139                          "glPointParameterf[v]{EXT,ARB}(param)" );
140             return;
141          }
142          if (ctx->Point.MinSize == params[0])
143             return;
144          FLUSH_VERTICES(ctx, _NEW_POINT);
145          ctx->Point.MinSize = params[0];
146          break;
147       case GL_POINT_SIZE_MAX_EXT:
148          if (params[0] < 0.0F) {
149             _mesa_error( ctx, GL_INVALID_VALUE,
150                          "glPointParameterf[v]{EXT,ARB}(param)" );
151             return;
152          }
153          if (ctx->Point.MaxSize == params[0])
154             return;
155          FLUSH_VERTICES(ctx, _NEW_POINT);
156          ctx->Point.MaxSize = params[0];
157          break;
158       case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
159          if (params[0] < 0.0F) {
160             _mesa_error( ctx, GL_INVALID_VALUE,
161                          "glPointParameterf[v]{EXT,ARB}(param)" );
162             return;
163          }
164          if (ctx->Point.Threshold == params[0])
165             return;
166          FLUSH_VERTICES(ctx, _NEW_POINT);
167          ctx->Point.Threshold = params[0];
168          break;
169       case GL_POINT_SPRITE_R_MODE_NV:
170          /* This is one area where ARB_point_sprite and NV_point_sprite
171 	  * differ.  In ARB_point_sprite the POINT_SPRITE_R_MODE is
172 	  * always ZERO.  NV_point_sprite adds the S and R modes.
173 	  */
174          if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.NV_point_sprite) {
175             GLenum value = (GLenum) params[0];
176             if (value != GL_ZERO && value != GL_S && value != GL_R) {
177                _mesa_error(ctx, GL_INVALID_VALUE,
178                            "glPointParameterf[v]{EXT,ARB}(param)");
179                return;
180             }
181             if (ctx->Point.SpriteRMode == value)
182                return;
183             FLUSH_VERTICES(ctx, _NEW_POINT);
184             ctx->Point.SpriteRMode = value;
185          }
186          else {
187             _mesa_error(ctx, GL_INVALID_ENUM,
188                         "glPointParameterf[v]{EXT,ARB}(pname)");
189             return;
190          }
191          break;
192       case GL_POINT_SPRITE_COORD_ORIGIN:
193 	 /* GL_POINT_SPRITE_COORD_ORIGIN was added to point sprites when the
194 	  * extension was merged into OpenGL 2.0.
195 	  */
196          if ((ctx->API == API_OPENGL && ctx->Version >= 20)
197              || ctx->API == API_OPENGL_CORE) {
198             GLenum value = (GLenum) params[0];
199             if (value != GL_LOWER_LEFT && value != GL_UPPER_LEFT) {
200                _mesa_error(ctx, GL_INVALID_VALUE,
201                            "glPointParameterf[v]{EXT,ARB}(param)");
202                return;
203             }
204             if (ctx->Point.SpriteOrigin == value)
205                return;
206             FLUSH_VERTICES(ctx, _NEW_POINT);
207             ctx->Point.SpriteOrigin = value;
208          }
209          else {
210             _mesa_error(ctx, GL_INVALID_ENUM,
211                         "glPointParameterf[v]{EXT,ARB}(pname)");
212             return;
213          }
214          break;
215       default:
216          _mesa_error( ctx, GL_INVALID_ENUM,
217                       "glPointParameterf[v]{EXT,ARB}(pname)" );
218          return;
219    }
220 
221    if (ctx->Driver.PointParameterfv)
222       (*ctx->Driver.PointParameterfv)(ctx, pname, params);
223 }
224 #endif
225 
226 
227 
228 /**
229  * Initialize the context point state.
230  *
231  * \param ctx GL context.
232  *
233  * Initializes __struct gl_contextRec::Point and point related constants in
234  * __struct gl_contextRec::Const.
235  */
236 void
_mesa_init_point(struct gl_context * ctx)237 _mesa_init_point(struct gl_context *ctx)
238 {
239    GLuint i;
240 
241    ctx->Point.SmoothFlag = GL_FALSE;
242    ctx->Point.Size = 1.0;
243    ctx->Point.Params[0] = 1.0;
244    ctx->Point.Params[1] = 0.0;
245    ctx->Point.Params[2] = 0.0;
246    ctx->Point._Attenuated = GL_FALSE;
247    ctx->Point.MinSize = 0.0;
248    ctx->Point.MaxSize
249       = MAX2(ctx->Const.MaxPointSize, ctx->Const.MaxPointSizeAA);
250    ctx->Point.Threshold = 1.0;
251 
252    /* Page 403 (page 423 of the PDF) of the OpenGL 3.0 spec says:
253     *
254     *     "Non-sprite points (section 3.4) - Enable/Disable targets
255     *     POINT_SMOOTH and POINT_SPRITE, and all associated state. Point
256     *     rasterization is always performed as though POINT_SPRITE were
257     *     enabled."
258     *
259     * In a core context, the state will default to true, and the setters and
260     * getters are disabled.
261     */
262    ctx->Point.PointSprite = (ctx->API == API_OPENGL_CORE);
263 
264    ctx->Point.SpriteRMode = GL_ZERO; /* GL_NV_point_sprite (only!) */
265    ctx->Point.SpriteOrigin = GL_UPPER_LEFT; /* GL_ARB_point_sprite */
266    for (i = 0; i < Elements(ctx->Point.CoordReplace); i++) {
267       ctx->Point.CoordReplace[i] = GL_FALSE; /* GL_ARB/NV_point_sprite */
268    }
269 }
270