~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/mesa/swrast/s_aaline.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Mesa 3-D graphics library
 
3
 * Version:  6.5.3
 
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 "glheader.h"
 
27
#include "imports.h"
 
28
#include "macros.h"
 
29
#include "swrast/s_aaline.h"
 
30
#include "swrast/s_context.h"
 
31
#include "swrast/s_span.h"
 
32
#include "swrast/swrast.h"
 
33
#include "mtypes.h"
 
34
 
 
35
 
 
36
#define SUB_PIXEL 4
 
37
 
 
38
 
 
39
/*
 
40
 * Info about the AA line we're rendering
 
41
 */
 
42
struct LineInfo
 
43
{
 
44
   GLfloat x0, y0;        /* start */
 
45
   GLfloat x1, y1;        /* end */
 
46
   GLfloat dx, dy;        /* direction vector */
 
47
   GLfloat len;           /* length */
 
48
   GLfloat halfWidth;     /* half of line width */
 
49
   GLfloat xAdj, yAdj;    /* X and Y adjustment for quad corners around line */
 
50
   /* for coverage computation */
 
51
   GLfloat qx0, qy0;      /* quad vertices */
 
52
   GLfloat qx1, qy1;
 
53
   GLfloat qx2, qy2;
 
54
   GLfloat qx3, qy3;
 
55
   GLfloat ex0, ey0;      /* quad edge vectors */
 
56
   GLfloat ex1, ey1;
 
57
   GLfloat ex2, ey2;
 
58
   GLfloat ex3, ey3;
 
59
 
 
60
   /* DO_Z */
 
61
   GLfloat zPlane[4];
 
62
   /* DO_FOG */
 
63
   GLfloat fPlane[4];
 
64
   /* DO_RGBA */
 
65
   GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
 
66
   /* DO_INDEX */
 
67
   GLfloat iPlane[4];
 
68
   /* DO_SPEC */
 
69
   GLfloat srPlane[4], sgPlane[4], sbPlane[4];
 
70
   /* DO_ATTRIBS */
 
71
   GLfloat sPlane[FRAG_ATTRIB_MAX][4];
 
72
   GLfloat tPlane[FRAG_ATTRIB_MAX][4];
 
73
   GLfloat uPlane[FRAG_ATTRIB_MAX][4];
 
74
   GLfloat vPlane[FRAG_ATTRIB_MAX][4];
 
75
   GLfloat lambda[FRAG_ATTRIB_MAX];
 
76
   GLfloat texWidth[FRAG_ATTRIB_MAX];
 
77
   GLfloat texHeight[FRAG_ATTRIB_MAX];
 
78
 
 
79
   SWspan span;
 
80
};
 
81
 
 
82
 
 
83
 
 
84
/*
 
85
 * Compute the equation of a plane used to interpolate line fragment data
 
86
 * such as color, Z, texture coords, etc.
 
87
 * Input: (x0, y0) and (x1,y1) are the endpoints of the line.
 
88
 *        z0, and z1 are the end point values to interpolate.
 
89
 * Output:  plane - the plane equation.
 
90
 *
 
91
 * Note: we don't really have enough parameters to specify a plane.
 
92
 * We take the endpoints of the line and compute a plane such that
 
93
 * the cross product of the line vector and the plane normal is
 
94
 * parallel to the projection plane.
 
95
 */
 
96
static void
 
97
compute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
 
98
              GLfloat z0, GLfloat z1, GLfloat plane[4])
 
