/** * Apply texture mapping to a span of fragments. */ void _swrast_texture_span( struct gl_context *ctx, SWspan *span ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); float4_array primary_rgba; GLuint unit; if (!swrast->TexelBuffer) { #ifdef _OPENMP const GLint maxThreads = omp_get_max_threads(); #else const GLint maxThreads = 1; #endif /* TexelBuffer is also global and normally shared by all SWspan * instances; when running with multiple threads, create one per * thread. */ swrast->TexelBuffer = malloc(ctx->Const.FragmentProgram.MaxTextureImageUnits * maxThreads * SWRAST_MAX_WIDTH * 4 * sizeof(GLfloat)); if (!swrast->TexelBuffer) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine"); return; } } primary_rgba = malloc(span->end * 4 * sizeof(GLfloat)); if (!primary_rgba) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span"); return; } ASSERT(span->end <= SWRAST_MAX_WIDTH); /* * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR) */ if (swrast->_TextureCombinePrimary) { GLuint i; for (i = 0; i < span->end; i++) { primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]); primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]); primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]); primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]); } } /* First must sample all bump maps */ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; if (texUnit->_ReallyEnabled && texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) { const GLfloat (*texcoords)[4] = (const GLfloat (*)[4]) span->array->attribs[VARYING_SLOT_TEX0 + unit]; float4_array targetcoords = span->array->attribs[VARYING_SLOT_TEX0 + ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0]; const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit); GLfloat *lambda = span->array->lambda[unit]; float4_array texels = get_texel_array(swrast, unit); GLuint i; GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0]; GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1]; GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2]; GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3]; /* adjust texture lod (lambda) */ if (span->arrayMask & SPAN_LAMBDA) { if (texUnit->LodBias + samp->LodBias != 0.0F) { /* apply LOD bias, but don't clamp yet */ const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias, -ctx->Const.MaxTextureLodBias, ctx->Const.MaxTextureLodBias); GLuint i; for (i = 0; i < span->end; i++) { lambda[i] += bias; } } if (samp->MinLod != -1000.0 || samp->MaxLod != 1000.0) { /* apply LOD clamping to lambda */ const GLfloat min = samp->MinLod; const GLfloat max = samp->MaxLod; GLuint i; for (i = 0; i < span->end; i++) { GLfloat l = lambda[i]; lambda[i] = CLAMP(l, min, max); } } } /* Sample the texture (span->end = number of fragments) */ swrast->TextureSample[unit]( ctx, samp, ctx->Texture.Unit[unit]._Current, span->end, texcoords, lambda, texels ); /* manipulate the span values of the bump target not sure this can work correctly even ignoring the problem that channel is unsigned */ for (i = 0; i < span->end; i++) { targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] * rotMatrix01) / targetcoords[i][3]; targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] * rotMatrix11) / targetcoords[i][3]; } } } /* * Must do all texture sampling before combining in order to * accomodate GL_ARB_texture_env_crossbar. */ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; if (texUnit->_ReallyEnabled && texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) { const GLfloat (*texcoords)[4] = (const GLfloat (*)[4]) span->array->attribs[VARYING_SLOT_TEX0 + unit]; const struct gl_texture_object *curObj = texUnit->_Current; const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit); GLfloat *lambda = span->array->lambda[unit]; float4_array texels = get_texel_array(swrast, unit); /* adjust texture lod (lambda) */ if (span->arrayMask & SPAN_LAMBDA) { if (texUnit->LodBias + samp->LodBias != 0.0F) { /* apply LOD bias, but don't clamp yet */ const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias, -ctx->Const.MaxTextureLodBias, ctx->Const.MaxTextureLodBias); GLuint i; for (i = 0; i < span->end; i++) { lambda[i] += bias; } } if (samp->MinLod != -1000.0 || samp->MaxLod != 1000.0) { /* apply LOD clamping to lambda */ const GLfloat min = samp->MinLod; const GLfloat max = samp->MaxLod; GLuint i; for (i = 0; i < span->end; i++) { GLfloat l = lambda[i]; lambda[i] = CLAMP(l, min, max); } } } else if (samp->MaxAnisotropy > 1.0 && samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) { /* sample_lambda_2d_aniso is beeing used as texture_sample_func, * it requires the current SWspan *span as an additional parameter. * In order to keep the same function signature, the unused lambda * parameter will be modified to actually contain the SWspan pointer. * This is a Hack. To make it right, the texture_sample_func * signature and all implementing functions need to be modified. */ /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */ lambda = (GLfloat *)span; } /* Sample the texture (span->end = number of fragments) */ swrast->TextureSample[unit]( ctx, samp, ctx->Texture.Unit[unit]._Current, span->end, texcoords, lambda, texels ); /* GL_EXT_texture_swizzle */ if (curObj->_Swizzle != SWIZZLE_NOOP) { swizzle_texels(curObj->_Swizzle, span->end, texels); } } } /* * OK, now apply the texture (aka texture combine/blend). * We modify the span->color.rgba values. */ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { if (ctx->Texture.Unit[unit]._ReallyEnabled) texture_combine(ctx, unit, primary_rgba, swrast->TexelBuffer, span); } free(primary_rgba); }
/** * Apply texture mapping to a span of fragments. */ void _swrast_texture_span( GLcontext *ctx, SWspan *span ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLfloat primary_rgba[MAX_WIDTH][4]; GLuint unit; ASSERT(span->end <= MAX_WIDTH); /* * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR) */ if (swrast->_TextureCombinePrimary) { GLuint i; for (i = 0; i < span->end; i++) { primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]); primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]); primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]); primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]); } } /* First must sample all bump maps */ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; if (texUnit->_ReallyEnabled && texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) { const GLfloat (*texcoords)[4] = (const GLfloat (*)[4]) span->array->attribs[FRAG_ATTRIB_TEX0 + unit]; float4_array targetcoords = span->array->attribs[FRAG_ATTRIB_TEX0 + ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0]; const struct gl_texture_object *curObj = texUnit->_Current; GLfloat *lambda = span->array->lambda[unit]; float4_array texels = get_texel_array(swrast, unit); GLuint i; GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0]; GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1]; GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2]; GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3]; /* adjust texture lod (lambda) */ if (span->arrayMask & SPAN_LAMBDA) { if (texUnit->LodBias + curObj->LodBias != 0.0F) { /* apply LOD bias, but don't clamp yet */ const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias, -ctx->Const.MaxTextureLodBias, ctx->Const.MaxTextureLodBias); GLuint i; for (i = 0; i < span->end; i++) { lambda[i] += bias; } } if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) { /* apply LOD clamping to lambda */ const GLfloat min = curObj->MinLod; const GLfloat max = curObj->MaxLod; GLuint i; for (i = 0; i < span->end; i++) { GLfloat l = lambda[i]; lambda[i] = CLAMP(l, min, max); } } } /* Sample the texture (span->end = number of fragments) */ swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end, texcoords, lambda, texels ); /* manipulate the span values of the bump target not sure this can work correctly even ignoring the problem that channel is unsigned */ for (i = 0; i < span->end; i++) { targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] * rotMatrix01) / targetcoords[i][3]; targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] * rotMatrix11) / targetcoords[i][3]; } } } /* * Must do all texture sampling before combining in order to * accomodate GL_ARB_texture_env_crossbar. */ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; if (texUnit->_ReallyEnabled && texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) { const GLfloat (*texcoords)[4] = (const GLfloat (*)[4]) span->array->attribs[FRAG_ATTRIB_TEX0 + unit]; const struct gl_texture_object *curObj = texUnit->_Current; GLfloat *lambda = span->array->lambda[unit]; float4_array texels = get_texel_array(swrast, unit); /* adjust texture lod (lambda) */ if (span->arrayMask & SPAN_LAMBDA) { if (texUnit->LodBias + curObj->LodBias != 0.0F) { /* apply LOD bias, but don't clamp yet */ const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias, -ctx->Const.MaxTextureLodBias, ctx->Const.MaxTextureLodBias); GLuint i; for (i = 0; i < span->end; i++) { lambda[i] += bias; } } if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) { /* apply LOD clamping to lambda */ const GLfloat min = curObj->MinLod; const GLfloat max = curObj->MaxLod; GLuint i; for (i = 0; i < span->end; i++) { GLfloat l = lambda[i]; lambda[i] = CLAMP(l, min, max); } } } /* Sample the texture (span->end = number of fragments) */ swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end, texcoords, lambda, texels ); /* GL_SGI_texture_color_table */ if (texUnit->ColorTableEnabled) { _mesa_lookup_rgba_float(&texUnit->ColorTable, span->end, texels); } /* GL_EXT_texture_swizzle */ if (curObj->_Swizzle != SWIZZLE_NOOP) { swizzle_texels(curObj->_Swizzle, span->end, texels); } } } /* * OK, now apply the texture (aka texture combine/blend). * We modify the span->color.rgba values. */ for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { if (ctx->Texture.Unit[unit]._ReallyEnabled) { texture_combine( ctx, unit, span->end, primary_rgba, swrast->TexelBuffer, span->array->rgba ); } } }