/** * As above, but 3D interpolation of 8 values. */ static INLINE float lerp_3d(float a, float b, float c, float v000, float v100, float v010, float v110, float v001, float v101, float v011, float v111) { const float temp0 = lerp_2d(a, b, v000, v100, v010, v110); const float temp1 = lerp_2d(a, b, v001, v101, v011, v111); return lerp(c, temp0, temp1); }
/** * Bilinear interpolation of two source rows. * GLubyte pixels. */ static void resample_linear_row_ub(GLint srcWidth, GLint dstWidth, const GLvoid *srcBuffer0, const GLvoid *srcBuffer1, GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight) { const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0; const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1; GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer; const GLfloat dstWidthF = (GLfloat) dstWidth; GLint dstCol; for (dstCol = 0; dstCol < dstWidth; dstCol++) { const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF; GLint srcCol0 = IFLOOR(srcCol); GLint srcCol1 = srcCol0 + 1; GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */ GLfloat red, green, blue, alpha; ASSERT(srcCol0 >= 0); ASSERT(srcCol0 < srcWidth); ASSERT(srcCol1 <= srcWidth); if (srcCol1 == srcWidth) { /* last column fudge */ srcCol1--; colWeight = 0.0; } if (flip) { srcCol0 = srcWidth - 1 - srcCol0; srcCol1 = srcWidth - 1 - srcCol1; } red = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP], srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]); green = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP], srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]); blue = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP], srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]); alpha = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP], srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]); dstColor[dstCol][RCOMP] = IFLOOR(red); dstColor[dstCol][GCOMP] = IFLOOR(green); dstColor[dstCol][BCOMP] = IFLOOR(blue); dstColor[dstCol][ACOMP] = IFLOOR(alpha); } }
/** * Bilinear interpolation of two source rows. floating point pixels. */ static void resample_linear_row_float(GLint srcWidth, GLint dstWidth, const GLvoid *srcBuffer0, const GLvoid *srcBuffer1, GLvoid *dstBuffer, GLboolean flip, GLfloat rowWeight) { const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4]) srcBuffer0; const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4]) srcBuffer1; GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer; GLint dstCol; for (dstCol = 0; dstCol < dstWidth; dstCol++) { const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F; GLint srcCol0 = MAX2(0, IFLOOR(srcCol)); GLint srcCol1 = srcCol0 + 1; GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */ GLfloat red, green, blue, alpha; assert(srcCol0 < srcWidth); assert(srcCol1 <= srcWidth); if (srcCol1 == srcWidth) { /* last column fudge */ srcCol1--; colWeight = 0.0; } if (flip) { srcCol0 = srcWidth - 1 - srcCol0; srcCol1 = srcWidth - 1 - srcCol1; } red = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][RCOMP], srcColor0[srcCol1][RCOMP], srcColor1[srcCol0][RCOMP], srcColor1[srcCol1][RCOMP]); green = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][GCOMP], srcColor0[srcCol1][GCOMP], srcColor1[srcCol0][GCOMP], srcColor1[srcCol1][GCOMP]); blue = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][BCOMP], srcColor0[srcCol1][BCOMP], srcColor1[srcCol0][BCOMP], srcColor1[srcCol1][BCOMP]); alpha = lerp_2d(colWeight, rowWeight, srcColor0[srcCol0][ACOMP], srcColor0[srcCol1][ACOMP], srcColor1[srcCol0][ACOMP], srcColor1[srcCol1][ACOMP]); dstColor[dstCol][RCOMP] = red; dstColor[dstCol][GCOMP] = green; dstColor[dstCol][BCOMP] = blue; dstColor[dstCol][ACOMP] = alpha; } }
/** * Common code for sampling 1D/2D/cube textures. * Could probably extend for 3D... */ static void sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], boolean computeLambda, float lodbias, float rgba[NUM_CHANNELS][QUAD_SIZE], const unsigned faces[4]) { const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); const struct softpipe_context *sp = samp->sp; const uint unit = samp->unit; const struct pipe_texture *texture = sp->texture[unit]; const struct pipe_sampler_state *sampler = sp->sampler[unit]; const uint compare_func = sampler->compare_func; unsigned level0, level1, j, imgFilter; int width, height; float levelBlend; choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias, &level0, &level1, &levelBlend, &imgFilter); assert(sampler->normalized_coords); width = texture->width[level0]; height = texture->height[level0]; assert(width > 0); switch (imgFilter) { case PIPE_TEX_FILTER_NEAREST: { int x[4], y[4]; nearest_texcoord_4(sampler->wrap_s, s, width, x); nearest_texcoord_4(sampler->wrap_t, t, height, y); for (j = 0; j < QUAD_SIZE; j++) { get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { shadow_compare(compare_func, rgba, p, j); } if (level0 != level1) { /* get texels from second mipmap level and blend */ float rgba2[4][4]; unsigned c; x[j] /= 2; y[j] /= 2; get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0, rgba2, j); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ shadow_compare(compare_func, rgba2, p, j); } for (c = 0; c < NUM_CHANNELS; c++) { rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); } } } } break; case PIPE_TEX_FILTER_LINEAR: case PIPE_TEX_FILTER_ANISO: { int x0[4], y0[4], x1[4], y1[4]; float xw[4], yw[4]; /* weights */ linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw); linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw); for (j = 0; j < QUAD_SIZE; j++) { float tx[4][4]; /* texels */ int c; get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0); get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1); get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2); get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { shadow_compare(compare_func, tx, p, 0); shadow_compare(compare_func, tx, p, 1); shadow_compare(compare_func, tx, p, 2); shadow_compare(compare_func, tx, p, 3); } /* interpolate R, G, B, A */ for (c = 0; c < 4; c++) { rgba[c][j] = lerp_2d(xw[j], yw[j], tx[c][0], tx[c][1], tx[c][2], tx[c][3]); } if (level0 != level1) { /* get texels from second mipmap level and blend */ float rgba2[4][4]; x0[j] /= 2; y0[j] /= 2; x1[j] /= 2; y1[j] /= 2; get_texel(tgsi_sampler, faces[j], level1, x0[j], y0[j], 0, tx, 0); get_texel(tgsi_sampler, faces[j], level1, x1[j], y0[j], 0, tx, 1); get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2); get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ shadow_compare(compare_func, tx, p, 0); shadow_compare(compare_func, tx, p, 1); shadow_compare(compare_func, tx, p, 2); shadow_compare(compare_func, tx, p, 3); } /* interpolate R, G, B, A */ for (c = 0; c < 4; c++) { rgba2[c][j] = lerp_2d(xw[j], yw[j], tx[c][0], tx[c][1], tx[c][2], tx[c][3]); } for (c = 0; c < NUM_CHANNELS; c++) { rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); } } } } break; default: assert(0); } }