| /* $Id: s_points.c,v 1.5 2000/11/15 16:38:40 brianp Exp $ */ |
| |
| /* |
| * Mesa 3-D graphics library |
| * Version: 3.4 |
| * |
| * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| |
| #include "glheader.h" |
| #include "context.h" |
| #include "macros.h" |
| #include "mmath.h" |
| #include "texstate.h" |
| #include "vb.h" |
| |
| #include "s_context.h" |
| #include "s_feedback.h" |
| #include "s_pb.h" |
| #include "s_points.h" |
| #include "s_span.h" |
| |
| |
| /**********************************************************************/ |
| /***** Rasterization *****/ |
| /**********************************************************************/ |
| |
| |
| /* |
| * There are 3 pairs (RGBA, CI) of point rendering functions: |
| * 1. simple: size=1 and no special rasterization functions (fastest) |
| * 2. size1: size=1 and any rasterization functions |
| * 3. general: any size and rasterization functions (slowest) |
| * |
| */ |
| |
| |
| |
| |
| |
| /* |
| * CI points with size == 1.0 |
| */ |
| static void |
| size1_ci_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; |
| GLint *pbx = PB->x, *pby = PB->y; |
| GLdepth *pbz = PB->z; |
| GLfixed *pbfog = PB->fog; |
| GLuint *pbi = PB->index; |
| GLuint pbcount = PB->count; |
| |
| pbx[pbcount] = (GLint) vert->win[0]; |
| pby[pbcount] = (GLint) vert->win[1]; |
| pbz[pbcount] = (GLint) vert->win[2]; |
| pbfog[pbcount] = FloatToFixed(vert->fog); |
| pbi[pbcount] = vert->index; |
| |
| PB->count++; |
| PB_CHECK_FLUSH(ctx, PB); |
| } |
| |
| |
| |
| /* |
| * RGBA points with size == 1.0 |
| */ |
| static void |
| size1_rgba_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; |
| |
| GLint x = (GLint) vert->win[0]; |
| GLint y = (GLint) vert->win[1]; |
| GLint z = (GLint) (vert->win[2]); |
| GLfixed fog = FloatToFixed( vert->fog ); |
| GLubyte red = vert->color[0]; |
| GLubyte green = vert->color[1]; |
| GLubyte blue = vert->color[2]; |
| GLubyte alpha = vert->color[3]; |
| |
| PB_WRITE_RGBA_PIXEL( PB, x, y, z, fog, red, green, blue, alpha ); |
| PB_CHECK_FLUSH(ctx, PB); |
| } |
| |
| |
| |
| /* |
| * General CI points. |
| */ |
| static void |
| general_ci_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; |
| const GLint isize = (GLint) (ctx->Point._Size + 0.5F); |
| GLint radius = isize >> 1; |
| |
| GLint x0, x1, y0, y1; |
| GLint ix, iy; |
| |
| GLint x = (GLint) vert->win[0]; |
| GLint y = (GLint) vert->win[1]; |
| GLint z = (GLint) (vert->win[2]); |
| |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| if (isize & 1) { |
| /* odd size */ |
| x0 = x - radius; |
| x1 = x + radius; |
| y0 = y - radius; |
| y1 = y + radius; |
| } |
| else { |
| /* even size */ |
| x0 = (GLint) (x + 1.5F) - radius; |
| x1 = x0 + isize - 1; |
| y0 = (GLint) (y + 1.5F) - radius; |
| y1 = y0 + isize - 1; |
| } |
| |
| PB_SET_INDEX( PB, vert->index ); |
| |
| for (iy = y0; iy <= y1; iy++) { |
| for (ix = x0; ix <= x1; ix++) { |
| PB_WRITE_PIXEL( PB, ix, iy, z, fog ); |
| } |
| } |
| PB_CHECK_FLUSH(ctx,PB); |
| } |
| |
| |
| /* |
| * General RGBA points. |
| */ |
| static void |
| general_rgba_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; |
| GLint isize = (GLint) (ctx->Point._Size + 0.5F); |
| GLint radius = isize >> 1; |
| |
| GLint x0, x1, y0, y1; |
| GLint ix, iy; |
| |
| GLint x = (GLint) vert->win[0]; |
| GLint y = (GLint) vert->win[1]; |
| GLint z = (GLint) (vert->win[2]); |
| |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| if (isize & 1) { |
| /* odd size */ |
| x0 = x - radius; |
| x1 = x + radius; |
| y0 = y - radius; |
| y1 = y + radius; |
| } |
| else { |
| /* even size */ |
| x0 = (GLint) (x + 1.5F) - radius; |
| x1 = x0 + isize - 1; |
| y0 = (GLint) (y + 1.5F) - radius; |
| y1 = y0 + isize - 1; |
| } |
| |
| PB_SET_COLOR( PB, |
| vert->color[0], |
| vert->color[1], |
| vert->color[2], |
| vert->color[3] ); |
| |
| for (iy = y0; iy <= y1; iy++) { |
| for (ix = x0; ix <= x1; ix++) { |
| PB_WRITE_PIXEL( PB, ix, iy, z, fog ); |
| } |
| } |
| PB_CHECK_FLUSH(ctx,PB); |
| } |
| |
| |
| |
| |
| /* |
| * Textured RGBA points. |
| */ |
| static void |
| textured_rgba_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; |
| |
| GLint x0, x1, y0, y1; |
| GLint ix, iy, radius; |
| GLint red, green, blue, alpha; |
| GLfloat s, t, u; |
| |
| GLint x = (GLint) vert->win[0]; |
| GLint y = (GLint) vert->win[1]; |
| GLint z = (GLint) (vert->win[2]); |
| GLint isize = (GLint) (ctx->Point._Size + 0.5F); |
| |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| if (isize < 1) { |
| isize = 1; |
| } |
| radius = isize >> 1; |
| |
| if (isize & 1) { |
| /* odd size */ |
| x0 = x - radius; |
| x1 = x + radius; |
| y0 = y - radius; |
| y1 = y + radius; |
| } |
| else { |
| /* even size */ |
| x0 = (GLint) (x + 1.5F) - radius; |
| x1 = x0 + isize - 1; |
| y0 = (GLint) (y + 1.5F) - radius; |
| y1 = y0 + isize - 1; |
| } |
| |
| red = vert->color[0]; |
| green = vert->color[1]; |
| blue = vert->color[2]; |
| alpha = vert->color[3]; |
| |
| if (vert->texcoord[0][3] != 1.0) { |
| s = vert->texcoord[0][0]/vert->texcoord[0][3]; |
| t = vert->texcoord[0][1]/vert->texcoord[0][3]; |
| u = vert->texcoord[0][2]/vert->texcoord[0][3]; |
| } else { |
| s = vert->texcoord[0][0]; |
| t = vert->texcoord[0][1]; |
| u = vert->texcoord[0][2]; |
| } |
| |
| for (iy = y0; iy <= y1; iy++) { |
| for (ix = x0; ix <= x1; ix++) { |
| PB_WRITE_TEX_PIXEL( PB, ix, iy, z, fog, red, green, blue, alpha, |
| s, t, u ); |
| } |
| } |
| |
| PB_CHECK_FLUSH(ctx, PB); |
| } |
| |
| |
| |
| /* |
| * Multitextured RGBA points. |
| */ |
| static void |
| multitextured_rgba_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; |
| |
| const GLint red = vert->color[0]; |
| const GLint green = vert->color[1]; |
| const GLint blue = vert->color[2]; |
| const GLint alpha = vert->color[3]; |
| const GLint sRed = vert->specular[0]; |
| const GLint sGreen = vert->specular[1]; |
| const GLint sBlue = vert->specular[2]; |
| const GLint x = (GLint) vert->win[0]; |
| const GLint y = (GLint) vert->win[1]; |
| const GLint z = (GLint) (vert->win[2]); |
| GLint x0, x1, y0, y1; |
| GLint ix, iy; |
| GLfloat texcoord[MAX_TEXTURE_UNITS][4]; |
| GLint radius, u; |
| GLint isize = (GLint) (ctx->Point._Size + 0.5F); |
| |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| if (isize < 1) { |
| isize = 1; |
| } |
| radius = isize >> 1; |
| |
| if (isize & 1) { |
| /* odd size */ |
| x0 = x - radius; |
| x1 = x + radius; |
| y0 = y - radius; |
| y1 = y + radius; |
| } |
| else { |
| /* even size */ |
| x0 = (GLint) (x + 1.5F) - radius; |
| x1 = x0 + isize - 1; |
| y0 = (GLint) (y + 1.5F) - radius; |
| y1 = y0 + isize - 1; |
| } |
| |
| for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { |
| if (ctx->Texture.Unit[u]._ReallyEnabled) { |
| if (vert->texcoord[u][3] != 1.0) { |
| texcoord[u][0] = vert->texcoord[u][0] / |
| vert->texcoord[u][3]; |
| texcoord[u][1] = vert->texcoord[u][1] / |
| vert->texcoord[u][3]; |
| texcoord[u][2] = vert->texcoord[u][2] / |
| vert->texcoord[u][3]; |
| } |
| else { |
| texcoord[u][0] = vert->texcoord[u][0]; |
| texcoord[u][1] = vert->texcoord[u][1]; |
| texcoord[u][2] = vert->texcoord[u][2]; |
| } |
| } |
| } |
| |
| for (iy = y0; iy <= y1; iy++) { |
| for (ix = x0; ix <= x1; ix++) { |
| PB_WRITE_MULTITEX_SPEC_PIXEL( PB, ix, iy, z, fog, |
| red, green, blue, alpha, |
| sRed, sGreen, sBlue, |
| texcoord ); |
| } |
| } |
| PB_CHECK_FLUSH(ctx, PB); |
| } |
| |
| |
| /* |
| * NOTES on aa point rasterization: |
| * |
| * Let d = distance of fragment center from vertex. |
| * if d < rmin2 then |
| * fragment has 100% coverage |
| * else if d > rmax2 then |
| * fragment has 0% coverage |
| * else |
| * fragement has % coverage = (d - rmin2) / (rmax2 - rmin2) |
| */ |
| |
| |
| /* |
| * Antialiased points with or without texture mapping. |
| */ |
| static void |
| antialiased_rgba_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| SWcontext *swrast = SWRAST_CONTEXT(ctx); |
| struct pixel_buffer *PB = swrast->PB; |
| const GLfloat radius = ctx->Point._Size * 0.5F; |
| const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ |
| const GLfloat rmax = radius + 0.7071F; |
| const GLfloat rmin2 = MAX2(0.0, rmin * rmin); |
| const GLfloat rmax2 = rmax * rmax; |
| const GLfloat cscale = 256.0F / (rmax2 - rmin2); |
| |
| if (ctx->Texture._ReallyEnabled) { |
| GLint x, y; |
| GLfloat vx = vert->win[0]; |
| GLfloat vy = vert->win[1]; |
| const GLint xmin = (GLint) (vx - radius); |
| const GLint xmax = (GLint) (vx + radius); |
| const GLint ymin = (GLint) (vy - radius); |
| const GLint ymax = (GLint) (vy + radius); |
| const GLint z = (GLint) (vert->win[2]); |
| const GLint red = vert->color[0]; |
| const GLint green = vert->color[1]; |
| const GLint blue = vert->color[2]; |
| GLfloat texcoord[MAX_TEXTURE_UNITS][4]; |
| GLint u, alpha; |
| |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { |
| if (ctx->Texture.Unit[u]._ReallyEnabled) { |
| if (texcoord[u][3] != 1.0) { |
| texcoord[u][0] = (vert->texcoord[u][0] / |
| vert->texcoord[u][3]); |
| texcoord[u][1] = (vert->texcoord[u][1] / |
| vert->texcoord[u][3]); |
| texcoord[u][2] = (vert->texcoord[u][2] / |
| vert->texcoord[u][3]); |
| } |
| else { |
| texcoord[u][0] = vert->texcoord[u][0]; |
| texcoord[u][1] = vert->texcoord[u][1]; |
| texcoord[u][2] = vert->texcoord[u][2]; |
| } |
| } |
| } |
| |
| /* translate by a half pixel to simplify math below */ |
| vx -= 0.5F; |
| vx -= 0.5F; |
| |
| for (y = ymin; y <= ymax; y++) { |
| for (x = xmin; x <= xmax; x++) { |
| const GLfloat dx = x - vx; |
| const GLfloat dy = y - vy; |
| const GLfloat dist2 = dx*dx + dy*dy; |
| if (dist2 < rmax2) { |
| alpha = vert->color[3]; |
| if (dist2 >= rmin2) { |
| GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale); |
| /* coverage is in [0,256] */ |
| alpha = (alpha * coverage) >> 8; |
| } |
| if (swrast->_MultiTextureEnabled) { |
| PB_WRITE_MULTITEX_PIXEL( PB, x,y,z, fog, |
| red, green, blue, |
| alpha, texcoord ); |
| } |
| else { |
| PB_WRITE_TEX_PIXEL( PB, x,y,z, fog, |
| red, green, blue, alpha, |
| texcoord[0][0], |
| texcoord[0][1], |
| texcoord[0][2] ); |
| } |
| } |
| } |
| } |
| |
| PB_CHECK_FLUSH(ctx,PB); |
| } |
| else { |
| /* Not texture mapped */ |
| const GLint xmin = (GLint) (vert->win[0] - 0.0 - radius); |
| const GLint xmax = (GLint) (vert->win[0] - 0.0 + radius); |
| const GLint ymin = (GLint) (vert->win[1] - 0.0 - radius); |
| const GLint ymax = (GLint) (vert->win[1] - 0.0 + radius); |
| const GLint red = vert->color[0]; |
| const GLint green = vert->color[1]; |
| const GLint blue = vert->color[2]; |
| const GLint z = (GLint) (vert->win[2]); |
| GLint x, y; |
| |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| /* |
| printf("point %g, %g\n", vert->win[0], vert->win[1]); |
| printf("%d..%d X %d..%d\n", xmin, xmax, ymin, ymax); |
| */ |
| for (y = ymin; y <= ymax; y++) { |
| for (x = xmin; x <= xmax; x++) { |
| const GLfloat dx = x + 0.5F - vert->win[0]; |
| const GLfloat dy = y + 0.5F - vert->win[1]; |
| const GLfloat dist2 = dx*dx + dy*dy; |
| if (dist2 < rmax2) { |
| GLint alpha = vert->color[3]; |
| if (dist2 >= rmin2) { |
| GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale); |
| /* coverage is in [0,256] */ |
| alpha = (alpha * coverage) >> 8; |
| } |
| PB_WRITE_RGBA_PIXEL(PB, x, y, z, fog, |
| red, green, blue, alpha); |
| } |
| } |
| } |
| PB_CHECK_FLUSH(ctx,PB); |
| } |
| } |
| |
| |
| |
| /* Definition of the functions for GL_EXT_point_parameters */ |
| |
| /* Calculates the distance attenuation formula of a vector of points in |
| * eye space coordinates |
| */ |
| static GLfloat attenuation_distance(const GLcontext *ctx, const GLfloat *pos) |
| { |
| GLfloat dist = GL_SQRT(pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]); |
| return 1.0F / (ctx->Point.Params[0] + |
| dist * (ctx->Point.Params[1] + |
| dist * ctx->Point.Params[2])); |
| } |
| |
| |
| |
| |
| |
| /* |
| * Distance Attenuated General CI points. |
| */ |
| static void |
| dist_atten_general_ci_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; |
| const GLfloat psize = ctx->Point._Size; |
| GLfloat dist = attenuation_distance( ctx, vert->eye ); |
| GLint x0, x1, y0, y1; |
| GLint ix, iy; |
| GLint isize, radius; |
| GLint x = (GLint) vert->win[0]; |
| GLint y = (GLint) vert->win[1]; |
| GLint z = (GLint) (vert->win[2]); |
| GLfloat dsize = psize * dist; |
| |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| if (dsize >= ctx->Point.Threshold) { |
| isize = (GLint) (MIN2(dsize, ctx->Point.MaxSize) + 0.5F); |
| } |
| else { |
| isize = (GLint) (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) + 0.5F); |
| } |
| radius = isize >> 1; |
| |
| if (isize & 1) { |
| /* odd size */ |
| x0 = x - radius; |
| x1 = x + radius; |
| y0 = y - radius; |
| y1 = y + radius; |
| } |
| else { |
| /* even size */ |
| x0 = (GLint) (x + 1.5F) - radius; |
| x1 = x0 + isize - 1; |
| y0 = (GLint) (y + 1.5F) - radius; |
| y1 = y0 + isize - 1; |
| } |
| |
| PB_SET_INDEX( PB, vert->index ); |
| |
| for (iy=y0;iy<=y1;iy++) { |
| for (ix=x0;ix<=x1;ix++) { |
| PB_WRITE_PIXEL( PB, ix, iy, z, fog ); |
| } |
| } |
| PB_CHECK_FLUSH(ctx,PB); |
| } |
| |
| /* |
| * Distance Attenuated General RGBA points. |
| */ |
| static void |
| dist_atten_general_rgba_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| struct pixel_buffer *PB = SWRAST_CONTEXT(ctx)->PB; |
| const GLfloat psize = ctx->Point._Size; |
| GLfloat dist = attenuation_distance( ctx, vert->eye ); |
| GLint x0, x1, y0, y1; |
| GLint ix, iy; |
| GLint isize, radius; |
| GLint x = (GLint) vert->win[0]; |
| GLint y = (GLint) vert->win[1]; |
| GLint z = (GLint) (vert->win[2]); |
| GLfloat dsize=psize*dist; |
| GLchan alpha; |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| if (dsize >= ctx->Point.Threshold) { |
| isize = (GLint) (MIN2(dsize,ctx->Point.MaxSize)+0.5F); |
| alpha = vert->color[3]; |
| } |
| else { |
| isize = (GLint) (MAX2(ctx->Point.Threshold,ctx->Point.MinSize)+0.5F); |
| dsize /= ctx->Point.Threshold; |
| alpha = (GLint) (vert->color[3]* (dsize*dsize)); |
| } |
| radius = isize >> 1; |
| |
| if (isize & 1) { |
| /* odd size */ |
| x0 = x - radius; |
| x1 = x + radius; |
| y0 = y - radius; |
| y1 = y + radius; |
| } |
| else { |
| /* even size */ |
| x0 = (GLint) (x + 1.5F) - radius; |
| x1 = x0 + isize - 1; |
| y0 = (GLint) (y + 1.5F) - radius; |
| y1 = y0 + isize - 1; |
| } |
| |
| PB_SET_COLOR( PB, |
| vert->color[0], |
| vert->color[1], |
| vert->color[2], |
| alpha ); |
| |
| for (iy = y0; iy <= y1; iy++) { |
| for (ix = x0; ix <= x1; ix++) { |
| PB_WRITE_PIXEL( PB, ix, iy, z, fog ); |
| } |
| } |
| PB_CHECK_FLUSH(ctx,PB); |
| } |
| |
| /* |
| * Distance Attenuated Textured RGBA points. |
| */ |
| static void |
| dist_atten_textured_rgba_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| SWcontext *swrast = SWRAST_CONTEXT(ctx); |
| struct pixel_buffer *PB = swrast->PB; |
| const GLfloat psize = ctx->Point._Size; |
| GLfloat dist = attenuation_distance( ctx, vert->eye ); |
| |
| const GLint x = (GLint) vert->win[0]; |
| const GLint y = (GLint) vert->win[1]; |
| const GLint z = (GLint) (vert->win[2]); |
| const GLint red = vert->color[0]; |
| const GLint green = vert->color[1]; |
| const GLint blue = vert->color[2]; |
| GLfloat texcoord[MAX_TEXTURE_UNITS][4]; |
| GLint x0, x1, y0, y1; |
| GLint ix, iy, alpha, u; |
| GLint isize, radius; |
| GLfloat dsize = psize*dist; |
| |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| /* compute point size and alpha */ |
| if (dsize >= ctx->Point.Threshold) { |
| isize = (GLint) (MIN2(dsize, ctx->Point.MaxSize) + 0.5F); |
| alpha = vert->color[3]; |
| } |
| else { |
| isize = (GLint) (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) + 0.5F); |
| dsize /= ctx->Point.Threshold; |
| alpha = (GLint) (vert->color[3] * (dsize * dsize)); |
| } |
| if (isize < 1) { |
| isize = 1; |
| } |
| radius = isize >> 1; |
| |
| if (isize & 1) { |
| /* odd size */ |
| x0 = x - radius; |
| x1 = x + radius; |
| y0 = y - radius; |
| y1 = y + radius; |
| } |
| else { |
| /* even size */ |
| x0 = (GLint) (x + 1.5F) - radius; |
| x1 = x0 + isize - 1; |
| y0 = (GLint) (y + 1.5F) - radius; |
| y1 = y0 + isize - 1; |
| } |
| |
| /* get texture coordinates */ |
| for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { |
| if (ctx->Texture.Unit[u]._ReallyEnabled) { |
| if (texcoord[u][3] != 1.0) { |
| texcoord[u][0] = vert->texcoord[u][0] / |
| vert->texcoord[u][3]; |
| texcoord[u][1] = vert->texcoord[u][1] / |
| vert->texcoord[u][3]; |
| texcoord[u][2] = vert->texcoord[u][2] / |
| vert->texcoord[u][3]; |
| } |
| else { |
| texcoord[u][0] = vert->texcoord[u][0]; |
| texcoord[u][1] = vert->texcoord[u][1]; |
| texcoord[u][2] = vert->texcoord[u][2]; |
| } |
| } |
| } |
| |
| for (iy = y0; iy <= y1; iy++) { |
| for (ix = x0; ix <= x1; ix++) { |
| if (swrast->_MultiTextureEnabled) { |
| PB_WRITE_MULTITEX_PIXEL( PB, ix, iy, z, fog, |
| red, green, blue, alpha, |
| texcoord ); |
| } |
| else { |
| PB_WRITE_TEX_PIXEL( PB, ix, iy, z, fog, |
| red, green, blue, alpha, |
| texcoord[0][0], |
| texcoord[0][1], |
| texcoord[0][2] ); |
| } |
| } |
| } |
| PB_CHECK_FLUSH(ctx,PB); |
| } |
| |
| /* |
| * Distance Attenuated Antialiased points with or without texture mapping. |
| */ |
| static void |
| dist_atten_antialiased_rgba_point( GLcontext *ctx, SWvertex *vert ) |
| { |
| SWcontext *swrast = SWRAST_CONTEXT(ctx); |
| struct pixel_buffer *PB = swrast->PB; |
| const GLfloat psize = ctx->Point._Size; |
| GLfloat dist = attenuation_distance( ctx, vert->eye ); |
| |
| if (ctx->Texture._ReallyEnabled) { |
| GLfloat radius, rmin, rmax, rmin2, rmax2, cscale, alphaf; |
| GLint xmin, ymin, xmax, ymax; |
| GLint x, y, z; |
| GLint red, green, blue, alpha; |
| GLfloat texcoord[MAX_TEXTURE_UNITS][4]; |
| GLfloat dsize = psize * dist; |
| GLint u; |
| |
| GLfixed fog = FloatToFixed( vert->fog ); |
| |
| if (dsize >= ctx->Point.Threshold) { |
| radius = MIN2(dsize, ctx->Point.MaxSize) * 0.5F; |
| alphaf = 1.0F; |
| } |
| else { |
| radius = (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) * 0.5F); |
| dsize /= ctx->Point.Threshold; |
| alphaf = (dsize*dsize); |
| } |
| rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ |
| rmax = radius + 0.7071F; |
| rmin2 = MAX2(0.0, rmin * rmin); |
| rmax2 = rmax * rmax; |
| cscale = 256.0F / (rmax2 - rmin2); |
| |
| xmin = (GLint) (vert->win[0] - radius); |
| xmax = (GLint) (vert->win[0] + radius); |
| ymin = (GLint) (vert->win[1] - radius); |
| ymax = (GLint) (vert->win[1] + radius); |
| z = (GLint) (vert->win[2]); |
| |
| red = vert->color[0]; |
| green = vert->color[1]; |
| blue = vert->color[2]; |
| |
| /* get texture coordinates */ |
| for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { |
| if (ctx->Texture.Unit[u]._ReallyEnabled) { |
| if (vert->texcoord[u][3] != 1.0 && vert->texcoord[u][3] != 0.0) { |
| texcoord[u][0] = vert->texcoord[u][0] / vert->texcoord[u][3]; |
| texcoord[u][1] = vert->texcoord[u][1] / vert->texcoord[u][3]; |
| texcoord[u][2] = vert->texcoord[u][2] / vert->texcoord[u][3]; |
| } |
| else { |
| texcoord[u][0] = vert->texcoord[u][0]; |
| texcoord[u][1] = vert->texcoord[u][1]; |
| texcoord[u][2] = vert->texcoord[u][2]; |
| } |
| } |
| } |
| |
| for (y = ymin; y <= ymax; y++) { |
| for (x = xmin; x <= xmax; x++) { |
| const GLfloat dx = x + 0.5F - vert->win[0]; |
| const GLfloat dy = y + 0.5F - vert->win[1]; |
| const GLfloat dist2 = dx*dx + dy*dy; |
| if (dist2 < rmax2) { |
| alpha = vert->color[3]; |
| if (dist2 >= rmin2) { |
| GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale); |
| /* coverage is in [0,256] */ |
| alpha = (alpha * coverage) >> 8; |
| } |
| alpha = (GLint) (alpha * alphaf); |
| if (swrast->_MultiTextureEnabled) { |
| PB_WRITE_MULTITEX_PIXEL( PB, x, y, z, fog, |
| red, green, blue, alpha, |
| texcoord ); |
| } |
| else { |
| PB_WRITE_TEX_PIXEL( PB, x,y,z, fog, |
| red, green, blue, alpha, |
| texcoord[0][0], |
| texcoord[0][1], |
| texcoord[0][2] ); |
| } |
| } |
| } |
| } |
| PB_CHECK_FLUSH(ctx,PB); |
| } |
| else { |
| /* Not texture mapped */ |
| GLfloat radius, rmin, rmax, rmin2, rmax2, cscale, alphaf; |
| GLint xmin, ymin, xmax, ymax; |
| GLint x, y, z; |
| GLfixed fog; |
| GLint red, green, blue, alpha; |
| GLfloat dsize = psize * dist; |
| |
| if (dsize >= ctx->Point.Threshold) { |
| radius = MIN2(dsize, ctx->Point.MaxSize) * 0.5F; |
| alphaf = 1.0F; |
| } |
| else { |
| radius = (MAX2(ctx->Point.Threshold, ctx->Point.MinSize) * 0.5F); |
| dsize /= ctx->Point.Threshold; |
| alphaf = dsize * dsize; |
| } |
| rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */ |
| rmax = radius + 0.7071F; |
| rmin2 = MAX2(0.0, rmin * rmin); |
| rmax2 = rmax * rmax; |
| cscale = 256.0F / (rmax2 - rmin2); |
| |
| xmin = (GLint) (vert->win[0] - radius); |
| xmax = (GLint) (vert->win[0] + radius); |
| ymin = (GLint) (vert->win[1] - radius); |
| ymax = (GLint) (vert->win[1] + radius); |
| z = (GLint) (vert->win[2]); |
| |
| fog = FloatToFixed( vert->fog ); |
| |
| red = vert->color[0]; |
| green = vert->color[1]; |
| blue = vert->color[2]; |
| |
| for (y = ymin; y <= ymax; y++) { |
| for (x = xmin; x <= xmax; x++) { |
| const GLfloat dx = x + 0.5F - vert->win[0]; |
| const GLfloat dy = y + 0.5F - vert->win[1]; |
| const GLfloat dist2 = dx * dx + dy * dy; |
| if (dist2 < rmax2) { |
| alpha = vert->color[3]; |
| if (dist2 >= rmin2) { |
| GLint coverage = (GLint) (256.0F - (dist2 - rmin2) * cscale); |
| /* coverage is in [0,256] */ |
| alpha = (alpha * coverage) >> 8; |
| } |
| alpha = (GLint) (alpha * alphaf); |
| PB_WRITE_RGBA_PIXEL(PB, x, y, z, fog, |
| red, green, blue, alpha); |
| } |
| } |
| } |
| PB_CHECK_FLUSH(ctx,PB); |
| } |
| } |
| |
| |
| #ifdef DEBUG |
| extern void |
| _mesa_print_point_function(GLcontext *ctx); /* silence compiler warning */ |
| void |
| _mesa_print_point_function(GLcontext *ctx) |
| { |
| SWcontext *swrast = SWRAST_CONTEXT(ctx); |
| |
| printf("Point Func == "); |
| if (swrast->Point == size1_ci_point) |
| printf("size1_ci_point\n"); |
| else if (swrast->Point == size1_rgba_point) |
| printf("size1_rgba_point\n"); |
| else if (swrast->Point == general_ci_point) |
| printf("general_ci_point\n"); |
| else if (swrast->Point == general_rgba_point) |
| printf("general_rgba_point\n"); |
| else if (swrast->Point == textured_rgba_point) |
| printf("textured_rgba_point\n"); |
| else if (swrast->Point == multitextured_rgba_point) |
| printf("multitextured_rgba_point\n"); |
| else if (swrast->Point == antialiased_rgba_point) |
| printf("antialiased_rgba_point\n"); |
| else if (swrast->Point == dist_atten_general_ci_point) |
| printf("dist_atten_general_ci_point\n"); |
| else if (swrast->Point == dist_atten_general_rgba_point) |
| printf("dist_atten_general_rgba_point\n"); |
| else if (swrast->Point == dist_atten_textured_rgba_point) |
| printf("dist_atten_textured_rgba_point\n"); |
| else if (swrast->Point == dist_atten_antialiased_rgba_point) |
| printf("dist_atten_antialiased_rgba_point\n"); |
| else if (!swrast->Point) |
| printf("NULL\n"); |
| else |
| printf("Driver func %p\n", swrast->Point); |
| } |
| #endif |
| |
| |
| /* |
| * Examine the current context to determine which point drawing function |
| * should be used. |
| */ |
| void |
| _swrast_choose_point( GLcontext *ctx ) |
| { |
| SWcontext *swrast = SWRAST_CONTEXT(ctx); |
| GLboolean rgbmode = ctx->Visual.RGBAflag; |
| |
| if (ctx->RenderMode==GL_RENDER) { |
| if (!ctx->Point._Attenuated) { |
| if (ctx->Point.SmoothFlag && rgbmode) { |
| swrast->Point = antialiased_rgba_point; |
| } |
| else if (ctx->Texture._ReallyEnabled) { |
| if (swrast->_MultiTextureEnabled || |
| ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR || |
| ctx->Fog.ColorSumEnabled) { |
| swrast->Point = multitextured_rgba_point; |
| } |
| else { |
| swrast->Point = textured_rgba_point; |
| } |
| } |
| else if (ctx->Point._Size == 1.0) { |
| /* size=1, any raster ops */ |
| if (rgbmode) |
| swrast->Point = size1_rgba_point; |
| else |
| swrast->Point = size1_ci_point; |
| } |
| else { |
| /* every other kind of point rendering */ |
| if (rgbmode) |
| swrast->Point = general_rgba_point; |
| else |
| swrast->Point = general_ci_point; |
| } |
| } |
| else if(ctx->Point.SmoothFlag && rgbmode) { |
| swrast->Point = dist_atten_antialiased_rgba_point; |
| } |
| else if (ctx->Texture._ReallyEnabled) { |
| swrast->Point = dist_atten_textured_rgba_point; |
| } |
| else { |
| /* every other kind of point rendering */ |
| if (rgbmode) |
| swrast->Point = dist_atten_general_rgba_point; |
| else |
| swrast->Point = dist_atten_general_ci_point; |
| } |
| } |
| else if (ctx->RenderMode==GL_FEEDBACK) { |
| swrast->Point = gl_feedback_point; |
| } |
| else { |
| /* GL_SELECT mode */ |
| swrast->Point = gl_select_point; |
| } |
| |
| /*_mesa_print_points_function(ctx);*/ |
| } |
| |