17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
37117f1b4Smrg *
47117f1b4Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
57117f1b4Smrg *
67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
77117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
87117f1b4Smrg * to deal in the Software without restriction, including without limitation
97117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
107117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
117117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
127117f1b4Smrg *
137117f1b4Smrg * The above copyright notice and this permission notice shall be included
147117f1b4Smrg * in all copies or substantial portions of the Software.
157117f1b4Smrg *
167117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
177117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
237117f1b4Smrg *
247117f1b4Smrg * Authors:
257117f1b4Smrg *    Brian Paul
267117f1b4Smrg */
277117f1b4Smrg
2801e04c3fSmrg#include "c99_math.h"
294a49301eSmrg#include "main/glheader.h"
30c1f859d4Smrg#include "main/mtypes.h"
314a49301eSmrg#include "main/dd.h"
327ec681f3Smrg
337117f1b4Smrg#include "t_context.h"
347117f1b4Smrg#include "t_pipeline.h"
357117f1b4Smrg
367117f1b4Smrg
377117f1b4Smrgstruct point_stage_data {
387117f1b4Smrg   GLvector4f PointSize;
397117f1b4Smrg};
407117f1b4Smrg
417117f1b4Smrg#define POINT_STAGE_DATA(stage) ((struct point_stage_data *)stage->privatePtr)
427117f1b4Smrg
437117f1b4Smrg
447117f1b4Smrg/**
457117f1b4Smrg * Compute point size for each vertex from the vertex eye-space Z
467117f1b4Smrg * coordinate and the point size attenuation factors.
477117f1b4Smrg * Only done when point size attenuation is enabled and vertex program is
487117f1b4Smrg * disabled.
497117f1b4Smrg */
507117f1b4Smrgstatic GLboolean
513464ebd5Sriastradhrun_point_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
527117f1b4Smrg{
537117f1b4Smrg   if (ctx->Point._Attenuated && !ctx->VertexProgram._Current) {
547117f1b4Smrg      struct point_stage_data *store = POINT_STAGE_DATA(stage);
557117f1b4Smrg      struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
567117f1b4Smrg      const GLfloat *eyeCoord = (GLfloat *) VB->EyePtr->data + 2;
577117f1b4Smrg      const GLint eyeCoordStride = VB->EyePtr->stride / sizeof(GLfloat);
587117f1b4Smrg      const GLfloat p0 = ctx->Point.Params[0];
597117f1b4Smrg      const GLfloat p1 = ctx->Point.Params[1];
607117f1b4Smrg      const GLfloat p2 = ctx->Point.Params[2];
617117f1b4Smrg      const GLfloat pointSize = ctx->Point.Size;
627117f1b4Smrg      GLfloat (*size)[4] = store->PointSize.data;
637117f1b4Smrg      GLuint i;
647117f1b4Smrg
657117f1b4Smrg      for (i = 0; i < VB->Count; i++) {
6601e04c3fSmrg         const GLfloat dist = fabsf(*eyeCoord);
677117f1b4Smrg         const GLfloat q = p0 + dist * (p1 + dist * p2);
6801e04c3fSmrg         const GLfloat atten = (q != 0.0F) ? (1.0f / sqrtf(q)) : 1.0F;
697117f1b4Smrg         size[i][0] = pointSize * atten; /* clamping done in rasterization */
707117f1b4Smrg         eyeCoord += eyeCoordStride;
717117f1b4Smrg      }
727117f1b4Smrg
737117f1b4Smrg      VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->PointSize;
747117f1b4Smrg   }
757117f1b4Smrg
767117f1b4Smrg   return GL_TRUE;
777117f1b4Smrg}
787117f1b4Smrg
797117f1b4Smrg
807117f1b4Smrgstatic GLboolean
813464ebd5Sriastradhalloc_point_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
827117f1b4Smrg{
837117f1b4Smrg   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
847117f1b4Smrg   struct point_stage_data *store;
85cdc920a0Smrg   stage->privatePtr = malloc(sizeof(*store));
867117f1b4Smrg   store = POINT_STAGE_DATA(stage);
877117f1b4Smrg   if (!store)
887117f1b4Smrg      return GL_FALSE;
897117f1b4Smrg
907117f1b4Smrg   _mesa_vector4f_alloc( &store->PointSize, 0, VB->Size, 32 );
917117f1b4Smrg   return GL_TRUE;
927117f1b4Smrg}
937117f1b4Smrg
947117f1b4Smrg
957117f1b4Smrgstatic void
967117f1b4Smrgfree_point_data(struct tnl_pipeline_stage *stage)
977117f1b4Smrg{
987117f1b4Smrg   struct point_stage_data *store = POINT_STAGE_DATA(stage);
997117f1b4Smrg   if (store) {
1007117f1b4Smrg      _mesa_vector4f_free( &store->PointSize );
101cdc920a0Smrg      free( store );
1027117f1b4Smrg      stage->privatePtr = NULL;
1037117f1b4Smrg   }
1047117f1b4Smrg}
1057117f1b4Smrg
1067117f1b4Smrg
1077117f1b4Smrgconst struct tnl_pipeline_stage _tnl_point_attenuation_stage =
1087117f1b4Smrg{
1097117f1b4Smrg   "point size attenuation",	/* name */
1107117f1b4Smrg   NULL,			/* stage private data */
1117117f1b4Smrg   alloc_point_data,		/* alloc data */
1127117f1b4Smrg   free_point_data,		/* destructor */
1137117f1b4Smrg   NULL,
1147117f1b4Smrg   run_point_stage		/* run */
1157117f1b4Smrg};
116