Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Mesa 3-D graphics library
3
 * Version:  7.1
4
 *
5
 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included
15
 * in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
 
26
#include "main/glheader.h"
27
#include "main/colormac.h"
28
#include "main/macros.h"
29
#include "s_context.h"
30
#include "s_feedback.h"
31
#include "s_points.h"
32
#include "s_span.h"
33
 
34
 
35
/**
36
 * Used to cull points with invalid coords
37
 */
38
#define CULL_INVALID(V)                              \
39
   do {                                              \
40
      float tmp = (V)->attrib[FRAG_ATTRIB_WPOS][0]   \
41
                + (V)->attrib[FRAG_ATTRIB_WPOS][1];  \
42
      if (IS_INF_OR_NAN(tmp))                        \
43
	 return;                                     \
44
   } while(0)
45
 
46
 
47
 
48
/**
49
 * Get/compute the point size.
50
 * The size may come from a vertex shader, or computed with attentuation
51
 * or just the glPointSize value.
52
 * Must also clamp to user-defined range and implmentation limits.
53
 */
54
static INLINE GLfloat
55
get_size(const struct gl_context *ctx, const SWvertex *vert, GLboolean smoothed)
56
{
57
   GLfloat size;
58
 
59
   if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) {
60
      /* use vertex's point size */
61
      size = vert->pointSize;
62
   }
63
   else {
64
      /* use constant point size */
65
      size = ctx->Point.Size;
66
   }
67
   /* always clamp to user-specified limits */
68
   size = CLAMP(size, ctx->Point.MinSize, ctx->Point.MaxSize);
69
   /* clamp to implementation limits */
70
   if (smoothed)
71
      size = CLAMP(size, ctx->Const.MinPointSizeAA, ctx->Const.MaxPointSizeAA);
72
   else
73
      size = CLAMP(size, ctx->Const.MinPointSize, ctx->Const.MaxPointSize);
74
 
75
   return size;
76
}
77
 
78
 
79
/**
80
 * Draw a point sprite
81
 */
