Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygens_span.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.1 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 00033 #include "main/glheader.h" 00034 #include "main/colormac.h" 00035 #include "main/context.h" 00036 #include "main/macros.h" 00037 #include "main/imports.h" 00038 #include "main/image.h" 00039 00040 #include "s_atifragshader.h" 00041 #include "s_alpha.h" 00042 #include "s_blend.h" 00043 #include "s_context.h" 00044 #include "s_depth.h" 00045 #include "s_fog.h" 00046 #include "s_logic.h" 00047 #include "s_masking.h" 00048 #include "s_fragprog.h" 00049 #include "s_span.h" 00050 #include "s_stencil.h" 00051 #include "s_texcombine.h" 00052 00053 00059 void 00060 _swrast_span_default_attribs(GLcontext *ctx, SWspan *span) 00061 { 00062 /* Z*/ 00063 { 00064 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; 00065 if (ctx->DrawBuffer->Visual.depthBits <= 16) 00066 span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F); 00067 else { 00068 GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax; 00069 tmpf = MIN2(tmpf, depthMax); 00070 span->z = (GLint)tmpf; 00071 } 00072 span->zStep = 0; 00073 span->interpMask |= SPAN_Z; 00074 } 00075 00076 /* W (for perspective correction) */ 00077 span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0; 00078 span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0; 00079 span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0; 00080 00081 /* primary color, or color index */ 00082 if (ctx->Visual.rgbMode) { 00083 GLchan r, g, b, a; 00084 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]); 00085 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]); 00086 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]); 00087 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]); 00088 #if CHAN_TYPE == GL_FLOAT 00089 span->red = r; 00090 span->green = g; 00091 span->blue = b; 00092 span->alpha = a; 00093 #else 00094 span->red = IntToFixed(r); 00095 span->green = IntToFixed(g); 00096 span->blue = IntToFixed(b); 00097 span->alpha = IntToFixed(a); 00098 #endif 00099 span->redStep = 0; 00100 span->greenStep = 0; 00101 span->blueStep = 0; 00102 span->alphaStep = 0; 00103 span->interpMask |= SPAN_RGBA; 00104 00105 COPY_4V(span->attrStart[FRAG_ATTRIB_COL0], ctx->Current.RasterColor); 00106 ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0); 00107 ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0); 00108 } 00109 else { 00110 span->index = FloatToFixed(ctx->Current.RasterIndex); 00111 span->indexStep = 0; 00112 span->interpMask |= SPAN_INDEX; 00113 } 00114 00115 /* Secondary color */ 00116 if (ctx->Visual.rgbMode && (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled)) 00117 { 00118 COPY_4V(span->attrStart[FRAG_ATTRIB_COL1], ctx->Current.RasterSecondaryColor); 00119 ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0); 00120 ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0); 00121 } 00122 00123 /* fog */ 00124 { 00125 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 00126 GLfloat fogVal; /* a coord or a blend factor */ 00127 if (swrast->_PreferPixelFog) { 00128 /* fog blend factors will be computed from fog coordinates per pixel */ 00129 fogVal = ctx->Current.RasterDistance; 00130 } 00131 else { 00132 /* fog blend factor should be computed from fogcoord now */ 00133 fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance); 00134 } 00135 span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal; 00136 span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0; 00137 span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0; 00138 } 00139 00140 /* texcoords */ 00141 { 00142 GLuint i; 00143 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { 00144 const GLuint attr = FRAG_ATTRIB_TEX0 + i; 00145 const GLfloat *tc = ctx->Current.RasterTexCoords[i]; 00146 if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) { 00147 COPY_4V(span->attrStart[attr], tc); 00148 } 00149 else if (tc[3] > 0.0F) { 00150 /* use (s/q, t/q, r/q, 1) */ 00151 span->attrStart[attr][0] = tc[0] / tc[3]; 00152 span->attrStart[attr][1] = tc[1] / tc[3]; 00153 span->attrStart[attr][2] = tc[2] / tc[3]; 00154 span->attrStart[attr][3] = 1.0; 00155 } 00156 else { 00157 ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F); 00158 } 00159 ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F); 00160 ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F); 00161 } 00162 } 00163 } 00164 00165 00172 static INLINE void 00173 interpolate_active_attribs(GLcontext *ctx, SWspan *span, GLbitfield attrMask) 00174 { 00175 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 00176 00177 /* 00178 * Don't overwrite existing array values, such as colors that may have 00179 * been produced by glDraw/CopyPixels. 00180 */ 00181 attrMask &= ~span->arrayAttribs; 00182 00183 ATTRIB_LOOP_BEGIN 00184 if (attrMask & (1 << attr)) { 00185 const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; 00186 GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; 00187 const GLfloat dv0dx = span->attrStepX[attr][0]; 00188 const GLfloat dv1dx = span->attrStepX[attr][1]; 00189 const GLfloat dv2dx = span->attrStepX[attr][2]; 00190 const GLfloat dv3dx = span->attrStepX[attr][3]; 00191 GLfloat v0 = span->attrStart[attr][0]; 00192 GLfloat v1 = span->attrStart[attr][1]; 00193 GLfloat v2 = span->attrStart[attr][2]; 00194 GLfloat v3 = span->attrStart[attr][3]; 00195 GLuint k; 00196 for (k = 0; k < span->end; k++) { 00197 const GLfloat invW = 1.0f / w; 00198 span->array->attribs[attr][k][0] = v0 * invW; 00199 span->array->attribs[attr][k][1] = v1 * invW; 00200 span->array->attribs[attr][k][2] = v2 * invW; 00201 span->array->attribs[attr][k][3] = v3 * invW; 00202 v0 += dv0dx; 00203 v1 += dv1dx; 00204 v2 += dv2dx; 00205 v3 += dv3dx; 00206 w += dwdx; 00207 } 00208 ASSERT((span->arrayAttribs & (1 << attr)) == 0); 00209 span->arrayAttribs |= (1 << attr); 00210 } 00211 ATTRIB_LOOP_END 00212 } 00213 00214 00219 static INLINE void 00220 interpolate_int_colors(GLcontext *ctx, SWspan *span) 00221 { 00222 const GLuint n = span->end; 00223 GLuint i; 00224 00225 #if CHAN_BITS != 32 00226 ASSERT(!(span->arrayMask & SPAN_RGBA)); 00227 #endif 00228 00229 switch (span->array->ChanType) { 00230 #if CHAN_BITS != 32 00231 case GL_UNSIGNED_BYTE: 00232 { 00233 GLubyte (*rgba)[4] = span->array->rgba8; 00234 if (span->interpMask & SPAN_FLAT) { 00235 GLubyte color[4]; 00236 color[RCOMP] = FixedToInt(span->red); 00237 color[GCOMP] = FixedToInt(span->green); 00238 color[BCOMP] = FixedToInt(span->blue); 00239 color[ACOMP] = FixedToInt(span->alpha); 00240 for (i = 0; i < n; i++) { 00241 COPY_4UBV(rgba[i], color); 00242 } 00243 } 00244 else { 00245 GLfixed r = span->red; 00246 GLfixed g = span->green; 00247 GLfixed b = span->blue; 00248 GLfixed a = span->alpha; 00249 GLint dr = span->redStep; 00250 GLint dg = span->greenStep; 00251 GLint db = span->blueStep; 00252 GLint da = span->alphaStep; 00253 for (i = 0; i < n; i++) { 00254 rgba[i][RCOMP] = FixedToChan(r); 00255 rgba[i][GCOMP] = FixedToChan(g); 00256 rgba[i][BCOMP] = FixedToChan(b); 00257 rgba[i][ACOMP] = FixedToChan(a); 00258 r += dr; 00259 g += dg; 00260 b += db; 00261 a += da; 00262 } 00263 } 00264 } 00265 break; 00266 case GL_UNSIGNED_SHORT: 00267 { 00268 GLushort (*rgba)[4] = span->array->rgba16; 00269 if (span->interpMask & SPAN_FLAT) { 00270 GLushort color[4]; 00271 color[RCOMP] = FixedToInt(span->red); 00272 color[GCOMP] = FixedToInt(span->green); 00273 color[BCOMP] = FixedToInt(span->blue); 00274 color[ACOMP] = FixedToInt(span->alpha); 00275 for (i = 0; i < n; i++) { 00276 COPY_4V(rgba[i], color); 00277 } 00278 } 00279 else { 00280 GLushort (*rgba)[4] = span->array->rgba16; 00281 GLfixed r, g, b, a; 00282 GLint dr, dg, db, da; 00283 r = span->red; 00284 g = span->green; 00285 b = span->blue; 00286 a = span->alpha; 00287 dr = span->redStep; 00288 dg = span->greenStep; 00289 db = span->blueStep; 00290 da = span->alphaStep; 00291 for (i = 0; i < n; i++) { 00292 rgba[i][RCOMP] = FixedToChan(r); 00293 rgba[i][GCOMP] = FixedToChan(g); 00294 rgba[i][BCOMP] = FixedToChan(b); 00295 rgba[i][ACOMP] = FixedToChan(a); 00296 r += dr; 00297 g += dg; 00298 b += db; 00299 a += da; 00300 } 00301 } 00302 } 00303 break; 00304 #endif 00305 case GL_FLOAT: 00306 interpolate_active_attribs(ctx, span, FRAG_BIT_COL0); 00307 break; 00308 default: 00309 _mesa_problem(NULL, "bad datatype in interpolate_int_colors"); 00310 } 00311 span->arrayMask |= SPAN_RGBA; 00312 } 00313 00314 00318 static INLINE void 00319 interpolate_float_colors(SWspan *span) 00320 { 00321 GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; 00322 const GLuint n = span->end; 00323 GLuint i; 00324 00325 assert(!(span->arrayAttribs & FRAG_BIT_COL0)); 00326 00327 if (span->arrayMask & SPAN_RGBA) { 00328 /* convert array of int colors */ 00329 for (i = 0; i < n; i++) { 00330 col0[i][0] = UBYTE_TO_FLOAT(span->array->rgba8[i][0]); 00331 col0[i][1] = UBYTE_TO_FLOAT(span->array->rgba8[i][1]); 00332 col0[i][2] = UBYTE_TO_FLOAT(span->array->rgba8[i][2]); 00333 col0[i][3] = UBYTE_TO_FLOAT(span->array->rgba8[i][3]); 00334 } 00335 } 00336 else { 00337 /* interpolate red/green/blue/alpha to get float colors */ 00338 ASSERT(span->interpMask & SPAN_RGBA); 00339 if (span->interpMask & SPAN_FLAT) { 00340 GLfloat r = FixedToFloat(span->red); 00341 GLfloat g = FixedToFloat(span->green); 00342 GLfloat b = FixedToFloat(span->blue); 00343 GLfloat a = FixedToFloat(span->alpha); 00344 for (i = 0; i < n; i++) { 00345 ASSIGN_4V(col0[i], r, g, b, a); 00346 } 00347 } 00348 else { 00349 GLfloat r = FixedToFloat(span->red); 00350 GLfloat g = FixedToFloat(span->green); 00351 GLfloat b = FixedToFloat(span->blue); 00352 GLfloat a = FixedToFloat(span->alpha); 00353 GLfloat dr = FixedToFloat(span->redStep); 00354 GLfloat dg = FixedToFloat(span->greenStep); 00355 GLfloat db = FixedToFloat(span->blueStep); 00356 GLfloat da = FixedToFloat(span->alphaStep); 00357 for (i = 0; i < n; i++) { 00358 col0[i][0] = r; 00359 col0[i][1] = g; 00360 col0[i][2] = b; 00361 col0[i][3] = a; 00362 r += dr; 00363 g += dg; 00364 b += db; 00365 a += da; 00366 } 00367 } 00368 } 00369 00370 span->arrayAttribs |= FRAG_BIT_COL0; 00371 span->array->ChanType = GL_FLOAT; 00372 } 00373 00374 00375 00376 /* Fill in the span.color.index array from the interpolation values */ 00377 static INLINE void 00378 interpolate_indexes(GLcontext *ctx, SWspan *span) 00379 { 00380 GLfixed index = span->index; 00381 const GLint indexStep = span->indexStep; 00382 const GLuint n = span->end; 00383 GLuint *indexes = span->array->index; 00384 GLuint i; 00385 (void) ctx; 00386 00387 ASSERT(!(span->arrayMask & SPAN_INDEX)); 00388 00389 if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) { 00390 /* constant color */ 00391 index = FixedToInt(index); 00392 for (i = 0; i < n; i++) { 00393 indexes[i] = index; 00394 } 00395 } 00396 else { 00397 /* interpolate */ 00398 for (i = 0; i < n; i++) { 00399 indexes[i] = FixedToInt(index); 00400 index += indexStep; 00401 } 00402 } 00403 span->arrayMask |= SPAN_INDEX; 00404 span->interpMask &= ~SPAN_INDEX; 00405 } 00406 00407 00411 void 00412 _swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span ) 00413 { 00414 const GLuint n = span->end; 00415 GLuint i; 00416 00417 ASSERT(!(span->arrayMask & SPAN_Z)); 00418 00419 if (ctx->DrawBuffer->Visual.depthBits <= 16) { 00420 GLfixed zval = span->z; 00421 GLuint *z = span->array->z; 00422 for (i = 0; i < n; i++) { 00423 z[i] = FixedToInt(zval); 00424 zval += span->zStep; 00425 } 00426 } 00427 else { 00428 /* Deep Z buffer, no fixed->int shift */ 00429 GLuint zval = span->z; 00430 GLuint *z = span->array->z; 00431 for (i = 0; i < n; i++) { 00432 z[i] = zval; 00433 zval += span->zStep; 00434 } 00435 } 00436 span->interpMask &= ~SPAN_Z; 00437 span->arrayMask |= SPAN_Z; 00438 } 00439 00440 00445 GLfloat 00446 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 00447 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, 00448 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) 00449 { 00450 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ); 00451 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ); 00452 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ); 00453 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ); 00454 GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx); 00455 GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy); 00456 GLfloat rho = MAX2(x, y); 00457 GLfloat lambda = LOG2(rho); 00458 return lambda; 00459 } 00460 00461 00466 #if 0 00467 GLfloat 00468 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 00469 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, 00470 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) 00471 { 00472 GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ; 00473 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ; 00474 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ; 00475 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ; 00476 GLfloat maxU, maxV, rho, lambda; 00477 dsdx2 = FABSF(dsdx2); 00478 dsdy2 = FABSF(dsdy2); 00479 dtdx2 = FABSF(dtdx2); 00480 dtdy2 = FABSF(dtdy2); 00481 maxU = MAX2(dsdx2, dsdy2) * texW; 00482 maxV = MAX2(dtdx2, dtdy2) * texH; 00483 rho = MAX2(maxU, maxV); 00484 lambda = LOG2(rho); 00485 return lambda; 00486 } 00487 #endif 00488 00489 00501 static void 00502 interpolate_texcoords(GLcontext *ctx, SWspan *span) 00503 { 00504 const GLuint maxUnit 00505 = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1; 00506 GLuint u; 00507 00508 /* XXX CoordUnits vs. ImageUnits */ 00509 for (u = 0; u < maxUnit; u++) { 00510 if (ctx->Texture._EnabledCoordUnits & (1 << u)) { 00511 const GLuint attr = FRAG_ATTRIB_TEX0 + u; 00512 const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; 00513 GLfloat texW, texH; 00514 GLboolean needLambda; 00515 GLfloat (*texcoord)[4] = span->array->attribs[attr]; 00516 GLfloat *lambda = span->array->lambda[u]; 00517 const GLfloat dsdx = span->attrStepX[attr][0]; 00518 const GLfloat dsdy = span->attrStepY[attr][0]; 00519 const GLfloat dtdx = span->attrStepX[attr][1]; 00520 const GLfloat dtdy = span->attrStepY[attr][1]; 00521 const GLfloat drdx = span->attrStepX[attr][2]; 00522 const GLfloat dqdx = span->attrStepX[attr][3]; 00523 const GLfloat dqdy = span->attrStepY[attr][3]; 00524 GLfloat s = span->attrStart[attr][0]; 00525 GLfloat t = span->attrStart[attr][1]; 00526 GLfloat r = span->attrStart[attr][2]; 00527 GLfloat q = span->attrStart[attr][3]; 00528 00529 if (obj) { 00530 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; 00531 needLambda = (obj->MinFilter != obj->MagFilter) 00532 || ctx->FragmentProgram._Current; 00533 texW = img->WidthScale; 00534 texH = img->HeightScale; 00535 } 00536 else { 00537 /* using a fragment program */ 00538 texW = 1.0; 00539 texH = 1.0; 00540 needLambda = GL_FALSE; 00541 } 00542 00543 if (needLambda) { 00544 GLuint i; 00545 if (ctx->FragmentProgram._Current 00546 || ctx->ATIFragmentShader._Enabled) { 00547 /* do perspective correction but don't divide s, t, r by q */ 00548 const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; 00549 GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; 00550 for (i = 0; i < span->end; i++) { 00551 const GLfloat invW = 1.0F / w; 00552 texcoord[i][0] = s * invW; 00553 texcoord[i][1] = t * invW; 00554 texcoord[i][2] = r * invW; 00555 texcoord[i][3] = q * invW; 00556 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 00557 dqdx, dqdy, texW, texH, 00558 s, t, q, invW); 00559 s += dsdx; 00560 t += dtdx; 00561 r += drdx; 00562 q += dqdx; 00563 w += dwdx; 00564 } 00565 } 00566 else { 00567 for (i = 0; i < span->end; i++) { 00568 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 00569 texcoord[i][0] = s * invQ; 00570 texcoord[i][1] = t * invQ; 00571 texcoord[i][2] = r * invQ; 00572 texcoord[i][3] = q; 00573 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 00574 dqdx, dqdy, texW, texH, 00575 s, t, q, invQ); 00576 s += dsdx; 00577 t += dtdx; 00578 r += drdx; 00579 q += dqdx; 00580 } 00581 } 00582 span->arrayMask |= SPAN_LAMBDA; 00583 } 00584 else { 00585 GLuint i; 00586 if (ctx->FragmentProgram._Current || 00587 ctx->ATIFragmentShader._Enabled) { 00588 /* do perspective correction but don't divide s, t, r by q */ 00589 const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; 00590 GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; 00591 for (i = 0; i < span->end; i++) { 00592 const GLfloat invW = 1.0F / w; 00593 texcoord[i][0] = s * invW; 00594 texcoord[i][1] = t * invW; 00595 texcoord[i][2] = r * invW; 00596 texcoord[i][3] = q * invW; 00597 lambda[i] = 0.0; 00598 s += dsdx; 00599 t += dtdx; 00600 r += drdx; 00601 q += dqdx; 00602 w += dwdx; 00603 } 00604 } 00605 else if (dqdx == 0.0F) { 00606 /* Ortho projection or polygon's parallel to window X axis */ 00607 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 00608 for (i = 0; i < span->end; i++) { 00609 texcoord[i][0] = s * invQ; 00610 texcoord[i][1] = t * invQ; 00611 texcoord[i][2] = r * invQ; 00612 texcoord[i][3] = q; 00613 lambda[i] = 0.0; 00614 s += dsdx; 00615 t += dtdx; 00616 r += drdx; 00617 } 00618 } 00619 else { 00620 for (i = 0; i < span->end; i++) { 00621 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 00622 texcoord[i][0] = s * invQ; 00623 texcoord[i][1] = t * invQ; 00624 texcoord[i][2] = r * invQ; 00625 texcoord[i][3] = q; 00626 lambda[i] = 0.0; 00627 s += dsdx; 00628 t += dtdx; 00629 r += drdx; 00630 q += dqdx; 00631 } 00632 } 00633 } /* lambda */ 00634 } /* if */ 00635 } /* for */ 00636 } 00637 00638 00642 static INLINE void 00643 interpolate_wpos(GLcontext *ctx, SWspan *span) 00644 { 00645 GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS]; 00646 GLuint i; 00647 const GLfloat zScale = 1.0 / ctx->DrawBuffer->_DepthMaxF; 00648 GLfloat w, dw; 00649 00650 if (span->arrayMask & SPAN_XY) { 00651 for (i = 0; i < span->end; i++) { 00652 wpos[i][0] = (GLfloat) span->array->x[i]; 00653 wpos[i][1] = (GLfloat) span->array->y[i]; 00654 } 00655 } 00656 else { 00657 for (i = 0; i < span->end; i++) { 00658 wpos[i][0] = (GLfloat) span->x + i; 00659 wpos[i][1] = (GLfloat) span->y; 00660 } 00661 } 00662 00663 w = span->attrStart[FRAG_ATTRIB_WPOS][3]; 00664 dw = span->attrStepX[FRAG_ATTRIB_WPOS][3]; 00665 for (i = 0; i < span->end; i++) { 00666 wpos[i][2] = (GLfloat) span->array->z[i] * zScale; 00667 wpos[i][3] = w; 00668 w += dw; 00669 } 00670 } 00671 00672 00676 static INLINE void 00677 stipple_polygon_span(GLcontext *ctx, SWspan *span) 00678 { 00679 GLubyte *mask = span->array->mask; 00680 00681 ASSERT(ctx->Polygon.StippleFlag); 00682 00683 if (span->arrayMask & SPAN_XY) { 00684 /* arrays of x/y pixel coords */ 00685 GLuint i; 00686 for (i = 0; i < span->end; i++) { 00687 const GLint col = span->array->x[i] % 32; 00688 const GLint row = span->array->y[i] % 32; 00689 const GLuint stipple = ctx->PolygonStipple[row]; 00690 if (((1 << col) & stipple) == 0) { 00691 mask[i] = 0; 00692 } 00693 } 00694 } 00695 else { 00696 /* horizontal span of pixels */ 00697 const GLuint highBit = 1 << 31; 00698 const GLuint stipple = ctx->PolygonStipple[span->y % 32]; 00699 GLuint i, m = highBit >> (GLuint) (span->x % 32); 00700 for (i = 0; i < span->end; i++) { 00701 if ((m & stipple) == 0) { 00702 mask[i] = 0; 00703 } 00704 m = m >> 1; 00705 if (m == 0) { 00706 m = highBit; 00707 } 00708 } 00709 } 00710 span->writeAll = GL_FALSE; 00711 } 00712 00713 00721 static INLINE GLuint 00722 clip_span( GLcontext *ctx, SWspan *span ) 00723 { 00724 const GLint xmin = ctx->DrawBuffer->_Xmin; 00725 const GLint xmax = ctx->DrawBuffer->_Xmax; 00726 const GLint ymin = ctx->DrawBuffer->_Ymin; 00727 const GLint ymax = ctx->DrawBuffer->_Ymax; 00728 00729 if (span->arrayMask & SPAN_XY) { 00730 /* arrays of x/y pixel coords */ 00731 const GLint *x = span->array->x; 00732 const GLint *y = span->array->y; 00733 const GLint n = span->end; 00734 GLubyte *mask = span->array->mask; 00735 GLint i; 00736 if (span->arrayMask & SPAN_MASK) { 00737 /* note: using & intead of && to reduce branches */ 00738 for (i = 0; i < n; i++) { 00739 mask[i] &= (x[i] >= xmin) & (x[i] < xmax) 00740 & (y[i] >= ymin) & (y[i] < ymax); 00741 } 00742 } 00743 else { 00744 /* note: using & intead of && to reduce branches */ 00745 for (i = 0; i < n; i++) { 00746 mask[i] = (x[i] >= xmin) & (x[i] < xmax) 00747 & (y[i] >= ymin) & (y[i] < ymax); 00748 } 00749 } 00750 return GL_TRUE; /* some pixels visible */ 00751 } 00752 else { 00753 /* horizontal span of pixels */ 00754 const GLint x = span->x; 00755 const GLint y = span->y; 00756 const GLint n = span->end; 00757 00758 /* Trivial rejection tests */ 00759 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) { 00760 span->end = 0; 00761 return GL_FALSE; /* all pixels clipped */ 00762 } 00763 00764 /* Clip to the left */ 00765 if (x < xmin) { 00766 ASSERT(x + n > xmin); 00767 span->writeAll = GL_FALSE; 00768 _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte)); 00769 } 00770 00771 /* Clip to right */ 00772 if (x + n > xmax) { 00773 ASSERT(x < xmax); 00774 span->end = xmax - x; 00775 } 00776 00777 return GL_TRUE; /* some pixels visible */ 00778 } 00779 } 00780 00781 00789 void 00790 _swrast_write_index_span( GLcontext *ctx, SWspan *span) 00791 { 00792 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 00793 const GLbitfield origInterpMask = span->interpMask; 00794 const GLbitfield origArrayMask = span->arrayMask; 00795 struct gl_framebuffer *fb = ctx->DrawBuffer; 00796 00797 ASSERT(span->end <= MAX_WIDTH); 00798 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || 00799 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); 00800 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX); 00801 /* 00802 ASSERT((span->interpMask & span->arrayMask) == 0); 00803 */ 00804 00805 if (span->arrayMask & SPAN_MASK) { 00806 /* mask was initialized by caller, probably glBitmap */ 00807 span->writeAll = GL_FALSE; 00808 } 00809 else { 00810 _mesa_memset(span->array->mask, 1, span->end); 00811 span->writeAll = GL_TRUE; 00812 } 00813 00814 /* Clipping */ 00815 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { 00816 if (!clip_span(ctx, span)) { 00817 return; 00818 } 00819 } 00820 00821 /* Depth bounds test */ 00822 if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) { 00823 if (!_swrast_depth_bounds_test(ctx, span)) { 00824 return; 00825 } 00826 } 00827 00828 #ifdef DEBUG 00829 /* Make sure all fragments are within window bounds */ 00830 if (span->arrayMask & SPAN_XY) { 00831 GLuint i; 00832 for (i = 0; i < span->end; i++) { 00833 if (span->array->mask[i]) { 00834 assert(span->array->x[i] >= fb->_Xmin); 00835 assert(span->array->x[i] < fb->_Xmax); 00836 assert(span->array->y[i] >= fb->_Ymin); 00837 assert(span->array->y[i] < fb->_Ymax); 00838 } 00839 } 00840 } 00841 #endif 00842 00843 /* Polygon Stippling */ 00844 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 00845 stipple_polygon_span(ctx, span); 00846 } 00847 00848 /* Stencil and Z testing */ 00849 if (ctx->Depth.Test || ctx->Stencil.Enabled) { 00850 if (!(span->arrayMask & SPAN_Z)) 00851 _swrast_span_interpolate_z(ctx, span); 00852 00853 if (ctx->Stencil.Enabled) { 00854 if (!_swrast_stencil_and_ztest_span(ctx, span)) { 00855 span->arrayMask = origArrayMask; 00856 return; 00857 } 00858 } 00859 else { 00860 ASSERT(ctx->Depth.Test); 00861 if (!_swrast_depth_test_span(ctx, span)) { 00862 span->interpMask = origInterpMask; 00863 span->arrayMask = origArrayMask; 00864 return; 00865 } 00866 } 00867 } 00868 00869 #if FEATURE_ARB_occlusion_query 00870 if (ctx->Query.CurrentOcclusionObject) { 00871 /* update count of 'passed' fragments */ 00872 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; 00873 GLuint i; 00874 for (i = 0; i < span->end; i++) 00875 q->Result += span->array->mask[i]; 00876 } 00877 #endif 00878 00879 /* we have to wait until after occlusion to do this test */ 00880 if (ctx->Color.IndexMask == 0) { 00881 /* write no pixels */ 00882 span->arrayMask = origArrayMask; 00883 return; 00884 } 00885 00886 /* Interpolate the color indexes if needed */ 00887 if (swrast->_FogEnabled || 00888 ctx->Color.IndexLogicOpEnabled || 00889 ctx->Color.IndexMask != 0xffffffff || 00890 (span->arrayMask & SPAN_COVERAGE)) { 00891 if (!(span->arrayMask & SPAN_INDEX) /*span->interpMask & SPAN_INDEX*/) { 00892 interpolate_indexes(ctx, span); 00893 } 00894 } 00895 00896 /* Fog */ 00897 if (swrast->_FogEnabled) { 00898 _swrast_fog_ci_span(ctx, span); 00899 } 00900 00901 /* Antialias coverage application */ 00902 if (span->arrayMask & SPAN_COVERAGE) { 00903 const GLfloat *coverage = span->array->coverage; 00904 GLuint *index = span->array->index; 00905 GLuint i; 00906 for (i = 0; i < span->end; i++) { 00907 ASSERT(coverage[i] < 16); 00908 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]); 00909 } 00910 } 00911 00912 /* 00913 * Write to renderbuffers 00914 */ 00915 { 00916 const GLuint numBuffers = fb->_NumColorDrawBuffers; 00917 GLuint buf; 00918 00919 for (buf = 0; buf < numBuffers; buf++) { 00920 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf]; 00921 GLuint indexSave[MAX_WIDTH]; 00922 00923 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX); 00924 00925 if (numBuffers > 1) { 00926 /* save indexes for second, third renderbuffer writes */ 00927 _mesa_memcpy(indexSave, span->array->index, 00928 span->end * sizeof(indexSave[0])); 00929 } 00930 00931 if (ctx->Color.IndexLogicOpEnabled) { 00932 _swrast_logicop_ci_span(ctx, rb, span); 00933 } 00934 00935 if (ctx->Color.IndexMask != 0xffffffff) { 00936 _swrast_mask_ci_span(ctx, rb, span); 00937 } 00938 00939 if (!(span->arrayMask & SPAN_INDEX) && span->indexStep == 0) { 00940 /* all fragments have same color index */ 00941 GLubyte index8; 00942 GLushort index16; 00943 GLuint index32; 00944 void *value; 00945 00946 if (rb->DataType == GL_UNSIGNED_BYTE) { 00947 index8 = FixedToInt(span->index); 00948 value = &index8; 00949 } 00950 else if (rb->DataType == GL_UNSIGNED_SHORT) { 00951 index16 = FixedToInt(span->index); 00952 value = &index16; 00953 } 00954 else { 00955 ASSERT(rb->DataType == GL_UNSIGNED_INT); 00956 index32 = FixedToInt(span->index); 00957 value = &index32; 00958 } 00959 00960 if (span->arrayMask & SPAN_XY) { 00961 rb->PutMonoValues(ctx, rb, span->end, span->array->x, 00962 span->array->y, value, span->array->mask); 00963 } 00964 else { 00965 rb->PutMonoRow(ctx, rb, span->end, span->x, span->y, 00966 value, span->array->mask); 00967 } 00968 } 00969 else { 00970 /* each fragment is a different color */ 00971 GLubyte index8[MAX_WIDTH]; 00972 GLushort index16[MAX_WIDTH]; 00973 void *values; 00974 00975 if (rb->DataType == GL_UNSIGNED_BYTE) { 00976 GLuint k; 00977 for (k = 0; k < span->end; k++) { 00978 index8[k] = (GLubyte) span->array->index[k]; 00979 } 00980 values = index8; 00981 } 00982 else if (rb->DataType == GL_UNSIGNED_SHORT) { 00983 GLuint k; 00984 for (k = 0; k < span->end; k++) { 00985 index16[k] = (GLushort) span->array->index[k]; 00986 } 00987 values = index16; 00988 } 00989 else { 00990 ASSERT(rb->DataType == GL_UNSIGNED_INT); 00991 values = span->array->index; 00992 } 00993 00994 if (span->arrayMask & SPAN_XY) { 00995 rb->PutValues(ctx, rb, span->end, 00996 span->array->x, span->array->y, 00997 values, span->array->mask); 00998 } 00999 else { 01000 rb->PutRow(ctx, rb, span->end, span->x, span->y, 01001 values, span->array->mask); 01002 } 01003 } 01004 01005 if (buf + 1 < numBuffers) { 01006 /* restore original span values */ 01007 _mesa_memcpy(span->array->index, indexSave, 01008 span->end * sizeof(indexSave[0])); 01009 } 01010 } /* for buf */ 01011 } 01012 01013 span->interpMask = origInterpMask; 01014 span->arrayMask = origArrayMask; 01015 } 01016 01017 01023 static INLINE void 01024 add_specular(GLcontext *ctx, SWspan *span) 01025 { 01026 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 01027 const GLubyte *mask = span->array->mask; 01028 GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; 01029 GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1]; 01030 GLuint i; 01031 01032 ASSERT(!ctx->FragmentProgram._Current); 01033 ASSERT(span->arrayMask & SPAN_RGBA); 01034 ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1); 01035 (void) swrast; /* silence warning */ 01036 01037 if (span->array->ChanType == GL_FLOAT) { 01038 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) { 01039 interpolate_active_attribs(ctx, span, FRAG_BIT_COL0); 01040 } 01041 } 01042 else { 01043 /* need float colors */ 01044 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) { 01045 interpolate_float_colors(span); 01046 } 01047 } 01048 01049 if ((span->arrayAttribs & FRAG_BIT_COL1) == 0) { 01050 /* XXX could avoid this and interpolate COL1 in the loop below */ 01051 interpolate_active_attribs(ctx, span, FRAG_BIT_COL1); 01052 } 01053 01054 ASSERT(span->arrayAttribs & FRAG_BIT_COL0); 01055 ASSERT(span->arrayAttribs & FRAG_BIT_COL1); 01056 01057 for (i = 0; i < span->end; i++) { 01058 if (mask[i]) { 01059 col0[i][0] += col1[i][0]; 01060 col0[i][1] += col1[i][1]; 01061 col0[i][2] += col1[i][2]; 01062 } 01063 } 01064 01065 span->array->ChanType = GL_FLOAT; 01066 } 01067 01068 01072 static INLINE void 01073 apply_aa_coverage(SWspan *span) 01074 { 01075 const GLfloat *coverage = span->array->coverage; 01076 GLuint i; 01077 if (span->array->ChanType == GL_UNSIGNED_BYTE) { 01078 GLubyte (*rgba)[4] = span->array->rgba8; 01079 for (i = 0; i < span->end; i++) { 01080 const GLfloat a = rgba[i][ACOMP] * coverage[i]; 01081 rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0); 01082 ASSERT(coverage[i] >= 0.0); 01083 ASSERT(coverage[i] <= 1.0); 01084 } 01085 } 01086 else if (span->array->ChanType == GL_UNSIGNED_SHORT) { 01087 GLushort (*rgba)[4] = span->array->rgba16; 01088 for (i = 0; i < span->end; i++) { 01089 const GLfloat a = rgba[i][ACOMP] * coverage[i]; 01090 rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0); 01091 } 01092 } 01093 else { 01094 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; 01095 for (i = 0; i < span->end; i++) { 01096 rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i]; 01097 /* clamp later */ 01098 } 01099 } 01100 } 01101 01102 01106 static INLINE void 01107 clamp_colors(SWspan *span) 01108 { 01109 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; 01110 GLuint i; 01111 ASSERT(span->array->ChanType == GL_FLOAT); 01112 for (i = 0; i < span->end; i++) { 01113 rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); 01114 rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); 01115 rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); 01116 rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); 01117 } 01118 } 01119 01120 01127 static INLINE void 01128 convert_color_type(SWspan *span, GLenum newType, GLuint output) 01129 { 01130 GLvoid *src, *dst; 01131 01132 if (output > 0 || span->array->ChanType == GL_FLOAT) { 01133 src = span->array->attribs[FRAG_ATTRIB_COL0 + output]; 01134 span->array->ChanType = GL_FLOAT; 01135 } 01136 else if (span->array->ChanType == GL_UNSIGNED_BYTE) { 01137 src = span->array->rgba8; 01138 } 01139 else { 01140 ASSERT(span->array->ChanType == GL_UNSIGNED_SHORT); 01141 src = span->array->rgba16; 01142 } 01143 01144 if (newType == GL_UNSIGNED_BYTE) { 01145 dst = span->array->rgba8; 01146 } 01147 else if (newType == GL_UNSIGNED_SHORT) { 01148 dst = span->array->rgba16; 01149 } 01150 else { 01151 dst = span->array->attribs[FRAG_ATTRIB_COL0]; 01152 } 01153 01154 _mesa_convert_colors(span->array->ChanType, src, 01155 newType, dst, 01156 span->end, span->array->mask); 01157 01158 span->array->ChanType = newType; 01159 span->array->rgba = dst; 01160 } 01161 01162 01163 01167 static INLINE void 01168 shade_texture_span(GLcontext *ctx, SWspan *span) 01169 { 01170 GLbitfield inputsRead; 01171 01172 /* Determine which fragment attributes are actually needed */ 01173 if (ctx->FragmentProgram._Current) { 01174 inputsRead = ctx->FragmentProgram._Current->Base.InputsRead; 01175 } 01176 else { 01177 /* XXX we could be a bit smarter about this */ 01178 inputsRead = ~0; 01179 } 01180 01181 if (ctx->FragmentProgram._Current || 01182 ctx->ATIFragmentShader._Enabled) { 01183 /* programmable shading */ 01184 if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) { 01185 convert_color_type(span, GL_FLOAT, 0); 01186 } 01187 if (span->primitive != GL_POINT || 01188 (span->interpMask & SPAN_RGBA) || 01189 ctx->Point.PointSprite) { 01190 /* for single-pixel points, we populated the arrays already */ 01191 interpolate_active_attribs(ctx, span, ~0); 01192 } 01193 span->array->ChanType = GL_FLOAT; 01194 01195 if (!(span->arrayMask & SPAN_Z)) 01196 _swrast_span_interpolate_z (ctx, span); 01197 01198 #if 0 01199 if (inputsRead & FRAG_BIT_WPOS) 01200 #else 01201 /* XXX always interpolate wpos so that DDX/DDY work */ 01202 #endif 01203 interpolate_wpos(ctx, span); 01204 01205 /* Run fragment program/shader now */ 01206 if (ctx->FragmentProgram._Current) { 01207 _swrast_exec_fragment_program(ctx, span); 01208 } 01209 else { 01210 ASSERT(ctx->ATIFragmentShader._Enabled); 01211 _swrast_exec_fragment_shader(ctx, span); 01212 } 01213 } 01214 else if (ctx->Texture._EnabledUnits) { 01215 /* conventional texturing */ 01216 01217 #if CHAN_BITS == 32 01218 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) { 01219 interpolate_int_colors(ctx, span); 01220 } 01221 #else 01222 if (!(span->arrayMask & SPAN_RGBA)) 01223 interpolate_int_colors(ctx, span); 01224 #endif 01225 if ((span->arrayAttribs & FRAG_BITS_TEX_ANY) == 0x0) 01226 interpolate_texcoords(ctx, span); 01227 01228 _swrast_texture_span(ctx, span); 01229 } 01230 } 01231 01232 01233 01241 void 01242 _swrast_write_rgba_span( GLcontext *ctx, SWspan *span) 01243 { 01244 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 01245 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); 01246 const GLbitfield origInterpMask = span->interpMask; 01247 const GLbitfield origArrayMask = span->arrayMask; 01248 const GLbitfield origArrayAttribs = span->arrayAttribs; 01249 const GLenum origChanType = span->array->ChanType; 01250 void * const origRgba = span->array->rgba; 01251 const GLboolean shader = (ctx->FragmentProgram._Current 01252 || ctx->ATIFragmentShader._Enabled); 01253 const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits; 01254 struct gl_framebuffer *fb = ctx->DrawBuffer; 01255 01256 /* 01257 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, 01258 span->interpMask, span->arrayMask); 01259 */ 01260 01261 ASSERT(span->primitive == GL_POINT || 01262 span->primitive == GL_LINE || 01263 span->primitive == GL_POLYGON || 01264 span->primitive == GL_BITMAP); 01265 ASSERT(span->end <= MAX_WIDTH); 01266 01267 /* Fragment write masks */ 01268 if (span->arrayMask & SPAN_MASK) { 01269 /* mask was initialized by caller, probably glBitmap */ 01270 span->writeAll = GL_FALSE; 01271 } 01272 else { 01273 _mesa_memset(span->array->mask, 1, span->end); 01274 span->writeAll = GL_TRUE; 01275 } 01276 01277 /* Clip to window/scissor box */ 01278 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { 01279 if (!clip_span(ctx, span)) { 01280 return; 01281 } 01282 } 01283 01284 #ifdef DEBUG 01285 /* Make sure all fragments are within window bounds */ 01286 if (span->arrayMask & SPAN_XY) { 01287 GLuint i; 01288 for (i = 0; i < span->end; i++) { 01289 if (span->array->mask[i]) { 01290 assert(span->array->x[i] >= fb->_Xmin); 01291 assert(span->array->x[i] < fb->_Xmax); 01292 assert(span->array->y[i] >= fb->_Ymin); 01293 assert(span->array->y[i] < fb->_Ymax); 01294 } 01295 } 01296 } 01297 #endif 01298 01299 /* Polygon Stippling */ 01300 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 01301 stipple_polygon_span(ctx, span); 01302 } 01303 01304 /* This is the normal place to compute the fragment color/Z 01305 * from texturing or shading. 01306 */ 01307 if (shaderOrTexture && !swrast->_DeferredTexture) { 01308 shade_texture_span(ctx, span); 01309 } 01310 01311 /* Do the alpha test */ 01312 if (ctx->Color.AlphaEnabled) { 01313 if (!_swrast_alpha_test(ctx, span)) { 01314 goto end; 01315 } 01316 } 01317 01318 /* Stencil and Z testing */ 01319 if (ctx->Stencil.Enabled || ctx->Depth.Test) { 01320 if (!(span->arrayMask & SPAN_Z)) 01321 _swrast_span_interpolate_z(ctx, span); 01322 01323 if (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0) { 01324 /* Combined Z/stencil tests */ 01325 if (!_swrast_stencil_and_ztest_span(ctx, span)) { 01326 goto end; 01327 } 01328 } 01329 else if (fb->Visual.depthBits > 0) { 01330 /* Just regular depth testing */ 01331 ASSERT(ctx->Depth.Test); 01332 ASSERT(span->arrayMask & SPAN_Z); 01333 if (!_swrast_depth_test_span(ctx, span)) { 01334 goto end; 01335 } 01336 } 01337 } 01338 01339 #if FEATURE_ARB_occlusion_query 01340 if (ctx->Query.CurrentOcclusionObject) { 01341 /* update count of 'passed' fragments */ 01342 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; 01343 GLuint i; 01344 for (i = 0; i < span->end; i++) 01345 q->Result += span->array->mask[i]; 01346 } 01347 #endif 01348 01349 /* We had to wait until now to check for glColorMask(0,0,0,0) because of 01350 * the occlusion test. 01351 */ 01352 if (colorMask == 0x0) { 01353 goto end; 01354 } 01355 01356 /* If we were able to defer fragment color computation to now, there's 01357 * a good chance that many fragments will have already been killed by 01358 * Z/stencil testing. 01359 */ 01360 if (shaderOrTexture && swrast->_DeferredTexture) { 01361 shade_texture_span(ctx, span); 01362 } 01363 01364 #if CHAN_BITS == 32 01365 if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) { 01366 interpolate_active_attribs(ctx, span, FRAG_BIT_COL0); 01367 } 01368 #else 01369 if ((span->arrayMask & SPAN_RGBA) == 0) { 01370 interpolate_int_colors(ctx, span); 01371 } 01372 #endif 01373 01374 ASSERT(span->arrayMask & SPAN_RGBA); 01375 01376 if (!shader) { 01377 /* Add base and specular colors */ 01378 if (ctx->Fog.ColorSumEnabled || 01379 (ctx->Light.Enabled && 01380 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { 01381 add_specular(ctx, span); 01382 } 01383 } 01384 01385 /* Fog */ 01386 if (swrast->_FogEnabled) { 01387 _swrast_fog_rgba_span(ctx, span); 01388 } 01389 01390 /* Antialias coverage application */ 01391 if (span->arrayMask & SPAN_COVERAGE) { 01392 apply_aa_coverage(span); 01393 } 01394 01395 /* Clamp color/alpha values over the range [0.0, 1.0] before storage */ 01396 if (ctx->Color.ClampFragmentColor == GL_TRUE && 01397 span->array->ChanType == GL_FLOAT) { 01398 clamp_colors(span); 01399 } 01400 01401 /* 01402 * Write to renderbuffers 01403 */ 01404 { 01405 const GLuint numBuffers = fb->_NumColorDrawBuffers; 01406 const GLboolean multiFragOutputs = numBuffers > 1; 01407 GLuint buf; 01408 01409 for (buf = 0; buf < numBuffers; buf++) { 01410 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf]; 01411 01412 /* color[fragOutput] will be written to buffer[buf] */ 01413 01414 if (rb) { 01415 GLchan rgbaSave[MAX_WIDTH][4]; 01416 const GLuint fragOutput = multiFragOutputs ? buf : 0; 01417 01418 if (rb->DataType != span->array->ChanType || fragOutput > 0) { 01419 convert_color_type(span, rb->DataType, fragOutput); 01420 } 01421 01422 if (!multiFragOutputs && numBuffers > 1) { 01423 /* save colors for second, third renderbuffer writes */ 01424 _mesa_memcpy(rgbaSave, span->array->rgba, 01425 4 * span->end * sizeof(GLchan)); 01426 } 01427 01428 ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB); 01429 01430 if (ctx->Color._LogicOpEnabled) { 01431 _swrast_logicop_rgba_span(ctx, rb, span); 01432 } 01433 else if (ctx->Color.BlendEnabled) { 01434 _swrast_blend_span(ctx, rb, span); 01435 } 01436 01437 if (colorMask != 0xffffffff) { 01438 _swrast_mask_rgba_span(ctx, rb, span); 01439 } 01440 01441 if (span->arrayMask & SPAN_XY) { 01442 /* array of pixel coords */ 01443 ASSERT(rb->PutValues); 01444 rb->PutValues(ctx, rb, span->end, 01445 span->array->x, span->array->y, 01446 span->array->rgba, span->array->mask); 01447 } 01448 else { 01449 /* horizontal run of pixels */ 01450 ASSERT(rb->PutRow); 01451 rb->PutRow(ctx, rb, span->end, span->x, span->y, 01452 span->array->rgba, 01453 span->writeAll ? NULL: span->array->mask); 01454 } 01455 01456 if (!multiFragOutputs && numBuffers > 1) { 01457 /* restore original span values */ 01458 _mesa_memcpy(span->array->rgba, rgbaSave, 01459 4 * span->end * sizeof(GLchan)); 01460 } 01461 01462 } /* if rb */ 01463 } /* for buf */ 01464 } 01465 01466 end: 01467 /* restore these values before returning */ 01468 span->interpMask = origInterpMask; 01469 span->arrayMask = origArrayMask; 01470 span->arrayAttribs = origArrayAttribs; 01471 span->array->ChanType = origChanType; 01472 span->array->rgba = origRgba; 01473 } 01474 01475 01482 void 01483 _swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb, 01484 GLuint n, GLint x, GLint y, GLenum dstType, 01485 GLvoid *rgba) 01486 { 01487 const GLint bufWidth = (GLint) rb->Width; 01488 const GLint bufHeight = (GLint) rb->Height; 01489 01490 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { 01491 /* completely above, below, or right */ 01492 /* XXX maybe leave rgba values undefined? */ 01493 _mesa_bzero(rgba, 4 * n * sizeof(GLchan)); 01494 } 01495 else { 01496 GLint skip, length; 01497 if (x < 0) { 01498 /* left edge clipping */ 01499 skip = -x; 01500 length = (GLint) n - skip; 01501 if (length < 0) { 01502 /* completely left of window */ 01503 return; 01504 } 01505 if (length > bufWidth) { 01506 length = bufWidth; 01507 } 01508 } 01509 else if ((GLint) (x + n) > bufWidth) { 01510 /* right edge clipping */ 01511 skip = 0; 01512 length = bufWidth - x; 01513 if (length < 0) { 01514 /* completely to right of window */ 01515 return; 01516 } 01517 } 01518 else { 01519 /* no clipping */ 01520 skip = 0; 01521 length = (GLint) n; 01522 } 01523 01524 ASSERT(rb); 01525 ASSERT(rb->GetRow); 01526 ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA); 01527 01528 if (rb->DataType == dstType) { 01529 rb->GetRow(ctx, rb, length, x + skip, y, 01530 (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType)); 01531 } 01532 else { 01533 GLuint temp[MAX_WIDTH * 4]; 01534 rb->GetRow(ctx, rb, length, x + skip, y, temp); 01535 _mesa_convert_colors(rb->DataType, temp, 01536 dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType), 01537 length, NULL); 01538 } 01539 } 01540 } 01541 01542 01547 void 01548 _swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb, 01549 GLuint n, GLint x, GLint y, GLuint index[] ) 01550 { 01551 const GLint bufWidth = (GLint) rb->Width; 01552 const GLint bufHeight = (GLint) rb->Height; 01553 01554 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { 01555 /* completely above, below, or right */ 01556 _mesa_bzero(index, n * sizeof(GLuint)); 01557 } 01558 else { 01559 GLint skip, length; 01560 if (x < 0) { 01561 /* left edge clipping */ 01562 skip = -x; 01563 length = (GLint) n - skip; 01564 if (length < 0) { 01565 /* completely left of window */ 01566 return; 01567 } 01568 if (length > bufWidth) { 01569 length = bufWidth; 01570 } 01571 } 01572 else if ((GLint) (x + n) > bufWidth) { 01573 /* right edge clipping */ 01574 skip = 0; 01575 length = bufWidth - x; 01576 if (length < 0) { 01577 /* completely to right of window */ 01578 return; 01579 } 01580 } 01581 else { 01582 /* no clipping */ 01583 skip = 0; 01584 length = (GLint) n; 01585 } 01586 01587 ASSERT(rb->GetRow); 01588 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX); 01589 01590 if (rb->DataType == GL_UNSIGNED_BYTE) { 01591 GLubyte index8[MAX_WIDTH]; 01592 GLint i; 01593 rb->GetRow(ctx, rb, length, x + skip, y, index8); 01594 for (i = 0; i < length; i++) 01595 index[skip + i] = index8[i]; 01596 } 01597 else if (rb->DataType == GL_UNSIGNED_SHORT) { 01598 GLushort index16[MAX_WIDTH]; 01599 GLint i; 01600 rb->GetRow(ctx, rb, length, x + skip, y, index16); 01601 for (i = 0; i < length; i++) 01602 index[skip + i] = index16[i]; 01603 } 01604 else if (rb->DataType == GL_UNSIGNED_INT) { 01605 rb->GetRow(ctx, rb, length, x + skip, y, index + skip); 01606 } 01607 } 01608 } 01609 01610 01618 void 01619 _swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, 01620 GLuint count, const GLint x[], const GLint y[], 01621 void *values, GLuint valueSize) 01622 { 01623 GLuint i, inCount = 0, inStart = 0; 01624 01625 for (i = 0; i < count; i++) { 01626 if (x[i] >= 0 && y[i] >= 0 && 01627 x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) { 01628 /* inside */ 01629 if (inCount == 0) 01630 inStart = i; 01631 inCount++; 01632 } 01633 else { 01634 if (inCount > 0) { 01635 /* read [inStart, inStart + inCount) */ 01636 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart, 01637 (GLubyte *) values + inStart * valueSize); 01638 inCount = 0; 01639 } 01640 } 01641 } 01642 if (inCount > 0) { 01643 /* read last values */ 01644 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart, 01645 (GLubyte *) values + inStart * valueSize); 01646 } 01647 } 01648 01649 01654 void 01655 _swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, 01656 GLuint count, GLint x, GLint y, 01657 const GLvoid *values, GLuint valueSize) 01658 { 01659 GLint skip = 0; 01660 01661 if (y < 0 || y >= (GLint) rb->Height) 01662 return; /* above or below */ 01663 01664 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width) 01665 return; /* entirely left or right */ 01666 01667 if ((GLint) (x + count) > (GLint) rb->Width) { 01668 /* right clip */ 01669 GLint clip = x + count - rb->Width; 01670 count -= clip; 01671 } 01672 01673 if (x < 0) { 01674 /* left clip */ 01675 skip = -x; 01676 x = 0; 01677 count -= skip; 01678 } 01679 01680 rb->PutRow(ctx, rb, count, x, y, 01681 (const GLubyte *) values + skip * valueSize, NULL); 01682 } 01683 01684 01689 void 01690 _swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, 01691 GLuint count, GLint x, GLint y, 01692 GLvoid *values, GLuint valueSize) 01693 { 01694 GLint skip = 0; 01695 01696 if (y < 0 || y >= (GLint) rb->Height) 01697 return; /* above or below */ 01698 01699 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width) 01700 return; /* entirely left or right */ 01701 01702 if (x + count > rb->Width) { 01703 /* right clip */ 01704 GLint clip = x + count - rb->Width; 01705 count -= clip; 01706 } 01707 01708 if (x < 0) { 01709 /* left clip */ 01710 skip = -x; 01711 x = 0; 01712 count -= skip; 01713 } 01714 01715 rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize); 01716 } 01717 01718 01726 void * 01727 _swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb, 01728 SWspan *span) 01729 { 01730 const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType); 01731 void *rbPixels; 01732 01733 /* 01734 * Point rbPixels to a temporary space (use specular color arrays). 01735 */ 01736 rbPixels = span->array->attribs[FRAG_ATTRIB_COL1]; 01737 01738 /* Get destination values from renderbuffer */ 01739 if (span->arrayMask & SPAN_XY) { 01740 _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y, 01741 rbPixels, pixelSize); 01742 } 01743 else { 01744 _swrast_get_row(ctx, rb, span->end, span->x, span->y, 01745 rbPixels, pixelSize); 01746 } 01747 01748 return rbPixels; 01749 } Generated on Sun May 27 2012 04:20:43 for ReactOS by
1.7.6.1
|