99
{
 
100
#if 0
 
101
   /* original */
 
102
   const GLfloat px = x1 - x0;
 
103
   const GLfloat py = y1 - y0;
 
104
   const GLfloat pz = z1 - z0;
 
105
   const GLfloat qx = -py;
 
106
   const GLfloat qy = px;
 
107
   const GLfloat qz = 0;
 
108
   const GLfloat a = py * qz - pz * qy;
 
109
   const GLfloat b = pz * qx - px * qz;
 
110
   const GLfloat c = px * qy - py * qx;
 
111
   const GLfloat d = -(a * x0 + b * y0 + c * z0);
 
112
   plane[0] = a;
 
113
   plane[1] = b;
 
114
   plane[2] = c;
 
115
   plane[3] = d;
 
116
#else
 
117
   /* simplified */
 
118
   const GLfloat px = x1 - x0;
 
119
   const GLfloat py = y1 - y0;
 
120
   const GLfloat pz = z0 - z1;
 
121
   const GLfloat a = pz * px;
 
122
   const GLfloat b = pz * py;
 
123
   const GLfloat c = px * px + py * py;
 
124
   const GLfloat d = -(a * x0 + b * y0 + c * z0);
 
125
   if (a == 0.0 && b == 0.0 && c == 0.0 && d == 0.0) {
 
126
      plane[0] = 0.0;
 
127
      plane[1] = 0.0;
 
128
      plane[2] = 1.0;
 
129
      plane[3] = 0.0;
 
130
   }
 
131
   else {
 
132
      plane[0] = a;
 
133
      plane[1] = b;
 
134
      plane[2] = c;
 
135
      plane[3] = d;
 
136
   }
 
137
#endif
 
138
}
 
139
 
 
140
 
 
141
static INLINE void
 
142
constant_plane(GLfloat value, GLfloat plane[4])
 
143
{
 
144
   plane[0] = 0.0;
 
145
   plane[1] = 0.0;
 
146
   plane[2] = -1.0;
 
147
   plane[3] = value;
 
148
}
 
149
 
 
150
 
 
151
static INLINE GLfloat
 
152
solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4])
 
153
{
 
154
   const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
 
155
   return z;
 
156
}
 
157
 
 
158
#define SOLVE_PLANE(X, Y, PLANE) \
 
159
   ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2])
 
160
 
 
161
 
 
162
/*
 
163
 * Return 1 / solve_plane().
 
164
 */
 
165
static INLINE GLfloat
 
166
solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4])
 
167
{
 
168
   const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y;
 
169
   if (denom == 0.0)
 
170
      return 0.0;
 
171
   else
 
172
      return -plane[2] / denom;
 
173
}
 
174
 
 
175
 
 
176
/*
 
177
 * Solve plane and return clamped GLchan value.
 
178
 */
 
179
static INLINE GLchan
 
180
solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4])
 
181
{
 
182
   const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2];
 
183
#if CHAN_TYPE == GL_FLOAT
 
184
   return CLAMP(z, 0.0F, CHAN_MAXF);
 
185
#else
 
186
   if (z < 0)
 
187
      return 0;
 
188
   else if (z > CHAN_MAX)
 
189
      return CHAN_MAX;
 
190
   return (GLchan) IROUND_POS(z);
 
191
#endif
 
192
}
 
193
 
 
194
 
 
195
/*
 
196
 * Compute mipmap level of detail.
 
197
 */
 
198
static INLINE GLfloat
 
199
compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4],
 
200
               GLfloat invQ, GLfloat width, GLfloat height)
 
201
{
 
202
   GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width;
 
203
   GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width;
 
204
   GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height;
 
205
   GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height;
 
206
   GLfloat r1 = dudx * dudx + dudy * dudy;
 
207
   GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
 
208
   GLfloat rho2 = r1 + r2;
 
209
   /* return log base 2 of rho */
 
210
   if (rho2 == 0.0F)
 
211
      return 0.0;
 
212
   else
 
213
      return (GLfloat) (LOGF(rho2) * 1.442695 * 0.5);/* 1.442695 = 1/log(2) */
 
214
}
 
215
 
 
216
 
 
217
 
 
218
 
 
219
/*
 
220
 * Fill in the samples[] array with the (x,y) subpixel positions of
 
221
 * xSamples * ySamples sample positions.
 
222
 * Note that the four corner samples are put into the first four
 
223
 * positions of the array.  This allows us to optimize for the common
 
224
 * case of all samples being inside the polygon.
 
225
 */
 
226
static void
 
227
make_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2])
 