82
static void
83
sprite_point(struct gl_context *ctx, const SWvertex *vert)
84
{
85
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
86
   SWspan span;
87
   GLfloat size;
88
   GLuint tCoords[MAX_TEXTURE_COORD_UNITS + 1];
89
   GLuint numTcoords = 0;
90
   GLfloat t0, dtdy;
91
 
92
   CULL_INVALID(vert);
93
 
94
   /* z coord */
95
   if (ctx->DrawBuffer->Visual.depthBits <= 16)
96
      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
97
   else
98
      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
99
   span.zStep = 0;
100
 
101
   size = get_size(ctx, vert, GL_FALSE);
102
 
103
   /* span init */
104
   INIT_SPAN(span, GL_POINT);
105
   span.interpMask = SPAN_Z | SPAN_RGBA;
106
 
107
   span.facing = swrast->PointLineFacing;
108
 
109
   span.red   = ChanToFixed(vert->color[0]);
110
   span.green = ChanToFixed(vert->color[1]);
111
   span.blue  = ChanToFixed(vert->color[2]);
112
   span.alpha = ChanToFixed(vert->color[3]);
113
   span.redStep = 0;
114
   span.greenStep = 0;
115
   span.blueStep = 0;
116
   span.alphaStep = 0;
117
 
118
   /* need these for fragment programs */
119
   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
120
   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
121
   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
122
 
123
   {
124
      GLfloat s, r, dsdx;
125
 
126
      /* texcoord / pointcoord interpolants */
127
      s = 0.0F;
128
      dsdx = 1.0F / size;
129
      if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) {
130
         dtdy = 1.0F / size;
131
         t0 = 0.5F * dtdy;
132
      }
133
      else {
134
         /* GL_UPPER_LEFT */
135
         dtdy = -1.0F / size;
136
         t0 = 1.0F + 0.5F * dtdy;
137
      }
138
 
139
      ATTRIB_LOOP_BEGIN
140
         if (attr >= FRAG_ATTRIB_TEX0 && attr <= FRAG_ATTRIB_TEX7) {
141
            /* a texcoord attribute */
142
            const GLuint u = attr - FRAG_ATTRIB_TEX0;
143
            ASSERT(u < Elements(ctx->Point.CoordReplace));
144
            if (ctx->Point.CoordReplace[u]) {
145
               tCoords[numTcoords++] = attr;
146
 
147
               if (ctx->Point.SpriteRMode == GL_ZERO)
148
                  r = 0.0F;
149
               else if (ctx->Point.SpriteRMode == GL_S)
150
                  r = vert->attrib[attr][0];
151
               else /* GL_R */
152
                  r = vert->attrib[attr][2];
153
 
154
               span.attrStart[attr][0] = s;
155
               span.attrStart[attr][1] = 0.0; /* overwritten below */
156
               span.attrStart[attr][2] = r;
157
               span.attrStart[attr][3] = 1.0;
158
 
159
               span.attrStepX[attr][0] = dsdx;
160
               span.attrStepX[attr][1] = 0.0;
161
               span.attrStepX[attr][2] = 0.0;
162
               span.attrStepX[attr][3] = 0.0;
163
 
164
               span.attrStepY[attr][0] = 0.0;
165
               span.attrStepY[attr][1] = dtdy;
166
               span.attrStepY[attr][2] = 0.0;
167
               span.attrStepY[attr][3] = 0.0;
168
 
169
               continue;
170
            }
171
         }
172
         else if (attr == FRAG_ATTRIB_PNTC) {
173
            /* GLSL gl_PointCoord.xy (.zw undefined) */
174
            span.attrStart[FRAG_ATTRIB_PNTC][0] = 0.0;
175
            span.attrStart[FRAG_ATTRIB_PNTC][1] = 0.0; /* t0 set below */
176
            span.attrStepX[FRAG_ATTRIB_PNTC][0] = dsdx;
177
            span.attrStepX[FRAG_ATTRIB_PNTC][1] = 0.0;
178
            span.attrStepY[FRAG_ATTRIB_PNTC][0] = 0.0;
179
            span.attrStepY[FRAG_ATTRIB_PNTC][1] = dtdy;
180
            tCoords[numTcoords++] = FRAG_ATTRIB_PNTC;
181
            continue;
182
         }
183
         /* use vertex's texcoord/attrib */
184
         COPY_4V(span.attrStart[attr], vert->attrib[attr]);
185
         ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
186
         ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
187
      ATTRIB_LOOP_END;
188
   }
189
 
190
   /* compute pos, bounds and render */
191
   {
192
      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
193
      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
194
      GLint iSize = (GLint) (size + 0.5F);
195
      GLint xmin, xmax, ymin, ymax, iy;
196
      GLint iRadius;
197
      GLfloat tcoord = t0;
198
 
199
      iSize = MAX2(1, iSize);
200
      iRadius = iSize / 2;
201
 
202
      if (iSize & 1) {
203
         /* odd size */
204
         xmin = (GLint) (x - iRadius);
205
         xmax = (GLint) (x + iRadius);
206
         ymin = (GLint) (y - iRadius);
207
         ymax = (GLint) (y + iRadius);
208
      }
209
      else {
210
         /* even size */
211
         /* 0.501 factor allows conformance to pass */
212
         xmin = (GLint) (x + 0.501) - iRadius;
213
         xmax = xmin + iSize - 1;
214
         ymin = (GLint) (y + 0.501) - iRadius;
215
         ymax = ymin + iSize - 1;
216
      }
217
 
218
      /* render spans */
219
      for (iy = ymin; iy <= ymax; iy++) {
220
         GLuint i;
221
         /* setup texcoord T for this row */
222
         for (i = 0; i < numTcoords; i++) {
223
            span.attrStart[tCoords[i]][1] = tcoord;
224
         }
225
 
226
         /* these might get changed by span clipping */
227
         span.x = xmin;
228
         span.y = iy;
229
         span.end = xmax - xmin + 1;
230
 
231
         _swrast_write_rgba_span(ctx, &span);
232
 
233
         tcoord += dtdy;
234
      }
235
   }
