xref: /third_party/mesa3d/src/mesa/main/rastpos.c (revision bf215546)
1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/**
27 * \file rastpos.c
28 * Raster position operations.
29 */
30
31#include "glheader.h"
32#include "context.h"
33#include "feedback.h"
34#include "macros.h"
35#include "mtypes.h"
36#include "rastpos.h"
37#include "state.h"
38#include "main/light.h"
39#include "main/viewport.h"
40#include "util/bitscan.h"
41
42#include "state_tracker/st_cb_rasterpos.h"
43#include "api_exec_decl.h"
44
45
46/**
47 * Clip a point against the view volume.
48 *
49 * \param v vertex vector describing the point to clip.
50 *
51 * \return zero if outside view volume, or one if inside.
52 */
53static GLuint
54viewclip_point_xy( const GLfloat v[] )
55{
56   if (   v[0] > v[3] || v[0] < -v[3]
57       || v[1] > v[3] || v[1] < -v[3] ) {
58      return 0;
59   }
60   else {
61      return 1;
62   }
63}
64
65
66/**
67 * Clip a point against the near Z clipping planes.
68 *
69 * \param v vertex vector describing the point to clip.
70 *
71 * \return zero if outside view volume, or one if inside.
72 */
73static GLuint
74viewclip_point_near_z( const GLfloat v[] )
75{
76   if (v[2] < -v[3]) {
77      return 0;
78   }
79   else {
80      return 1;
81   }
82}
83
84
85/**
86 * Clip a point against the far Z clipping planes.
87 *
88 * \param v vertex vector describing the point to clip.
89 *
90 * \return zero if outside view volume, or one if inside.
91 */
92static GLuint
93viewclip_point_far_z( const GLfloat v[] )
94{
95   if (v[2] > v[3]) {
96      return 0;
97   }
98   else {
99      return 1;
100   }
101}
102
103
104/**
105 * Clip a point against the user clipping planes.
106 *
107 * \param ctx GL context.
108 * \param v vertex vector describing the point to clip.
109 *
110 * \return zero if the point was clipped, or one otherwise.
111 */
112static GLuint
113userclip_point( struct gl_context *ctx, const GLfloat v[] )
114{
115   GLbitfield mask = ctx->Transform.ClipPlanesEnabled;
116   while (mask) {
117      const int p = u_bit_scan(&mask);
118      GLfloat dot = v[0] * ctx->Transform._ClipUserPlane[p][0]
119         + v[1] * ctx->Transform._ClipUserPlane[p][1]
120         + v[2] * ctx->Transform._ClipUserPlane[p][2]
121         + v[3] * ctx->Transform._ClipUserPlane[p][3];
122
123      if (dot < 0.0F) {
124         return 0;
125      }
126   }
127
128   return 1;
129}
130
131
132/**
133 * Compute lighting for the raster position.  RGB modes computed.
134 * \param ctx the context
135 * \param vertex vertex location
136 * \param normal normal vector
137 * \param Rcolor returned color
138 * \param Rspec returned specular color (if separate specular enabled)
139 */
140static void
141shade_rastpos(struct gl_context *ctx,
142              const GLfloat vertex[4],
143              const GLfloat normal[3],
144              GLfloat Rcolor[4],
145              GLfloat Rspec[4])
146{
147   /*const*/ GLfloat (*base)[3] = ctx->Light._BaseColor;
148   GLbitfield mask;
149   GLfloat diffuseColor[4], specularColor[4];  /* for RGB mode only */
150
151   _mesa_update_light_materials(ctx);
152
153   COPY_3V(diffuseColor, base[0]);
154   diffuseColor[3] = CLAMP(
155      ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3], 0.0F, 1.0F );
156   ASSIGN_4V(specularColor, 0.0, 0.0, 0.0, 1.0);
157
158   mask = ctx->Light._EnabledLights;
159   while (mask) {
160      const int i = u_bit_scan(&mask);
161      struct gl_light *light = &ctx->Light.Light[i];
162      struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
163      GLfloat attenuation = 1.0;
164      GLfloat VP[3]; /* vector from vertex to light pos */
165      GLfloat n_dot_VP;
166      GLfloat diffuseContrib[3], specularContrib[3];
167
168      if (!(light->_Flags & LIGHT_POSITIONAL)) {
169         /* light at infinity */
170	 COPY_3V(VP, light->_VP_inf_norm);
171	 attenuation = light->_VP_inf_spot_attenuation;
172      }
173      else {
174         /* local/positional light */
175	 GLfloat d;
176
177         /* VP = vector from vertex pos to light[i].pos */
178	 SUB_3V(VP, light->_Position, vertex);
179         /* d = length(VP) */
180	 d = (GLfloat) LEN_3FV( VP );
181	 if (d > 1.0e-6F) {
182            /* normalize VP */
183	    GLfloat invd = 1.0F / d;
184	    SELF_SCALE_SCALAR_3V(VP, invd);
185	 }
186
187         /* atti */
188	 attenuation = 1.0F / (lu->ConstantAttenuation + d *
189			       (lu->LinearAttenuation + d *
190				lu->QuadraticAttenuation));
191
192	 if (light->_Flags & LIGHT_SPOT) {
193	    GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
194
195	    if (PV_dot_dir<lu->_CosCutoff) {
196	       continue;
197	    }
198	    else {
199               GLfloat spot = powf(PV_dot_dir, lu->SpotExponent);
200	       attenuation *= spot;
201	    }
202	 }
203      }
204
205      if (attenuation < 1e-3F)
206	 continue;
207
208      n_dot_VP = DOT3( normal, VP );
209
210      if (n_dot_VP < 0.0F) {
211	 ACC_SCALE_SCALAR_3V(diffuseColor, attenuation, light->_MatAmbient[0]);
212	 continue;
213      }
214
215      /* Ambient + diffuse */
216      COPY_3V(diffuseContrib, light->_MatAmbient[0]);
217      ACC_SCALE_SCALAR_3V(diffuseContrib, n_dot_VP, light->_MatDiffuse[0]);
218
219      /* Specular */
220      {
221         const GLfloat *h;
222         GLfloat n_dot_h;
223
224         ASSIGN_3V(specularContrib, 0.0, 0.0, 0.0);
225
226	 if (ctx->Light.Model.LocalViewer) {
227	    GLfloat v[3];
228	    COPY_3V(v, vertex);
229	    NORMALIZE_3FV(v);
230	    SUB_3V(VP, VP, v);
231            NORMALIZE_3FV(VP);
232	    h = VP;
233	 }
234	 else if (light->_Flags & LIGHT_POSITIONAL) {
235	    ACC_3V(VP, ctx->_EyeZDir);
236            NORMALIZE_3FV(VP);
237	    h = VP;
238	 }
239         else {
240	    h = light->_h_inf_norm;
241	 }
242
243	 n_dot_h = DOT3(normal, h);
244
245	 if (n_dot_h > 0.0F) {
246	    GLfloat shine;
247	    GLfloat spec_coef;
248
249	    shine = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0];
250	    spec_coef = powf(n_dot_h, shine);
251
252	    if (spec_coef > 1.0e-10F) {
253               if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
254                  ACC_SCALE_SCALAR_3V( specularContrib, spec_coef,
255                                       light->_MatSpecular[0]);
256               }
257               else {
258                  ACC_SCALE_SCALAR_3V( diffuseContrib, spec_coef,
259                                       light->_MatSpecular[0]);
260               }
261	    }
262	 }
263      }
264
265      ACC_SCALE_SCALAR_3V( diffuseColor, attenuation, diffuseContrib );
266      ACC_SCALE_SCALAR_3V( specularColor, attenuation, specularContrib );
267   }
268
269   Rcolor[0] = CLAMP(diffuseColor[0], 0.0F, 1.0F);
270   Rcolor[1] = CLAMP(diffuseColor[1], 0.0F, 1.0F);
271   Rcolor[2] = CLAMP(diffuseColor[2], 0.0F, 1.0F);
272   Rcolor[3] = CLAMP(diffuseColor[3], 0.0F, 1.0F);
273   Rspec[0] = CLAMP(specularColor[0], 0.0F, 1.0F);
274   Rspec[1] = CLAMP(specularColor[1], 0.0F, 1.0F);
275   Rspec[2] = CLAMP(specularColor[2], 0.0F, 1.0F);
276   Rspec[3] = CLAMP(specularColor[3], 0.0F, 1.0F);
277}
278
279
280/**
281 * Do texgen needed for glRasterPos.
282 * \param ctx  rendering context
283 * \param vObj  object-space vertex coordinate
284 * \param vEye  eye-space vertex coordinate
285 * \param normal  vertex normal
286 * \param unit  texture unit number
287 * \param texcoord  incoming texcoord and resulting texcoord
288 */
289static void
290compute_texgen(struct gl_context *ctx, const GLfloat vObj[4], const GLfloat vEye[4],
291               const GLfloat normal[3], GLuint unit, GLfloat texcoord[4])
292{
293   const struct gl_fixedfunc_texture_unit *texUnit =
294      &ctx->Texture.FixedFuncUnit[unit];
295
296   /* always compute sphere map terms, just in case */
297   GLfloat u[3], two_nu, rx, ry, rz, m, mInv;
298   COPY_3V(u, vEye);
299   NORMALIZE_3FV(u);
300   two_nu = 2.0F * DOT3(normal, u);
301   rx = u[0] - normal[0] * two_nu;
302   ry = u[1] - normal[1] * two_nu;
303   rz = u[2] - normal[2] * two_nu;
304   m = rx * rx + ry * ry + (rz + 1.0F) * (rz + 1.0F);
305   if (m > 0.0F)
306      mInv = 0.5F * (1.0f / sqrtf(m));
307   else
308      mInv = 0.0F;
309
310   if (texUnit->TexGenEnabled & S_BIT) {
311      switch (texUnit->GenS.Mode) {
312         case GL_OBJECT_LINEAR:
313            texcoord[0] = DOT4(vObj, texUnit->ObjectPlane[GEN_S]);
314            break;
315         case GL_EYE_LINEAR:
316            texcoord[0] = DOT4(vEye, texUnit->EyePlane[GEN_S]);
317            break;
318         case GL_SPHERE_MAP:
319            texcoord[0] = rx * mInv + 0.5F;
320            break;
321         case GL_REFLECTION_MAP:
322            texcoord[0] = rx;
323            break;
324         case GL_NORMAL_MAP:
325            texcoord[0] = normal[0];
326            break;
327         default:
328            _mesa_problem(ctx, "Bad S texgen in compute_texgen()");
329            return;
330      }
331   }
332
333   if (texUnit->TexGenEnabled & T_BIT) {
334      switch (texUnit->GenT.Mode) {
335         case GL_OBJECT_LINEAR:
336            texcoord[1] = DOT4(vObj, texUnit->ObjectPlane[GEN_T]);
337            break;
338         case GL_EYE_LINEAR:
339            texcoord[1] = DOT4(vEye, texUnit->EyePlane[GEN_T]);
340            break;
341         case GL_SPHERE_MAP:
342            texcoord[1] = ry * mInv + 0.5F;
343            break;
344         case GL_REFLECTION_MAP:
345            texcoord[1] = ry;
346            break;
347         case GL_NORMAL_MAP:
348            texcoord[1] = normal[1];
349            break;
350         default:
351            _mesa_problem(ctx, "Bad T texgen in compute_texgen()");
352            return;
353      }
354   }
355
356   if (texUnit->TexGenEnabled & R_BIT) {
357      switch (texUnit->GenR.Mode) {
358         case GL_OBJECT_LINEAR:
359            texcoord[2] = DOT4(vObj, texUnit->ObjectPlane[GEN_R]);
360            break;
361         case GL_EYE_LINEAR:
362            texcoord[2] = DOT4(vEye, texUnit->EyePlane[GEN_R]);
363            break;
364         case GL_REFLECTION_MAP:
365            texcoord[2] = rz;
366            break;
367         case GL_NORMAL_MAP:
368            texcoord[2] = normal[2];
369            break;
370         default:
371            _mesa_problem(ctx, "Bad R texgen in compute_texgen()");
372            return;
373      }
374   }
375
376   if (texUnit->TexGenEnabled & Q_BIT) {
377      switch (texUnit->GenQ.Mode) {
378         case GL_OBJECT_LINEAR:
379            texcoord[3] = DOT4(vObj, texUnit->ObjectPlane[GEN_Q]);
380            break;
381         case GL_EYE_LINEAR:
382            texcoord[3] = DOT4(vEye, texUnit->EyePlane[GEN_Q]);
383            break;
384         default:
385            _mesa_problem(ctx, "Bad Q texgen in compute_texgen()");
386            return;
387      }
388   }
389}
390
391
392/**
393 * glRasterPos transformation.
394 *
395 * \param vObj  vertex position in object space
396 */
397void
398_mesa_RasterPos(struct gl_context *ctx, const GLfloat vObj[4])
399{
400   ctx->PopAttribState |= GL_CURRENT_BIT;
401
402   if (_mesa_arb_vertex_program_enabled(ctx)) {
403      /* XXX implement this */
404      _mesa_problem(ctx, "Vertex programs not implemented for glRasterPos");
405      return;
406   }
407   else {
408      GLfloat eye[4], clip[4], ndc[3], d;
409      GLfloat *norm, eyenorm[3];
410      GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
411      float scale[3], translate[3];
412
413      /* apply modelview matrix:  eye = MV * obj */
414      TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, vObj );
415      /* apply projection matrix:  clip = Proj * eye */
416      TRANSFORM_POINT( clip, ctx->ProjectionMatrixStack.Top->m, eye );
417
418      /* clip to view volume. */
419      if (!ctx->Transform.DepthClampNear) {
420         if (viewclip_point_near_z(clip) == 0) {
421            ctx->Current.RasterPosValid = GL_FALSE;
422            return;
423         }
424      }
425      if (!ctx->Transform.DepthClampFar) {
426         if (viewclip_point_far_z(clip) == 0) {
427            ctx->Current.RasterPosValid = GL_FALSE;
428            return;
429         }
430      }
431      if (!ctx->Transform.RasterPositionUnclipped) {
432         if (viewclip_point_xy(clip) == 0) {
433            ctx->Current.RasterPosValid = GL_FALSE;
434            return;
435         }
436      }
437
438      /* clip to user clipping planes */
439      if (ctx->Transform.ClipPlanesEnabled && !userclip_point(ctx, clip)) {
440         ctx->Current.RasterPosValid = GL_FALSE;
441         return;
442      }
443
444      /* ndc = clip / W */
445      d = (clip[3] == 0.0F) ? 1.0F : 1.0F / clip[3];
446      ndc[0] = clip[0] * d;
447      ndc[1] = clip[1] * d;
448      ndc[2] = clip[2] * d;
449      /* wincoord = viewport_mapping(ndc) */
450      _mesa_get_viewport_xform(ctx, 0, scale, translate);
451      ctx->Current.RasterPos[0] = ndc[0] * scale[0] + translate[0];
452      ctx->Current.RasterPos[1] = ndc[1] * scale[1] + translate[1];
453      ctx->Current.RasterPos[2] = ndc[2] * scale[2] + translate[2];
454      ctx->Current.RasterPos[3] = clip[3];
455
456      if (ctx->Transform.DepthClampNear &&
457          ctx->Transform.DepthClampFar) {
458         ctx->Current.RasterPos[3] = CLAMP(ctx->Current.RasterPos[3],
459                                           ctx->ViewportArray[0].Near,
460                                           ctx->ViewportArray[0].Far);
461      } else {
462         /* Clamp against near and far plane separately */
463         if (ctx->Transform.DepthClampNear) {
464            ctx->Current.RasterPos[3] = MAX2(ctx->Current.RasterPos[3],
465                                             ctx->ViewportArray[0].Near);
466         }
467
468         if (ctx->Transform.DepthClampFar) {
469            ctx->Current.RasterPos[3] = MIN2(ctx->Current.RasterPos[3],
470                                             ctx->ViewportArray[0].Far);
471         }
472      }
473
474      /* compute raster distance */
475      if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
476         ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
477      else
478         ctx->Current.RasterDistance =
479                        sqrtf( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );
480
481      /* compute transformed normal vector (for lighting or texgen) */
482      if (ctx->_NeedEyeCoords) {
483         const GLfloat *inv = ctx->ModelviewMatrixStack.Top->inv;
484         TRANSFORM_NORMAL( eyenorm, objnorm, inv );
485         norm = eyenorm;
486      }
487      else {
488         norm = objnorm;
489      }
490
491      /* update raster color */
492      if (ctx->Light.Enabled) {
493         /* lighting */
494         shade_rastpos( ctx, vObj, norm,
495                        ctx->Current.RasterColor,
496                        ctx->Current.RasterSecondaryColor );
497      }
498      else {
499         /* use current color */
500	 COPY_4FV(ctx->Current.RasterColor,
501		  ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
502	 COPY_4FV(ctx->Current.RasterSecondaryColor,
503		  ctx->Current.Attrib[VERT_ATTRIB_COLOR1]);
504      }
505
506      /* texture coords */
507      {
508         GLuint u;
509         for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
510            GLfloat tc[4];
511            COPY_4V(tc, ctx->Current.Attrib[VERT_ATTRIB_TEX0 + u]);
512            if (ctx->Texture.FixedFuncUnit[u].TexGenEnabled) {
513               compute_texgen(ctx, vObj, eye, norm, u, tc);
514            }
515            TRANSFORM_POINT(ctx->Current.RasterTexCoords[u],
516                            ctx->TextureMatrixStack[u].Top->m, tc);
517         }
518      }
519
520      ctx->Current.RasterPosValid = GL_TRUE;
521   }
522
523   if (ctx->RenderMode == GL_SELECT) {
524      _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
525   }
526}
527
528
529/**
530 * Helper function for all the RasterPos functions.
531 */
532static void
533rasterpos(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
534{
535   GET_CURRENT_CONTEXT(ctx);
536   GLfloat p[4];
537
538   p[0] = x;
539   p[1] = y;
540   p[2] = z;
541   p[3] = w;
542
543   FLUSH_VERTICES(ctx, 0, 0);
544   FLUSH_CURRENT(ctx, 0);
545
546   if (ctx->NewState)
547      _mesa_update_state( ctx );
548
549   st_RasterPos(ctx, p);
550}
551
552
553void GLAPIENTRY
554_mesa_RasterPos2d(GLdouble x, GLdouble y)
555{
556   rasterpos((GLfloat)x, (GLfloat)y, (GLfloat)0.0, (GLfloat)1.0);
557}
558
559void GLAPIENTRY
560_mesa_RasterPos2f(GLfloat x, GLfloat y)
561{
562   rasterpos(x, y, 0.0F, 1.0F);
563}
564
565void GLAPIENTRY
566_mesa_RasterPos2i(GLint x, GLint y)
567{
568   rasterpos((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
569}
570
571void GLAPIENTRY
572_mesa_RasterPos2s(GLshort x, GLshort y)
573{
574   rasterpos(x, y, 0.0F, 1.0F);
575}
576
577void GLAPIENTRY
578_mesa_RasterPos3d(GLdouble x, GLdouble y, GLdouble z)
579{
580   rasterpos((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
581}
582
583void GLAPIENTRY
584_mesa_RasterPos3f(GLfloat x, GLfloat y, GLfloat z)
585{
586   rasterpos(x, y, z, 1.0F);
587}
588
589void GLAPIENTRY
590_mesa_RasterPos3i(GLint x, GLint y, GLint z)
591{
592   rasterpos((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
593}
594
595void GLAPIENTRY
596_mesa_RasterPos3s(GLshort x, GLshort y, GLshort z)
597{
598   rasterpos(x, y, z, 1.0F);
599}
600
601void GLAPIENTRY
602_mesa_RasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
603{
604   rasterpos((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
605}
606
607void GLAPIENTRY
608_mesa_RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
609{
610   rasterpos(x, y, z, w);
611}
612
613void GLAPIENTRY
614_mesa_RasterPos4i(GLint x, GLint y, GLint z, GLint w)
615{
616   rasterpos((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
617}
618
619void GLAPIENTRY
620_mesa_RasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w)
621{
622   rasterpos(x, y, z, w);
623}
624
625void GLAPIENTRY
626_mesa_RasterPos2dv(const GLdouble *v)
627{
628   rasterpos((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
629}
630
631void GLAPIENTRY
632_mesa_RasterPos2fv(const GLfloat *v)
633{
634   rasterpos(v[0], v[1], 0.0F, 1.0F);
635}
636
637void GLAPIENTRY
638_mesa_RasterPos2iv(const GLint *v)
639{
640   rasterpos((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
641}
642
643void GLAPIENTRY
644_mesa_RasterPos2sv(const GLshort *v)
645{
646   rasterpos(v[0], v[1], 0.0F, 1.0F);
647}
648
649void GLAPIENTRY
650_mesa_RasterPos3dv(const GLdouble *v)
651{
652   rasterpos((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
653}
654
655void GLAPIENTRY
656_mesa_RasterPos3fv(const GLfloat *v)
657{
658   rasterpos(v[0], v[1], v[2], 1.0F);
659}
660
661void GLAPIENTRY
662_mesa_RasterPos3iv(const GLint *v)
663{
664   rasterpos((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
665}
666
667void GLAPIENTRY
668_mesa_RasterPos3sv(const GLshort *v)
669{
670   rasterpos(v[0], v[1], v[2], 1.0F);
671}
672
673void GLAPIENTRY
674_mesa_RasterPos4dv(const GLdouble *v)
675{
676   rasterpos((GLfloat) v[0], (GLfloat) v[1],
677		     (GLfloat) v[2], (GLfloat) v[3]);
678}
679
680void GLAPIENTRY
681_mesa_RasterPos4fv(const GLfloat *v)
682{
683   rasterpos(v[0], v[1], v[2], v[3]);
684}
685
686void GLAPIENTRY
687_mesa_RasterPos4iv(const GLint *v)
688{
689   rasterpos((GLfloat) v[0], (GLfloat) v[1],
690		     (GLfloat) v[2], (GLfloat) v[3]);
691}
692
693void GLAPIENTRY
694_mesa_RasterPos4sv(const GLshort *v)
695{
696   rasterpos(v[0], v[1], v[2], v[3]);
697}
698
699
700/**********************************************************************/
701/***           GL_ARB_window_pos / GL_MESA_window_pos               ***/
702/**********************************************************************/
703
704
705/**
706 * All glWindowPosMESA and glWindowPosARB commands call this function to
707 * update the current raster position.
708 */
709static void
710window_pos3f(GLfloat x, GLfloat y, GLfloat z)
711{
712   GET_CURRENT_CONTEXT(ctx);
713   GLfloat z2;
714
715   FLUSH_VERTICES(ctx, 0, GL_CURRENT_BIT);
716   FLUSH_CURRENT(ctx, 0);
717
718   z2 = CLAMP(z, 0.0F, 1.0F)
719      * (ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near)
720      + ctx->ViewportArray[0].Near;
721
722   /* set raster position */
723   ctx->Current.RasterPos[0] = x;
724   ctx->Current.RasterPos[1] = y;
725   ctx->Current.RasterPos[2] = z2;
726   ctx->Current.RasterPos[3] = 1.0F;
727
728   ctx->Current.RasterPosValid = GL_TRUE;
729
730   if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
731      ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
732   else
733      ctx->Current.RasterDistance = 0.0;
734
735   /* raster color = current color or index */
736   ctx->Current.RasterColor[0]
737      = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0], 0.0F, 1.0F);
738   ctx->Current.RasterColor[1]
739      = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1], 0.0F, 1.0F);
740   ctx->Current.RasterColor[2]
741      = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2], 0.0F, 1.0F);
742   ctx->Current.RasterColor[3]
743      = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3], 0.0F, 1.0F);
744   ctx->Current.RasterSecondaryColor[0]
745      = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0], 0.0F, 1.0F);
746   ctx->Current.RasterSecondaryColor[1]
747      = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1], 0.0F, 1.0F);
748   ctx->Current.RasterSecondaryColor[2]
749      = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2], 0.0F, 1.0F);
750   ctx->Current.RasterSecondaryColor[3]
751      = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3], 0.0F, 1.0F);
752
753   /* raster texcoord = current texcoord */
754   {
755      GLuint texSet;
756      for (texSet = 0; texSet < ctx->Const.MaxTextureCoordUnits; texSet++) {
757         assert(texSet < ARRAY_SIZE(ctx->Current.RasterTexCoords));
758         COPY_4FV( ctx->Current.RasterTexCoords[texSet],
759                  ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texSet] );
760      }
761   }
762
763   if (ctx->RenderMode==GL_SELECT) {
764      _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
765   }
766}
767
768
769/* This is just to support the GL_MESA_window_pos version */
770static void
771window_pos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
772{
773   GET_CURRENT_CONTEXT(ctx);
774   window_pos3f(x, y, z);
775   ctx->Current.RasterPos[3] = w;
776}
777
778
779void GLAPIENTRY
780_mesa_WindowPos2d(GLdouble x, GLdouble y)
781{
782   window_pos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
783}
784
785void GLAPIENTRY
786_mesa_WindowPos2f(GLfloat x, GLfloat y)
787{
788   window_pos4f(x, y, 0.0F, 1.0F);
789}
790
791void GLAPIENTRY
792_mesa_WindowPos2i(GLint x, GLint y)
793{
794   window_pos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
795}
796
797void GLAPIENTRY
798_mesa_WindowPos2s(GLshort x, GLshort y)
799{
800   window_pos4f(x, y, 0.0F, 1.0F);
801}
802
803void GLAPIENTRY
804_mesa_WindowPos3d(GLdouble x, GLdouble y, GLdouble z)
805{
806   window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
807}
808
809void GLAPIENTRY
810_mesa_WindowPos3f(GLfloat x, GLfloat y, GLfloat z)
811{
812   window_pos4f(x, y, z, 1.0F);
813}
814
815void GLAPIENTRY
816_mesa_WindowPos3i(GLint x, GLint y, GLint z)
817{
818   window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
819}
820
821void GLAPIENTRY
822_mesa_WindowPos3s(GLshort x, GLshort y, GLshort z)
823{
824   window_pos4f(x, y, z, 1.0F);
825}
826
827void GLAPIENTRY
828_mesa_WindowPos4dMESA(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
829{
830   window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
831}
832
833void GLAPIENTRY
834_mesa_WindowPos4fMESA(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
835{
836   window_pos4f(x, y, z, w);
837}
838
839void GLAPIENTRY
840_mesa_WindowPos4iMESA(GLint x, GLint y, GLint z, GLint w)
841{
842   window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
843}
844
845void GLAPIENTRY
846_mesa_WindowPos4sMESA(GLshort x, GLshort y, GLshort z, GLshort w)
847{
848   window_pos4f(x, y, z, w);
849}
850
851void GLAPIENTRY
852_mesa_WindowPos2dv(const GLdouble *v)
853{
854   window_pos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
855}
856
857void GLAPIENTRY
858_mesa_WindowPos2fv(const GLfloat *v)
859{
860   window_pos4f(v[0], v[1], 0.0F, 1.0F);
861}
862
863void GLAPIENTRY
864_mesa_WindowPos2iv(const GLint *v)
865{
866   window_pos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
867}
868
869void GLAPIENTRY
870_mesa_WindowPos2sv(const GLshort *v)
871{
872   window_pos4f(v[0], v[1], 0.0F, 1.0F);
873}
874
875void GLAPIENTRY
876_mesa_WindowPos3dv(const GLdouble *v)
877{
878   window_pos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
879}
880
881void GLAPIENTRY
882_mesa_WindowPos3fv(const GLfloat *v)
883{
884   window_pos4f(v[0], v[1], v[2], 1.0);
885}
886
887void GLAPIENTRY
888_mesa_WindowPos3iv(const GLint *v)
889{
890   window_pos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
891}
892
893void GLAPIENTRY
894_mesa_WindowPos3sv(const GLshort *v)
895{
896   window_pos4f(v[0], v[1], v[2], 1.0F);
897}
898
899void GLAPIENTRY
900_mesa_WindowPos4dvMESA(const GLdouble *v)
901{
902   window_pos4f((GLfloat) v[0], (GLfloat) v[1],
903			 (GLfloat) v[2], (GLfloat) v[3]);
904}
905
906void GLAPIENTRY
907_mesa_WindowPos4fvMESA(const GLfloat *v)
908{
909   window_pos4f(v[0], v[1], v[2], v[3]);
910}
911
912void GLAPIENTRY
913_mesa_WindowPos4ivMESA(const GLint *v)
914{
915   window_pos4f((GLfloat) v[0], (GLfloat) v[1],
916			 (GLfloat) v[2], (GLfloat) v[3]);
917}
918
919void GLAPIENTRY
920_mesa_WindowPos4svMESA(const GLshort *v)
921{
922   window_pos4f(v[0], v[1], v[2], v[3]);
923}
924
925
926#if 0
927
928/*
929 * OpenGL implementation of glWindowPos*MESA()
930 */
931void glWindowPos4fMESA( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
932{
933   GLfloat fx, fy;
934
935   /* Push current matrix mode and viewport attributes */
936   glPushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT );
937
938   /* Setup projection parameters */
939   glMatrixMode( GL_PROJECTION );
940   glPushMatrix();
941   glLoadIdentity();
942   glMatrixMode( GL_MODELVIEW );
943   glPushMatrix();
944   glLoadIdentity();
945
946   glDepthRange( z, z );
947   glViewport( (int) x - 1, (int) y - 1, 2, 2 );
948
949   /* set the raster (window) position */
950   fx = x - (int) x;
951   fy = y - (int) y;
952   glRasterPos4f( fx, fy, 0.0, w );
953
954   /* restore matrices, viewport and matrix mode */
955   glPopMatrix();
956   glMatrixMode( GL_PROJECTION );
957   glPopMatrix();
958
959   glPopAttrib();
960}
961
962#endif
963
964
965/**********************************************************************/
966/** \name Initialization                                              */
967/**********************************************************************/
968/*@{*/
969
970/**
971 * Initialize the context current raster position information.
972 *
973 * \param ctx GL context.
974 *
975 * Initialize the current raster position information in
976 * __struct gl_contextRec::Current, and adds the extension entry points to the
977 * dispatcher.
978 */
979void _mesa_init_rastpos( struct gl_context * ctx )
980{
981   unsigned i;
982
983   ASSIGN_4V( ctx->Current.RasterPos, 0.0, 0.0, 0.0, 1.0 );
984   ctx->Current.RasterDistance = 0.0;
985   ASSIGN_4V( ctx->Current.RasterColor, 1.0, 1.0, 1.0, 1.0 );
986   ASSIGN_4V( ctx->Current.RasterSecondaryColor, 0.0, 0.0, 0.0, 1.0 );
987   for (i = 0; i < ARRAY_SIZE(ctx->Current.RasterTexCoords); i++)
988      ASSIGN_4V( ctx->Current.RasterTexCoords[i], 0.0, 0.0, 0.0, 1.0 );
989   ctx->Current.RasterPosValid = GL_TRUE;
990}
991
992/*@}*/
993