228
{
 
229
   const GLfloat dx = 1.0F / (GLfloat) xSamples;
 
230
   const GLfloat dy = 1.0F / (GLfloat) ySamples;
 
231
   GLint x, y;
 
232
   GLint i;
 
233
 
 
234
   i = 4;
 
235
   for (x = 0; x < xSamples; x++) {
 
236
      for (y = 0; y < ySamples; y++) {
 
237
         GLint j;
 
238
         if (x == 0 && y == 0) {
 
239
            /* lower left */
 
240
            j = 0;
 
241
         }
 
242
         else if (x == xSamples - 1 && y == 0) {
 
243
            /* lower right */
 
244
            j = 1;
 
245
         }
 
246
         else if (x == 0 && y == ySamples - 1) {
 
247
            /* upper left */
 
248
            j = 2;
 
249
         }
 
250
         else if (x == xSamples - 1 && y == ySamples - 1) {
 
251
            /* upper right */
 
252
            j = 3;
 
253
         }
 
254
         else {
 
255
            j = i++;
 
256
         }
 
257
         samples[j][0] = x * dx + 0.5F * dx;
 
258
         samples[j][1] = y * dy + 0.5F * dy;
 
259
      }
 
260
   }
 
261
}
 
262
 
 
263
 
 
264
 
 
265
/*
 
266
 * Compute how much of the given pixel's area is inside the rectangle
 
267
 * defined by vertices v0, v1, v2, v3.
 
268
 * Vertices MUST be specified in counter-clockwise order.
 
269
 * Return:  coverage in [0, 1].
 
270
 */
 
271
static GLfloat
 
272
compute_coveragef(const struct LineInfo *info,
 
273
                  GLint winx, GLint winy)
 
274
{
 
275
   static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2];
 
276
   static GLboolean haveSamples = GL_FALSE;
 
277
   const GLfloat x = (GLfloat) winx;
 
278
   const GLfloat y = (GLfloat) winy;
 
279
   GLint stop = 4, i;
 
280
   GLfloat insideCount = SUB_PIXEL * SUB_PIXEL;
 
281
 
 
282
   if (!haveSamples) {
 
283
      make_sample_table(SUB_PIXEL, SUB_PIXEL, samples);
 
284
      haveSamples = GL_TRUE;
 
285
   }
 
286
 
 
287
#if 0 /*DEBUG*/
 
288
   {
 
289
      const GLfloat area = dx0 * dy1 - dx1 * dy0;
 
290
      assert(area >= 0.0);
 
291
   }
 
292
#endif
 
293
 
 
294
   for (i = 0; i < stop; i++) {
 
295
      const GLfloat sx = x + samples[i][0];
 
296
      const GLfloat sy = y + samples[i][1];
 
297
      const GLfloat fx0 = sx - info->qx0;
 
298
      const GLfloat fy0 = sy - info->qy0;
 
299
      const GLfloat fx1 = sx - info->qx1;
 
300
      const GLfloat fy1 = sy - info->qy1;
 
301
      const GLfloat fx2 = sx - info->qx2;
 
302
      const GLfloat fy2 = sy - info->qy2;
 
303
      const GLfloat fx3 = sx - info->qx3;
 
304
      const GLfloat fy3 = sy - info->qy3;
 
305
      /* cross product determines if sample is inside or outside each edge */
 
306
      GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0);
 
307
      GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1);
 
308
      GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2);
 
309
      GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3);
 
310
      /* Check if the sample is exactly on an edge.  If so, let cross be a
 
311
       * positive or negative value depending on the direction of the edge.
 
312
       */
 
313
      if (cross0 == 0.0F)
 
314
         cross0 = info->ex0 + info->ey0;
 
315
      if (cross1 == 0.0F)
 
316
         cross1 = info->ex1 + info->ey1;
 
317
      if (cross2 == 0.0F)
 
318
         cross2 = info->ex2 + info->ey2;
 
319
      if (cross3 == 0.0F)
 
320
         cross3 = info->ex3 + info->ey3;
 
321
      if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) {
 
322
         /* point is outside quadrilateral */
 
323
         insideCount -= 1.0F;
 
324
         stop = SUB_PIXEL * SUB_PIXEL;
 
325
      }
 
326
   }
 
327
   if (stop == 4)
 
328
      return 1.0F;
 
329
   else
 
330
      return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL));
 
331
}
 
332
 
 
333
 
 
334
/**
 
335
 * Compute coverage value for color index mode.
 
336
 * XXX this may not be quite correct.
 
337
 * \return coverage in [0,15].
 
338
 */
 
339
static GLfloat
 
340
compute_coveragei(const struct LineInfo *info,
 
341
                  GLint winx, GLint winy)
 
342
{
 
343
   return compute_coveragef(info, winx, winy) * 15.0F;
 
344
}
 
345
 
 
346
 
 
347
 
 
348
typedef void (*plot_func)(GLcontext *ctx, struct LineInfo *line,
 
349
                          int ix, int iy);
 
350
                         
 
351
 
 
352
 
 
353
/*
 
354
 * Draw an AA line segment (called many times per line when stippling)
 
355
 */
 
356
static void
 
357
segment(GLcontext *ctx,
 
358
        struct LineInfo *line,
 
359
        plot_func plot,
 
360
        GLfloat t0, GLfloat t1)
 
361
{
 
362
   const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx;
 
363
   const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy;
 
364
   /* compute the actual segment's endpoints */
 
365
   const GLfloat x0 = line->x0 + t0 * line->dx;
 
366
   const GLfloat y0 = line->y0 + t0 * line->dy;
 
367
   const GLfloat x1 = line->x0 + t1 * line->dx;
 
368
   const GLfloat y1 = line->y0 + t1 * line->dy;
 
369
 
 
370
   /* compute vertices of the line-aligned quadrilateral */
 
371
   line->qx0 = x0 - line->yAdj;
 
372
   line->qy0 = y0 + line->xAdj;
 
373
   line->qx1 = x0 + line->yAdj;
 
374
   line->qy1 = y0 - line->xAdj;
 
375
   line->qx2 = x1 + line->yAdj;
 
376
   line->qy2 = y1 - line->xAdj;
 
377
   line->qx3 = x1 - line->yAdj;
 
378
   line->qy3 = y1 + line->xAdj;
 
379
   /* compute the quad's edge vectors (for coverage calc) */
 
380
   line->ex0 = line->qx1 - line->qx0;
 
381
   line->ey0 = line->qy1 - line->qy0;
 
382
   line->ex1 = line->qx2 - line->qx1;
 
383
   line->ey1 = line->qy2 - line->qy1;
 
384
   line->ex2 = line->qx3 - line->qx2;
 
385
   line->ey2 = line->qy3 - line->qy2;
 
386
   line->ex3 = line->qx0 - line->qx3;
 
387
   line->ey3 = line->qy0 - line->qy3;
 
388
 
 
389
   if (absDx > absDy) {
 
390
      /* X-major line */
 
391
      GLfloat dydx = line->dy / line->dx;
 
392
      GLfloat xLeft, xRight, yBot, yTop;
 
393
      GLint ix, ixRight;
 
394
      if (x0 < x1) {
 
395
         xLeft = x0 - line->halfWidth;
 
396
         xRight = x1 + line->halfWidth;
 
397
         if (line->dy >= 0.0) {
 
398
            yBot = y0 - 3.0F * line->halfWidth;
 
399
            yTop = y0 + line->halfWidth;
 
400
         }
 
401
         else {
 
402
            yBot = y0 - line->halfWidth;
 
403
            yTop = y0 + 3.0F * line->halfWidth;
 
404
         }
 
405
      }
 
406
      else {
 
407
         xLeft = x1 - line->halfWidth;
 
408
         xRight = x0 + line->halfWidth;
 
409
         if (line->dy <= 0.0) {
 
410
            yBot = y1 - 3.0F * line->halfWidth;
 
411
            yTop = y1 + line->halfWidth;
 
412
         }
 
413
         else {
 
414
            yBot = y1 - line->halfWidth;
 
415
            yTop = y1 + 3.0F * line->halfWidth;
 
416
         }
 
417
      }
 
418
 
 
419
      /* scan along the line, left-to-right */
 
420
      ixRight = (GLint) (xRight + 1.0F);
 
421
 
 
422
      /*printf("avg span height: %g\n", yTop - yBot);*/
 
423
      for (ix = (GLint) xLeft; ix < ixRight; ix++) {
 
424
         const GLint iyBot = (GLint) yBot;
 
425
         const GLint iyTop = (GLint) (yTop + 1.0F);
 
426
         GLint iy;
 
427
         /* scan across the line, bottom-to-top */
 
428
         for (iy = iyBot; iy < iyTop; iy++) {
 
429
            (*plot)(ctx, line, ix, iy);
 
430
         }
 
431
         yBot += dydx;
 
432
         yTop += dydx;
 
433
      }
 
434
   }
 
435
   else {
 
436
      /* Y-major line */
 
437
      GLfloat dxdy = line->dx / line->dy;
 
438
      GLfloat yBot, yTop, xLeft, xRight;
 
439
      GLint iy, iyTop;
 
440
      if (y0 < y1) {
 
441
         yBot = y0 - line->halfWidth;
 
442
         yTop = y1 + line->halfWidth;
 
443
         if (line->dx >= 0.0) {
 
444
            xLeft = x0 - 3.0F * line->halfWidth;
 
445
            xRight = x0 + line->halfWidth;
 
446
         }
 
447
         else {
 
448
            xLeft = x0 - line->halfWidth;
 
449
            xRight = x0 + 3.0F * line->halfWidth;
 
450
         }
 
451
      }
 
452
      else {
 
453
         yBot = y1 - line->halfWidth;
 
454
         yTop = y0 + line->halfWidth;
 
455
         if (line->dx <= 0.0) {
 
456
            xLeft = x1 - 3.0F * line->halfWidth;
 
457
            xRight = x1 + line->halfWidth;
 
458
         }
 
459
         else {
 
460
            xLeft = x1 - line->halfWidth;
 
461
            xRight = x1 + 3.0F * line->halfWidth;
 
462
         }
 
463
      }
 
464
 
 
465
      /* scan along the line, bottom-to-top */
 
466
      iyTop = (GLint) (yTop + 1.0F);
 
467
 
 
468
      /*printf("avg span width: %g\n", xRight - xLeft);*/
 
469
      for (iy = (GLint) yBot; iy < iyTop; iy++) {
 
470
         const GLint ixLeft = (GLint) xLeft;
 
471
         const GLint ixRight = (GLint) (xRight + 1.0F);
 
472
         GLint ix;
 
473
         /* scan across the line, left-to-right */
 
474
         for (ix = ixLeft; ix < ixRight; ix++) {
 
475
            (*plot)(ctx, line, ix, iy);
 
476
         }
 
477
         xLeft += dxdy;
 
478
         xRight += dxdy;
 
479
      }
 
480
   }
 
481
}
 