236
}
237
 
238
 
239
/**
240
 * Draw smooth/antialiased point.  RGB or CI mode.
241
 */
242
static void
243
smooth_point(struct gl_context *ctx, const SWvertex *vert)
244
{
245
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
246
   SWspan span;
247
   GLfloat size, alphaAtten;
248
 
249
   CULL_INVALID(vert);
250
 
251
   /* z coord */
252
   if (ctx->DrawBuffer->Visual.depthBits <= 16)
253
      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
254
   else
255
      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
256
   span.zStep = 0;
257
 
258
   size = get_size(ctx, vert, GL_TRUE);
259
 
260
   /* alpha attenuation / fade factor */
261
   if (ctx->Multisample._Enabled) {
262
      if (vert->pointSize >= ctx->Point.Threshold) {
263
         alphaAtten = 1.0F;
264
      }
265
      else {
266
         GLfloat dsize = vert->pointSize / ctx->Point.Threshold;
267
         alphaAtten = dsize * dsize;
268
      }
269
   }
270
   else {
271
      alphaAtten = 1.0;
272
   }
273
   (void) alphaAtten; /* not used */
274
 
275
   /* span init */
276
   INIT_SPAN(span, GL_POINT);
277
   span.interpMask = SPAN_Z | SPAN_RGBA;
278
   span.arrayMask = SPAN_COVERAGE | SPAN_MASK;
279
 
280
   span.facing = swrast->PointLineFacing;
281
 
282
   span.red   = ChanToFixed(vert->color[0]);
283
   span.green = ChanToFixed(vert->color[1]);
284
   span.blue  = ChanToFixed(vert->color[2]);
285
   span.alpha = ChanToFixed(vert->color[3]);
286
   span.redStep = 0;
287
   span.greenStep = 0;
288
   span.blueStep = 0;
289
   span.alphaStep = 0;
290
 
291
   /* need these for fragment programs */
292
   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
293
   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
294
   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
295
 
296
   ATTRIB_LOOP_BEGIN
297
      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
298
      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
299
      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
300
   ATTRIB_LOOP_END
301
 
302
   /* compute pos, bounds and render */
303
   {
304
      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
305
      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
306
      const GLfloat radius = 0.5F * size;
307
      const GLfloat rmin = radius - 0.7071F;  /* 0.7071 = sqrt(2)/2 */
308
      const GLfloat rmax = radius + 0.7071F;
309
      const GLfloat rmin2 = MAX2(0.0F, rmin * rmin);
310
      const GLfloat rmax2 = rmax * rmax;
311
      const GLfloat cscale = 1.0F / (rmax2 - rmin2);
312
      const GLint xmin = (GLint) (x - radius);
313
      const GLint xmax = (GLint) (x + radius);
314
      const GLint ymin = (GLint) (y - radius);
315
      const GLint ymax = (GLint) (y + radius);
316
      GLint ix, iy;
317
 
318
      for (iy = ymin; iy <= ymax; iy++) {
319
 
320
         /* these might get changed by span clipping */
321
         span.x = xmin;
322
         span.y = iy;
323
         span.end = xmax - xmin + 1;
324
 
325
         /* compute coverage for each pixel in span */
326
         for (ix = xmin; ix <= xmax; ix++) {
327
            const GLfloat dx = ix - x + 0.5F;
328
            const GLfloat dy = iy - y + 0.5F;
329
            const GLfloat dist2 = dx * dx + dy * dy;
330
            GLfloat coverage;
331
 
332
            if (dist2 < rmax2) {
333
               if (dist2 >= rmin2) {
334
                  /* compute partial coverage */
335
                  coverage = 1.0F - (dist2 - rmin2) * cscale;
336
               }
337
               else {
338
                  /* full coverage */
339
                  coverage = 1.0F;
340
               }
341
               span.array->mask[ix - xmin] = 1;
342
            }
343
            else {
344
               /* zero coverage - fragment outside the radius */
345
               coverage = 0.0;
346
               span.array->mask[ix - xmin] = 0;
347
            }
348
            span.array->coverage[ix - xmin] = coverage;
349
         }
350
 
351
         /* render span */
352
         _swrast_write_rgba_span(ctx, &span);
353
 
354
      }
355
   }
356
}
357
 
