📄 s_span.c
字号:
/** * Compute mipmap LOD from partial derivatives. * This the ideal solution, as given in the OpenGL spec. */#if 0static GLfloatcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, GLfloat s, GLfloat t, GLfloat q, GLfloat invQ){ GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ); GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ); GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ); GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ); GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx); GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy); GLfloat rho = MAX2(x, y); GLfloat lambda = LOG2(rho); return lambda;}#endif/** * Compute mipmap LOD from partial derivatives. * This is a faster approximation than above function. */GLfloat_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, GLfloat s, GLfloat t, GLfloat q, GLfloat invQ){ GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ; GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ; GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ; GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ; GLfloat maxU, maxV, rho, lambda; dsdx2 = FABSF(dsdx2); dsdy2 = FABSF(dsdy2); dtdx2 = FABSF(dtdx2); dtdy2 = FABSF(dtdy2); maxU = MAX2(dsdx2, dsdy2) * texW; maxV = MAX2(dtdx2, dtdy2) * texH; rho = MAX2(maxU, maxV); lambda = LOG2(rho); return lambda;}/** * Fill in the span.array->attrib[FRAG_ATTRIB_TEXn] arrays from the * using the attrStart/Step values. * * This function only used during fixed-function fragment processing. * * Note: in the places where we divide by Q (or mult by invQ) we're * really doing two things: perspective correction and texcoord * projection. Remember, for texcoord (s,t,r,q) we need to index * texels with (s/q, t/q, r/q). */static voidinterpolate_texcoords(GLcontext *ctx, SWspan *span){ const GLuint maxUnit = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1; GLuint u; /* XXX CoordUnits vs. ImageUnits */ for (u = 0; u < maxUnit; u++) { if (ctx->Texture._EnabledCoordUnits & (1 << u)) { const GLuint attr = FRAG_ATTRIB_TEX0 + u; const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; GLfloat texW, texH; GLboolean needLambda; GLfloat (*texcoord)[4] = span->array->attribs[attr]; GLfloat *lambda = span->array->lambda[u]; const GLfloat dsdx = span->attrStepX[attr][0]; const GLfloat dsdy = span->attrStepY[attr][0]; const GLfloat dtdx = span->attrStepX[attr][1]; const GLfloat dtdy = span->attrStepY[attr][1]; const GLfloat drdx = span->attrStepX[attr][2]; const GLfloat dqdx = span->attrStepX[attr][3]; const GLfloat dqdy = span->attrStepY[attr][3]; GLfloat s = span->attrStart[attr][0]; GLfloat t = span->attrStart[attr][1]; GLfloat r = span->attrStart[attr][2]; GLfloat q = span->attrStart[attr][3]; if (obj) { const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; needLambda = (obj->MinFilter != obj->MagFilter) || ctx->FragmentProgram._Current; texW = img->WidthScale; texH = img->HeightScale; } else { /* using a fragment program */ texW = 1.0; texH = 1.0; needLambda = GL_FALSE; } if (needLambda) { GLuint i; if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) { /* do perspective correction but don't divide s, t, r by q */ const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; for (i = 0; i < span->end; i++) { const GLfloat invW = 1.0F / w; texcoord[i][0] = s * invW; texcoord[i][1] = t * invW; texcoord[i][2] = r * invW; texcoord[i][3] = q * invW; lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, dqdx, dqdy, texW, texH, s, t, q, invW); s += dsdx; t += dtdx; r += drdx; q += dqdx; w += dwdx; } } else { for (i = 0; i < span->end; i++) { const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); texcoord[i][0] = s * invQ; texcoord[i][1] = t * invQ; texcoord[i][2] = r * invQ; texcoord[i][3] = q; lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, dqdx, dqdy, texW, texH, s, t, q, invQ); s += dsdx; t += dtdx; r += drdx; q += dqdx; } } span->arrayMask |= SPAN_LAMBDA; } else { GLuint i; if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) { /* do perspective correction but don't divide s, t, r by q */ const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; for (i = 0; i < span->end; i++) { const GLfloat invW = 1.0F / w; texcoord[i][0] = s * invW; texcoord[i][1] = t * invW; texcoord[i][2] = r * invW; texcoord[i][3] = q * invW; lambda[i] = 0.0; s += dsdx; t += dtdx; r += drdx; q += dqdx; w += dwdx; } } else if (dqdx == 0.0F) { /* Ortho projection or polygon's parallel to window X axis */ const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); for (i = 0; i < span->end; i++) { texcoord[i][0] = s * invQ; texcoord[i][1] = t * invQ; texcoord[i][2] = r * invQ; texcoord[i][3] = q; lambda[i] = 0.0; s += dsdx; t += dtdx; r += drdx; } } else { for (i = 0; i < span->end; i++) { const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); texcoord[i][0] = s * invQ; texcoord[i][1] = t * invQ; texcoord[i][2] = r * invQ; texcoord[i][3] = q; lambda[i] = 0.0; s += dsdx; t += dtdx; r += drdx; q += dqdx; } } } /* lambda */ } /* if */ } /* for */}/** * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array. */static INLINE voidinterpolate_wpos(GLcontext *ctx, SWspan *span){ GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS]; GLuint i; const GLfloat zScale = 1.0 / ctx->DrawBuffer->_DepthMaxF; GLfloat w, dw; if (span->arrayMask & SPAN_XY) { for (i = 0; i < span->end; i++) { wpos[i][0] = (GLfloat) span->array->x[i]; wpos[i][1] = (GLfloat) span->array->y[i]; } } else { for (i = 0; i < span->end; i++) { wpos[i][0] = (GLfloat) span->x + i; wpos[i][1] = (GLfloat) span->y; } } w = span->attrStart[FRAG_ATTRIB_WPOS][3]; dw = span->attrStepX[FRAG_ATTRIB_WPOS][3]; for (i = 0; i < span->end; i++) { wpos[i][2] = (GLfloat) span->array->z[i] * zScale; wpos[i][3] = w; w += dw; }}/** * Apply the current polygon stipple pattern to a span of pixels. */static INLINE voidstipple_polygon_span(GLcontext *ctx, SWspan *span){ GLubyte *mask = span->array->mask; ASSERT(ctx->Polygon.StippleFlag); if (span->arrayMask & SPAN_XY) { /* arrays of x/y pixel coords */ GLuint i; for (i = 0; i < span->end; i++) { const GLint col = span->array->x[i] % 32; const GLint row = span->array->y[i] % 32; const GLuint stipple = ctx->PolygonStipple[row]; if (((1 << col) & stipple) == 0) { mask[i] = 0; } } } else { /* horizontal span of pixels */ const GLuint highBit = 1 << 31; const GLuint stipple = ctx->PolygonStipple[span->y % 32]; GLuint i, m = highBit >> (GLuint) (span->x % 32); for (i = 0; i < span->end; i++) { if ((m & stipple) == 0) { mask[i] = 0; } m = m >> 1; if (m == 0) { m = highBit; } } } span->writeAll = GL_FALSE;}/** * Clip a pixel span to the current buffer/window boundaries: * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish * window clipping and scissoring. * Return: GL_TRUE some pixels still visible * GL_FALSE nothing visible */static INLINE GLuintclip_span( GLcontext *ctx, SWspan *span ){ const GLint xmin = ctx->DrawBuffer->_Xmin; const GLint xmax = ctx->DrawBuffer->_Xmax; const GLint ymin = ctx->DrawBuffer->_Ymin; const GLint ymax = ctx->DrawBuffer->_Ymax; if (span->arrayMask & SPAN_XY) { /* arrays of x/y pixel coords */ const GLint *x = span->array->x; const GLint *y = span->array->y; const GLint n = span->end; GLubyte *mask = span->array->mask; GLint i; if (span->arrayMask & SPAN_MASK) { /* note: using & intead of && to reduce branches */ for (i = 0; i < n; i++) { mask[i] &= (x[i] >= xmin) & (x[i] < xmax) & (y[i] >= ymin) & (y[i] < ymax); } } else { /* note: using & intead of && to reduce branches */ for (i = 0; i < n; i++) { mask[i] = (x[i] >= xmin) & (x[i] < xmax) & (y[i] >= ymin) & (y[i] < ymax); } } return GL_TRUE; /* some pixels visible */ } else { /* horizontal span of pixels */ const GLint x = span->x; const GLint y = span->y; const GLint n = span->end; /* Trivial rejection tests */ if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) { span->end = 0; return GL_FALSE; /* all pixels clipped */ } /* Clip to the left */ if (x < xmin) { ASSERT(x + n > xmin); span->writeAll = GL_FALSE; _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte)); } /* Clip to right */ if (x + n > xmax) { ASSERT(x < xmax); span->end = xmax - x; } return GL_TRUE; /* some pixels visible */ }}/** * Apply all the per-fragment opertions to a span of color index fragments * and write them to the enabled color drawbuffers. * The 'span' parameter can be considered to be const. Note that * span->interpMask and span->arrayMask may be changed but will be restored * to their original values before returning. */void_swrast_write_index_span( GLcontext *ctx, SWspan *span){ const SWcontext *swrast = SWRAST_CONTEXT(ctx); const GLbitfield origInterpMask = span->interpMask; const GLbitfield origArrayMask = span->arrayMask; struct gl_framebuffer *fb = ctx->DrawBuffer; ASSERT(span->end <= MAX_WIDTH); ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX); /* ASSERT((span->interpMask & span->arrayMask) == 0); */ if (span->arrayMask & SPAN_MASK) { /* mask was initialized by caller, probably glBitmap */ span->writeAll = GL_FALSE; } else { _mesa_memset(span->array->mask, 1, span->end); span->writeAll = GL_TRUE; } /* Clipping */ if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { if (!clip_span(ctx, span)) { return; } } /* Depth bounds test */ if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) { if (!_swrast_depth_bounds_test(ctx, span)) { return; } }#ifdef DEBUG /* Make sure all fragments are within window bounds */ if (span->arrayMask & SPAN_XY) { GLuint i; for (i = 0; i < span->end; i++) { if (span->array->mask[i]) { assert(span->array->x[i] >= fb->_Xmin); assert(span->array->x[i] < fb->_Xmax); assert(span->array->y[i] >= fb->_Ymin); assert(span->array->y[i] < fb->_Ymax); } } }#endif /* Polygon Stippling */ if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { stipple_polygon_span(ctx, span); } /* Stencil and Z testing */ if (ctx->Depth.Test || ctx->Stencil.Enabled) { if (!(span->arrayMask & SPAN_Z)) _swrast_span_interpolate_z(ctx, span); if (ctx->Stencil.Enabled) { if (!_swrast_stencil_and_ztest_span(ctx, span)) { span->arrayMask = origArrayMask; return; } } else { ASSERT(ctx->Depth.Test); if (!_swrast_depth_test_span(ctx, span)) { span->interpMask = origInterpMask; span->arrayMask = origArrayMask; return; } } }#if FEATURE_ARB_occlusion_query if (ctx->Query.CurrentOcclusionObject) { /* update count of 'passed' fragments */ struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; GLuint i; for (i = 0; i < span->end; i++) q->Result += span->array->mask[i]; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -