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