358
 
359
/**
360
 * Draw large (size >= 1) non-AA point.  RGB or CI mode.
361
 */
362
static void
363
large_point(struct gl_context *ctx, const SWvertex *vert)
364
{
365
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
366
   SWspan span;
367
   GLfloat size;
368
 
369
   CULL_INVALID(vert);
370
 
371
   /* z coord */
372
   if (ctx->DrawBuffer->Visual.depthBits <= 16)
373
      span.z = FloatToFixed(vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
374
   else
375
      span.z = (GLuint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
376
   span.zStep = 0;
377
 
378
   size = get_size(ctx, vert, GL_FALSE);
379
 
380
   /* span init */
381
   INIT_SPAN(span, GL_POINT);
382
   span.arrayMask = SPAN_XY;
383
   span.facing = swrast->PointLineFacing;
384
 
385
   span.interpMask = SPAN_Z | SPAN_RGBA;
386
   span.red   = ChanToFixed(vert->color[0]);
387
   span.green = ChanToFixed(vert->color[1]);
388
   span.blue  = ChanToFixed(vert->color[2]);
389
   span.alpha = ChanToFixed(vert->color[3]);
390
   span.redStep = 0;
391
   span.greenStep = 0;
392
   span.blueStep = 0;
393
   span.alphaStep = 0;
394
 
395
   /* need these for fragment programs */
396
   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
397
   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
398
   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
399
 
400
   ATTRIB_LOOP_BEGIN
401
      COPY_4V(span.attrStart[attr], vert->attrib[attr]);
402
      ASSIGN_4V(span.attrStepX[attr], 0, 0, 0, 0);
403
      ASSIGN_4V(span.attrStepY[attr], 0, 0, 0, 0);
404
   ATTRIB_LOOP_END
405
 
406
   /* compute pos, bounds and render */
407
   {
408
      const GLfloat x = vert->attrib[FRAG_ATTRIB_WPOS][0];
409
      const GLfloat y = vert->attrib[FRAG_ATTRIB_WPOS][1];
410
      GLint iSize = (GLint) (size + 0.5F);
411
      GLint xmin, xmax, ymin, ymax, ix, iy;
412
      GLint iRadius;
413
 
414
      iSize = MAX2(1, iSize);
415
      iRadius = iSize / 2;
416
 
417
      if (iSize & 1) {
418
         /* odd size */
419
         xmin = (GLint) (x - iRadius);
420
         xmax = (GLint) (x + iRadius);
421
         ymin = (GLint) (y - iRadius);
422
         ymax = (GLint) (y + iRadius);
423
      }
424
      else {
425
         /* even size */
426
         /* 0.501 factor allows conformance to pass */
427
         xmin = (GLint) (x + 0.501) - iRadius;
428
         xmax = xmin + iSize - 1;
429
         ymin = (GLint) (y + 0.501) - iRadius;
430
         ymax = ymin + iSize - 1;
431
      }
432
 
433
      /* generate fragments */
434
      span.end = 0;
435
      for (iy = ymin; iy <= ymax; iy++) {
436
         for (ix = xmin; ix <= xmax; ix++) {
437
            span.array->x[span.end] = ix;
438
            span.array->y[span.end] = iy;
439
            span.end++;
440
         }
441
      }
442
      assert(span.end <= MAX_WIDTH);
443
      _swrast_write_rgba_span(ctx, &span);
444
   }
445
}
446
 
447
 
448
/**
449
 * Draw size=1, single-pixel point
450
 */
451
static void
452
pixel_point(struct gl_context *ctx, const SWvertex *vert)
453
{
454
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
455
   /*
456
    * Note that unlike the other functions, we put single-pixel points
457
    * into a special span array in order to render as many points as
458
    * possible with a single _swrast_write_rgba_span() call.
459
    */
460
   SWspan *span = &(swrast->PointSpan);
461
   GLuint count;
462
 
463
   CULL_INVALID(vert);
464
 
465
   /* Span init */
466
   span->interpMask = 0;
467
   span->arrayMask = SPAN_XY | SPAN_Z;
468
   span->arrayMask |= SPAN_RGBA;
469
   /*span->arrayMask |= SPAN_LAMBDA;*/
470
   span->arrayAttribs = swrast->_ActiveAttribMask; /* we'll produce these vals */
471
 
472
   /* need these for fragment programs */
473
   span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
474
   span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
475
   span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
476
 
477
   /* check if we need to flush */
478
   if (span->end >= MAX_WIDTH ||
479
       (swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT)) ||
480
       span->facing != swrast->PointLineFacing) {
481
      if (span->end > 0) {
482
	 _swrast_write_rgba_span(ctx, span);
483
         span->end = 0;
484
      }
485
   }
486
 
487
   count = span->end;
488
 
489
   span->facing = swrast->PointLineFacing;
490
 
491
   /* fragment attributes */
492
   span->array->rgba[count][RCOMP] = vert->color[0];
493
   span->array->rgba[count][GCOMP] = vert->color[1];
494
   span->array->rgba[count][BCOMP] = vert->color[2];
495
   span->array->rgba[count][ACOMP] = vert->color[3];
496
 
497
   ATTRIB_LOOP_BEGIN
498
      COPY_4V(span->array->attribs[attr][count], vert->attrib[attr]);
499
   ATTRIB_LOOP_END
500
 
501
   /* fragment position */
502
   span->array->x[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][0];
503
   span->array->y[count] = (GLint) vert->attrib[FRAG_ATTRIB_WPOS][1];
504
   span->array->z[count] = (GLint) (vert->attrib[FRAG_ATTRIB_WPOS][2] + 0.5F);
505
 
506
   span->end = count + 1;
507
   ASSERT(span->end <= MAX_WIDTH);
508
}
509
 
510
 
511
/**
512
 * Add specular color to primary color, draw point, restore original
513
 * primary color.
514
 */
515
void
516
_swrast_add_spec_terms_point(struct gl_context *ctx, const SWvertex *v0)
517
{
518
   SWvertex *ncv0 = (SWvertex *) v0; /* cast away const */
519
   GLfloat rSum, gSum, bSum;
520
   GLchan cSave[4];
521
 
522
   /* save */
523
   COPY_CHAN4(cSave, ncv0->color);
524
   /* sum */
525
   rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0];
526
   gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1];
