/** * Fetch a texel with the given partial derivatives to compute a level * of detail in the mipmap. * Called via machine->FetchTexelDeriv() * \param lodBias the lod bias which may be specified by a TXB instruction, * otherwise zero. */ static void fetch_texel_deriv( struct gl_context *ctx, const GLfloat texcoord[4], const GLfloat texdx[4], const GLfloat texdy[4], GLfloat lodBias, GLuint unit, GLfloat color[4] ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; const struct gl_texture_object *texObj = texUnit->_Current; if (texObj) { const struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel]; const struct swrast_texture_image *swImg = swrast_texture_image_const(texImg); const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit); const GLfloat texW = (GLfloat) swImg->WidthScale; const GLfloat texH = (GLfloat) swImg->HeightScale; GLfloat lambda; GLfloat rgba[4]; lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */ texdx[1], texdy[1], /* dt/dx, dt/dy */ texdx[3], texdy[3], /* dq/dx, dq/dy */ texW, texH, texcoord[0], texcoord[1], texcoord[3], 1.0F / texcoord[3]); lambda += lodBias + texUnit->LodBias + samp->LodBias; lambda = CLAMP(lambda, samp->MinLod, samp->MaxLod); swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current, 1, (const GLfloat (*)[4]) texcoord, &lambda, &rgba); swizzle_texel(rgba, color, texObj->_Swizzle); } else { ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F); } }
/** * 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 void interpolate_texcoords(struct gl_context *ctx, SWspan *span) { if (ctx->Texture._EnabledCoord) { const GLuint attr = FRAG_ATTRIB_TEX; const struct gl_texture_object *obj = ctx->Texture.Unit._Current; GLfloat texW, texH; GLboolean needLambda; GLfloat (*texcoord)[4] = span->array->attribs[attr]; GLfloat *lambda = span->array->lambda; 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] + span->leftClip * dsdx; GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx; GLfloat r = span->attrStart[attr][2] + span->leftClip * drdx; GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx; if (obj) { const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; const struct swrast_texture_image *swImg = swrast_texture_image_const(img); needLambda = (obj->Sampler.MinFilter != obj->Sampler.MagFilter); /* LOD is calculated directly in the ansiotropic filter, we can * skip the normal lambda function as the result is ignored. */ if (obj->Sampler.MaxAnisotropy > 1.0 && obj->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) { needLambda = GL_FALSE; } texW = swImg->WidthScale; texH = swImg->HeightScale; } else { /* using a fragment program */ texW = 1.0; texH = 1.0; needLambda = GL_FALSE; } if (needLambda) { GLuint i; 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 (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 */ }