482
 
 
483
 
 
484
#define NAME(x) aa_ci_##x
 
485
#define DO_Z
 
486
#define DO_FOG
 
487
#define DO_INDEX
 
488
#include "s_aalinetemp.h"
 
489
 
 
490
 
 
491
#define NAME(x) aa_rgba_##x
 
492
#define DO_Z
 
493
#define DO_FOG
 
494
#define DO_RGBA
 
495
#include "s_aalinetemp.h"
 
496
 
 
497
 
 
498
#define NAME(x)  aa_tex_rgba_##x
 
499
#define DO_Z
 
500
#define DO_FOG
 
501
#define DO_RGBA
 
502
#define DO_ATTRIBS
 
503
#include "s_aalinetemp.h"
 
504
 
 
505
 
 
506
#define NAME(x)  aa_multitex_spec_##x
 
507
#define DO_Z
 
508
#define DO_FOG
 
509
#define DO_RGBA
 
510
#define DO_ATTRIBS
 
511
#define DO_SPEC
 
512
#include "s_aalinetemp.h"
 
513
 
 
514
 
 
515
 
 
516
void
 
517
_swrast_choose_aa_line_function(GLcontext *ctx)
 
518
{
 
519
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
520
 
 
521
   ASSERT(ctx->Line.SmoothFlag);
 
522
 
 
523
   if (ctx->Visual.rgbMode) {
 
524
      /* RGBA */
 
525
      if (ctx->Texture._EnabledCoordUnits != 0
 
526
          || ctx->FragmentProgram._Current) {
 
527
 
 
528
         if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR || 
 
529
             ctx->Fog.ColorSumEnabled)
 
530
            swrast->Line = aa_multitex_spec_line;
 
531
         else
 
532
            swrast->Line = aa_tex_rgba_line;
 
533
 
 
534
      }
 
535
      else {
 
536
         swrast->Line = aa_rgba_line;
 
537
      }
 
538
   }
 
539
   else {
 
540
      /* Color Index */
 
541
      swrast->Line = aa_ci_line;
 
542
   }
 
543
}