527
   bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2];
528
   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
529
   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
530
   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
531
   /* draw */
532
   SWRAST_CONTEXT(ctx)->SpecPoint(ctx, ncv0);
533
   /* restore */
534
   COPY_CHAN4(ncv0->color, cSave);
535
}
536
 
537
 
538
/**
539
 * Examine current state to determine which point drawing function to use.
540
 */
541
void
542
_swrast_choose_point(struct gl_context *ctx)
543
{
544
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
545
   const GLfloat size = CLAMP(ctx->Point.Size,
546
                              ctx->Point.MinSize,
547
                              ctx->Point.MaxSize);
548
 
549
   if (ctx->RenderMode == GL_RENDER) {
550
      if (ctx->Point.PointSprite) {
551
         swrast->Point = sprite_point;
552
      }
553
      else if (ctx->Point.SmoothFlag) {
554
         swrast->Point = smooth_point;
555
      }
556
      else if (size > 1.0 ||
557
               ctx->Point._Attenuated ||
558
               ctx->VertexProgram.PointSizeEnabled) {
559
         swrast->Point = large_point;
560
      }
561
      else {
562
         swrast->Point = pixel_point;
563
      }
564
   }
565
   else if (ctx->RenderMode == GL_FEEDBACK) {
566
      swrast->Point = _swrast_feedback_point;
567
   }
568
   else {
569
      /* GL_SELECT mode */
570
      swrast->Point = _swrast_select_point;
571
   }
572
}