Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygens_aaline.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 6.5.3 00004 * 00005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00026 #include "main/glheader.h" 00027 #include "main/imports.h" 00028 #include "main/macros.h" 00029 #include "main/mtypes.h" 00030 #include "swrast/s_aaline.h" 00031 #include "swrast/s_context.h" 00032 #include "swrast/s_span.h" 00033 #include "swrast/swrast.h" 00034 00035 00036 #define SUB_PIXEL 4 00037 00038 00039 /* 00040 * Info about the AA line we're rendering 00041 */ 00042 struct LineInfo 00043 { 00044 GLfloat x0, y0; /* start */ 00045 GLfloat x1, y1; /* end */ 00046 GLfloat dx, dy; /* direction vector */ 00047 GLfloat len; /* length */ 00048 GLfloat halfWidth; /* half of line width */ 00049 GLfloat xAdj, yAdj; /* X and Y adjustment for quad corners around line */ 00050 /* for coverage computation */ 00051 GLfloat qx0, qy0; /* quad vertices */ 00052 GLfloat qx1, qy1; 00053 GLfloat qx2, qy2; 00054 GLfloat qx3, qy3; 00055 GLfloat ex0, ey0; /* quad edge vectors */ 00056 GLfloat ex1, ey1; 00057 GLfloat ex2, ey2; 00058 GLfloat ex3, ey3; 00059 00060 /* DO_Z */ 00061 GLfloat zPlane[4]; 00062 /* DO_RGBA */ 00063 GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4]; 00064 /* DO_INDEX */ 00065 GLfloat iPlane[4]; 00066 /* DO_ATTRIBS */ 00067 GLfloat wPlane[4]; 00068 GLfloat attrPlane[FRAG_ATTRIB_MAX][4][4]; 00069 GLfloat lambda[FRAG_ATTRIB_MAX]; 00070 GLfloat texWidth[FRAG_ATTRIB_MAX]; 00071 GLfloat texHeight[FRAG_ATTRIB_MAX]; 00072 00073 SWspan span; 00074 }; 00075 00076 00077 00078 /* 00079 * Compute the equation of a plane used to interpolate line fragment data 00080 * such as color, Z, texture coords, etc. 00081 * Input: (x0, y0) and (x1,y1) are the endpoints of the line. 00082 * z0, and z1 are the end point values to interpolate. 00083 * Output: plane - the plane equation. 00084 * 00085 * Note: we don't really have enough parameters to specify a plane. 00086 * We take the endpoints of the line and compute a plane such that 00087 * the cross product of the line vector and the plane normal is 00088 * parallel to the projection plane. 00089 */ 00090 static void 00091 compute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, 00092 GLfloat z0, GLfloat z1, GLfloat plane[4]) 00093 { 00094 #if 0 00095 /* original */ 00096 const GLfloat px = x1 - x0; 00097 const GLfloat py = y1 - y0; 00098 const GLfloat pz = z1 - z0; 00099 const GLfloat qx = -py; 00100 const GLfloat qy = px; 00101 const GLfloat qz = 0; 00102 const GLfloat a = py * qz - pz * qy; 00103 const GLfloat b = pz * qx - px * qz; 00104 const GLfloat c = px * qy - py * qx; 00105 const GLfloat d = -(a * x0 + b * y0 + c * z0); 00106 plane[0] = a; 00107 plane[1] = b; 00108 plane[2] = c; 00109 plane[3] = d; 00110 #else 00111 /* simplified */ 00112 const GLfloat px = x1 - x0; 00113 const GLfloat py = y1 - y0; 00114 const GLfloat pz = z0 - z1; 00115 const GLfloat a = pz * px; 00116 const GLfloat b = pz * py; 00117 const GLfloat c = px * px + py * py; 00118 const GLfloat d = -(a * x0 + b * y0 + c * z0); 00119 if (a == 0.0 && b == 0.0 && c == 0.0 && d == 0.0) { 00120 plane[0] = 0.0; 00121 plane[1] = 0.0; 00122 plane[2] = 1.0; 00123 plane[3] = 0.0; 00124 } 00125 else { 00126 plane[0] = a; 00127 plane[1] = b; 00128 plane[2] = c; 00129 plane[3] = d; 00130 } 00131 #endif 00132 } 00133 00134 00135 static INLINE void 00136 constant_plane(GLfloat value, GLfloat plane[4]) 00137 { 00138 plane[0] = 0.0; 00139 plane[1] = 0.0; 00140 plane[2] = -1.0; 00141 plane[3] = value; 00142 } 00143 00144 00145 static INLINE GLfloat 00146 solve_plane(GLfloat x, GLfloat y, const GLfloat plane[4]) 00147 { 00148 const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; 00149 return z; 00150 } 00151 00152 #define SOLVE_PLANE(X, Y, PLANE) \ 00153 ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2]) 00154 00155 00156 /* 00157 * Return 1 / solve_plane(). 00158 */ 00159 static INLINE GLfloat 00160 solve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4]) 00161 { 00162 const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y; 00163 if (denom == 0.0) 00164 return 0.0; 00165 else 00166 return -plane[2] / denom; 00167 } 00168 00169 00170 /* 00171 * Solve plane and return clamped GLchan value. 00172 */ 00173 static INLINE GLchan 00174 solve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4]) 00175 { 00176 const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; 00177 #if CHAN_TYPE == GL_FLOAT 00178 return CLAMP(z, 0.0F, CHAN_MAXF); 00179 #else 00180 if (z < 0) 00181 return 0; 00182 else if (z > CHAN_MAX) 00183 return CHAN_MAX; 00184 return (GLchan) IROUND_POS(z); 00185 #endif 00186 } 00187 00188 00189 /* 00190 * Compute mipmap level of detail. 00191 */ 00192 static INLINE GLfloat 00193 compute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4], 00194 GLfloat invQ, GLfloat width, GLfloat height) 00195 { 00196 GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width; 00197 GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width; 00198 GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height; 00199 GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height; 00200 GLfloat r1 = dudx * dudx + dudy * dudy; 00201 GLfloat r2 = dvdx * dvdx + dvdy * dvdy; 00202 GLfloat rho2 = r1 + r2; 00203 /* return log base 2 of rho */ 00204 if (rho2 == 0.0F) 00205 return 0.0; 00206 else 00207 return (GLfloat) (LOGF(rho2) * 1.442695 * 0.5);/* 1.442695 = 1/log(2) */ 00208 } 00209 00210 00211 00212 00213 /* 00214 * Fill in the samples[] array with the (x,y) subpixel positions of 00215 * xSamples * ySamples sample positions. 00216 * Note that the four corner samples are put into the first four 00217 * positions of the array. This allows us to optimize for the common 00218 * case of all samples being inside the polygon. 00219 */ 00220 static void 00221 make_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2]) 00222 { 00223 const GLfloat dx = 1.0F / (GLfloat) xSamples; 00224 const GLfloat dy = 1.0F / (GLfloat) ySamples; 00225 GLint x, y; 00226 GLint i; 00227 00228 i = 4; 00229 for (x = 0; x < xSamples; x++) { 00230 for (y = 0; y < ySamples; y++) { 00231 GLint j; 00232 if (x == 0 && y == 0) { 00233 /* lower left */ 00234 j = 0; 00235 } 00236 else if (x == xSamples - 1 && y == 0) { 00237 /* lower right */ 00238 j = 1; 00239 } 00240 else if (x == 0 && y == ySamples - 1) { 00241 /* upper left */ 00242 j = 2; 00243 } 00244 else if (x == xSamples - 1 && y == ySamples - 1) { 00245 /* upper right */ 00246 j = 3; 00247 } 00248 else { 00249 j = i++; 00250 } 00251 samples[j][0] = x * dx + 0.5F * dx; 00252 samples[j][1] = y * dy + 0.5F * dy; 00253 } 00254 } 00255 } 00256 00257 00258 00259 /* 00260 * Compute how much of the given pixel's area is inside the rectangle 00261 * defined by vertices v0, v1, v2, v3. 00262 * Vertices MUST be specified in counter-clockwise order. 00263 * Return: coverage in [0, 1]. 00264 */ 00265 static GLfloat 00266 compute_coveragef(const struct LineInfo *info, 00267 GLint winx, GLint winy) 00268 { 00269 static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2]; 00270 static GLboolean haveSamples = GL_FALSE; 00271 const GLfloat x = (GLfloat) winx; 00272 const GLfloat y = (GLfloat) winy; 00273 GLint stop = 4, i; 00274 GLfloat insideCount = SUB_PIXEL * SUB_PIXEL; 00275 00276 if (!haveSamples) { 00277 make_sample_table(SUB_PIXEL, SUB_PIXEL, samples); 00278 haveSamples = GL_TRUE; 00279 } 00280 00281 #if 0 /*DEBUG*/ 00282 { 00283 const GLfloat area = dx0 * dy1 - dx1 * dy0; 00284 assert(area >= 0.0); 00285 } 00286 #endif 00287 00288 for (i = 0; i < stop; i++) { 00289 const GLfloat sx = x + samples[i][0]; 00290 const GLfloat sy = y + samples[i][1]; 00291 const GLfloat fx0 = sx - info->qx0; 00292 const GLfloat fy0 = sy - info->qy0; 00293 const GLfloat fx1 = sx - info->qx1; 00294 const GLfloat fy1 = sy - info->qy1; 00295 const GLfloat fx2 = sx - info->qx2; 00296 const GLfloat fy2 = sy - info->qy2; 00297 const GLfloat fx3 = sx - info->qx3; 00298 const GLfloat fy3 = sy - info->qy3; 00299 /* cross product determines if sample is inside or outside each edge */ 00300 GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0); 00301 GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1); 00302 GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2); 00303 GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3); 00304 /* Check if the sample is exactly on an edge. If so, let cross be a 00305 * positive or negative value depending on the direction of the edge. 00306 */ 00307 if (cross0 == 0.0F) 00308 cross0 = info->ex0 + info->ey0; 00309 if (cross1 == 0.0F) 00310 cross1 = info->ex1 + info->ey1; 00311 if (cross2 == 0.0F) 00312 cross2 = info->ex2 + info->ey2; 00313 if (cross3 == 0.0F) 00314 cross3 = info->ex3 + info->ey3; 00315 if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) { 00316 /* point is outside quadrilateral */ 00317 insideCount -= 1.0F; 00318 stop = SUB_PIXEL * SUB_PIXEL; 00319 } 00320 } 00321 if (stop == 4) 00322 return 1.0F; 00323 else 00324 return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL)); 00325 } 00326 00327 00333 static GLfloat 00334 compute_coveragei(const struct LineInfo *info, 00335 GLint winx, GLint winy) 00336 { 00337 return compute_coveragef(info, winx, winy) * 15.0F; 00338 } 00339 00340 00341 00342 typedef void (*plot_func)(GLcontext *ctx, struct LineInfo *line, 00343 int ix, int iy); 00344 00345 00346 00347 /* 00348 * Draw an AA line segment (called many times per line when stippling) 00349 */ 00350 static void 00351 segment(GLcontext *ctx, 00352 struct LineInfo *line, 00353 plot_func plot, 00354 GLfloat t0, GLfloat t1) 00355 { 00356 const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx; 00357 const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy; 00358 /* compute the actual segment's endpoints */ 00359 const GLfloat x0 = line->x0 + t0 * line->dx; 00360 const GLfloat y0 = line->y0 + t0 * line->dy; 00361 const GLfloat x1 = line->x0 + t1 * line->dx; 00362 const GLfloat y1 = line->y0 + t1 * line->dy; 00363 00364 /* compute vertices of the line-aligned quadrilateral */ 00365 line->qx0 = x0 - line->yAdj; 00366 line->qy0 = y0 + line->xAdj; 00367 line->qx1 = x0 + line->yAdj; 00368 line->qy1 = y0 - line->xAdj; 00369 line->qx2 = x1 + line->yAdj; 00370 line->qy2 = y1 - line->xAdj; 00371 line->qx3 = x1 - line->yAdj; 00372 line->qy3 = y1 + line->xAdj; 00373 /* compute the quad's edge vectors (for coverage calc) */ 00374 line->ex0 = line->qx1 - line->qx0; 00375 line->ey0 = line->qy1 - line->qy0; 00376 line->ex1 = line->qx2 - line->qx1; 00377 line->ey1 = line->qy2 - line->qy1; 00378 line->ex2 = line->qx3 - line->qx2; 00379 line->ey2 = line->qy3 - line->qy2; 00380 line->ex3 = line->qx0 - line->qx3; 00381 line->ey3 = line->qy0 - line->qy3; 00382 00383 if (absDx > absDy) { 00384 /* X-major line */ 00385 GLfloat dydx = line->dy / line->dx; 00386 GLfloat xLeft, xRight, yBot, yTop; 00387 GLint ix, ixRight; 00388 if (x0 < x1) { 00389 xLeft = x0 - line->halfWidth; 00390 xRight = x1 + line->halfWidth; 00391 if (line->dy >= 0.0) { 00392 yBot = y0 - 3.0F * line->halfWidth; 00393 yTop = y0 + line->halfWidth; 00394 } 00395 else { 00396 yBot = y0 - line->halfWidth; 00397 yTop = y0 + 3.0F * line->halfWidth; 00398 } 00399 } 00400 else { 00401 xLeft = x1 - line->halfWidth; 00402 xRight = x0 + line->halfWidth; 00403 if (line->dy <= 0.0) { 00404 yBot = y1 - 3.0F * line->halfWidth; 00405 yTop = y1 + line->halfWidth; 00406 } 00407 else { 00408 yBot = y1 - line->halfWidth; 00409 yTop = y1 + 3.0F * line->halfWidth; 00410 } 00411 } 00412 00413 /* scan along the line, left-to-right */ 00414 ixRight = (GLint) (xRight + 1.0F); 00415 00416 /*printf("avg span height: %g\n", yTop - yBot);*/ 00417 for (ix = (GLint) xLeft; ix < ixRight; ix++) { 00418 const GLint iyBot = (GLint) yBot; 00419 const GLint iyTop = (GLint) (yTop + 1.0F); 00420 GLint iy; 00421 /* scan across the line, bottom-to-top */ 00422 for (iy = iyBot; iy < iyTop; iy++) { 00423 (*plot)(ctx, line, ix, iy); 00424 } 00425 yBot += dydx; 00426 yTop += dydx; 00427 } 00428 } 00429 else { 00430 /* Y-major line */ 00431 GLfloat dxdy = line->dx / line->dy; 00432 GLfloat yBot, yTop, xLeft, xRight; 00433 GLint iy, iyTop; 00434 if (y0 < y1) { 00435 yBot = y0 - line->halfWidth; 00436 yTop = y1 + line->halfWidth; 00437 if (line->dx >= 0.0) { 00438 xLeft = x0 - 3.0F * line->halfWidth; 00439 xRight = x0 + line->halfWidth; 00440 } 00441 else { 00442 xLeft = x0 - line->halfWidth; 00443 xRight = x0 + 3.0F * line->halfWidth; 00444 } 00445 } 00446 else { 00447 yBot = y1 - line->halfWidth; 00448 yTop = y0 + line->halfWidth; 00449 if (line->dx <= 0.0) { 00450 xLeft = x1 - 3.0F * line->halfWidth; 00451 xRight = x1 + line->halfWidth; 00452 } 00453 else { 00454 xLeft = x1 - line->halfWidth; 00455 xRight = x1 + 3.0F * line->halfWidth; 00456 } 00457 } 00458 00459 /* scan along the line, bottom-to-top */ 00460 iyTop = (GLint) (yTop + 1.0F); 00461 00462 /*printf("avg span width: %g\n", xRight - xLeft);*/ 00463 for (iy = (GLint) yBot; iy < iyTop; iy++) { 00464 const GLint ixLeft = (GLint) xLeft; 00465 const GLint ixRight = (GLint) (xRight + 1.0F); 00466 GLint ix; 00467 /* scan across the line, left-to-right */ 00468 for (ix = ixLeft; ix < ixRight; ix++) { 00469 (*plot)(ctx, line, ix, iy); 00470 } 00471 xLeft += dxdy; 00472 xRight += dxdy; 00473 } 00474 } 00475 } 00476 00477 00478 #define NAME(x) aa_ci_##x 00479 #define DO_Z 00480 #define DO_ATTRIBS /* for fog */ 00481 #define DO_INDEX 00482 #include "s_aalinetemp.h" 00483 00484 00485 #define NAME(x) aa_rgba_##x 00486 #define DO_Z 00487 #define DO_RGBA 00488 #include "s_aalinetemp.h" 00489 00490 00491 #define NAME(x) aa_general_rgba_##x 00492 #define DO_Z 00493 #define DO_RGBA 00494 #define DO_ATTRIBS 00495 #include "s_aalinetemp.h" 00496 00497 00498 00499 void 00500 _swrast_choose_aa_line_function(GLcontext *ctx) 00501 { 00502 SWcontext *swrast = SWRAST_CONTEXT(ctx); 00503 00504 ASSERT(ctx->Line.SmoothFlag); 00505 00506 if (ctx->Visual.rgbMode) { 00507 /* RGBA */ 00508 if (ctx->Texture._EnabledCoordUnits != 0 00509 || ctx->FragmentProgram._Current 00510 || (ctx->Light.Enabled && 00511 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) 00512 || ctx->Fog.ColorSumEnabled 00513 || swrast->_FogEnabled) { 00514 swrast->Line = aa_general_rgba_line; 00515 } 00516 else { 00517 swrast->Line = aa_rgba_line; 00518 } 00519 } 00520 else { 00521 /* Color Index */ 00522 swrast->Line = aa_ci_line; 00523 } 00524 } Generated on Mon May 28 2012 04:20:21 for ReactOS by
1.7.6.1
|