1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * Copyright 2008-2010 VMware, Inc. All rights reserved. 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 9bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 10bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 11bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 12bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 13bf215546Sopenharmony_ci * the following conditions: 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 16bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 17bf215546Sopenharmony_ci * of the Software. 18bf215546Sopenharmony_ci * 19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26bf215546Sopenharmony_ci * 27bf215546Sopenharmony_ci **************************************************************************/ 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci/** 30bf215546Sopenharmony_ci * Texture sampling 31bf215546Sopenharmony_ci * 32bf215546Sopenharmony_ci * Authors: 33bf215546Sopenharmony_ci * Brian Paul 34bf215546Sopenharmony_ci * Keith Whitwell 35bf215546Sopenharmony_ci */ 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#include "pipe/p_context.h" 38bf215546Sopenharmony_ci#include "pipe/p_defines.h" 39bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h" 40bf215546Sopenharmony_ci#include "util/u_math.h" 41bf215546Sopenharmony_ci#include "util/format/u_format.h" 42bf215546Sopenharmony_ci#include "util/u_memory.h" 43bf215546Sopenharmony_ci#include "util/u_inlines.h" 44bf215546Sopenharmony_ci#include "sp_quad.h" /* only for #define QUAD_* tokens */ 45bf215546Sopenharmony_ci#include "sp_tex_sample.h" 46bf215546Sopenharmony_ci#include "sp_texture.h" 47bf215546Sopenharmony_ci#include "sp_tex_tile_cache.h" 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci/** Set to one to help debug texture sampling */ 51bf215546Sopenharmony_ci#define DEBUG_TEX 0 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/* 55bf215546Sopenharmony_ci * Return fractional part of 'f'. Used for computing interpolation weights. 56bf215546Sopenharmony_ci * Need to be careful with negative values. 57bf215546Sopenharmony_ci * Note, if this function isn't perfect you'll sometimes see 1-pixel bands 58bf215546Sopenharmony_ci * of improperly weighted linear-filtered textures. 59bf215546Sopenharmony_ci * The tests/texwrap.c demo is a good test. 60bf215546Sopenharmony_ci */ 61bf215546Sopenharmony_cistatic inline float 62bf215546Sopenharmony_cifrac(float f) 63bf215546Sopenharmony_ci{ 64bf215546Sopenharmony_ci return f - floorf(f); 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci/** 70bf215546Sopenharmony_ci * Linear interpolation macro 71bf215546Sopenharmony_ci */ 72bf215546Sopenharmony_cistatic inline float 73bf215546Sopenharmony_cilerp(float a, float v0, float v1) 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci return v0 + a * (v1 - v0); 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci/** 80bf215546Sopenharmony_ci * Do 2D/bilinear interpolation of float values. 81bf215546Sopenharmony_ci * v00, v10, v01 and v11 are typically four texture samples in a square/box. 82bf215546Sopenharmony_ci * a and b are the horizontal and vertical interpolants. 83bf215546Sopenharmony_ci * It's important that this function is inlined when compiled with 84bf215546Sopenharmony_ci * optimization! If we find that's not true on some systems, convert 85bf215546Sopenharmony_ci * to a macro. 86bf215546Sopenharmony_ci */ 87bf215546Sopenharmony_cistatic inline float 88bf215546Sopenharmony_cilerp_2d(float a, float b, 89bf215546Sopenharmony_ci float v00, float v10, float v01, float v11) 90bf215546Sopenharmony_ci{ 91bf215546Sopenharmony_ci const float temp0 = lerp(a, v00, v10); 92bf215546Sopenharmony_ci const float temp1 = lerp(a, v01, v11); 93bf215546Sopenharmony_ci return lerp(b, temp0, temp1); 94bf215546Sopenharmony_ci} 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci/** 98bf215546Sopenharmony_ci * As above, but 3D interpolation of 8 values. 99bf215546Sopenharmony_ci */ 100bf215546Sopenharmony_cistatic inline float 101bf215546Sopenharmony_cilerp_3d(float a, float b, float c, 102bf215546Sopenharmony_ci float v000, float v100, float v010, float v110, 103bf215546Sopenharmony_ci float v001, float v101, float v011, float v111) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci const float temp0 = lerp_2d(a, b, v000, v100, v010, v110); 106bf215546Sopenharmony_ci const float temp1 = lerp_2d(a, b, v001, v101, v011, v111); 107bf215546Sopenharmony_ci return lerp(c, temp0, temp1); 108bf215546Sopenharmony_ci} 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci/** 113bf215546Sopenharmony_ci * Compute coord % size for repeat wrap modes. 114bf215546Sopenharmony_ci * Note that if coord is negative, coord % size doesn't give the right 115bf215546Sopenharmony_ci * value. To avoid that problem we add a large multiple of the size 116bf215546Sopenharmony_ci * (rather than using a conditional). 117bf215546Sopenharmony_ci */ 118bf215546Sopenharmony_cistatic inline int 119bf215546Sopenharmony_cirepeat(int coord, unsigned size) 120bf215546Sopenharmony_ci{ 121bf215546Sopenharmony_ci return (coord + size * 1024) % size; 122bf215546Sopenharmony_ci} 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci/** 126bf215546Sopenharmony_ci * Apply texture coord wrapping mode and return integer texture indexes 127bf215546Sopenharmony_ci * for a vector of four texcoords (S or T or P). 128bf215546Sopenharmony_ci * \param wrapMode PIPE_TEX_WRAP_x 129bf215546Sopenharmony_ci * \param s the incoming texcoords 130bf215546Sopenharmony_ci * \param size the texture image size 131bf215546Sopenharmony_ci * \param icoord returns the integer texcoords 132bf215546Sopenharmony_ci */ 133bf215546Sopenharmony_cistatic void 134bf215546Sopenharmony_ciwrap_nearest_repeat(float s, unsigned size, int offset, int *icoord) 135bf215546Sopenharmony_ci{ 136bf215546Sopenharmony_ci /* s limited to [0,1) */ 137bf215546Sopenharmony_ci /* i limited to [0,size-1] */ 138bf215546Sopenharmony_ci const int i = util_ifloor(s * size); 139bf215546Sopenharmony_ci *icoord = repeat(i + offset, size); 140bf215546Sopenharmony_ci} 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_cistatic void 144bf215546Sopenharmony_ciwrap_nearest_clamp(float s, unsigned size, int offset, int *icoord) 145bf215546Sopenharmony_ci{ 146bf215546Sopenharmony_ci /* s limited to [0,1] */ 147bf215546Sopenharmony_ci /* i limited to [0,size-1] */ 148bf215546Sopenharmony_ci s *= size; 149bf215546Sopenharmony_ci s += offset; 150bf215546Sopenharmony_ci if (s <= 0.0F) 151bf215546Sopenharmony_ci *icoord = 0; 152bf215546Sopenharmony_ci else if (s >= size) 153bf215546Sopenharmony_ci *icoord = size - 1; 154bf215546Sopenharmony_ci else 155bf215546Sopenharmony_ci *icoord = util_ifloor(s); 156bf215546Sopenharmony_ci} 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_cistatic void 160bf215546Sopenharmony_ciwrap_nearest_clamp_to_edge(float s, unsigned size, int offset, int *icoord) 161bf215546Sopenharmony_ci{ 162bf215546Sopenharmony_ci /* s limited to [min,max] */ 163bf215546Sopenharmony_ci /* i limited to [0, size-1] */ 164bf215546Sopenharmony_ci const float min = 0.5F; 165bf215546Sopenharmony_ci const float max = (float)size - 0.5F; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci s *= size; 168bf215546Sopenharmony_ci s += offset; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci if (s < min) 171bf215546Sopenharmony_ci *icoord = 0; 172bf215546Sopenharmony_ci else if (s > max) 173bf215546Sopenharmony_ci *icoord = size - 1; 174bf215546Sopenharmony_ci else 175bf215546Sopenharmony_ci *icoord = util_ifloor(s); 176bf215546Sopenharmony_ci} 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_cistatic void 180bf215546Sopenharmony_ciwrap_nearest_clamp_to_border(float s, unsigned size, int offset, int *icoord) 181bf215546Sopenharmony_ci{ 182bf215546Sopenharmony_ci /* s limited to [min,max] */ 183bf215546Sopenharmony_ci /* i limited to [-1, size] */ 184bf215546Sopenharmony_ci const float min = -0.5F; 185bf215546Sopenharmony_ci const float max = size + 0.5F; 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci s *= size; 188bf215546Sopenharmony_ci s += offset; 189bf215546Sopenharmony_ci if (s <= min) 190bf215546Sopenharmony_ci *icoord = -1; 191bf215546Sopenharmony_ci else if (s >= max) 192bf215546Sopenharmony_ci *icoord = size; 193bf215546Sopenharmony_ci else 194bf215546Sopenharmony_ci *icoord = util_ifloor(s); 195bf215546Sopenharmony_ci} 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_cistatic void 198bf215546Sopenharmony_ciwrap_nearest_mirror_repeat(float s, unsigned size, int offset, int *icoord) 199bf215546Sopenharmony_ci{ 200bf215546Sopenharmony_ci const float min = 1.0F / (2.0F * size); 201bf215546Sopenharmony_ci const float max = 1.0F - min; 202bf215546Sopenharmony_ci int flr; 203bf215546Sopenharmony_ci float u; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci s += (float)offset / size; 206bf215546Sopenharmony_ci flr = util_ifloor(s); 207bf215546Sopenharmony_ci u = frac(s); 208bf215546Sopenharmony_ci if (flr & 1) 209bf215546Sopenharmony_ci u = 1.0F - u; 210bf215546Sopenharmony_ci if (u < min) 211bf215546Sopenharmony_ci *icoord = 0; 212bf215546Sopenharmony_ci else if (u > max) 213bf215546Sopenharmony_ci *icoord = size - 1; 214bf215546Sopenharmony_ci else 215bf215546Sopenharmony_ci *icoord = util_ifloor(u * size); 216bf215546Sopenharmony_ci} 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_cistatic void 220bf215546Sopenharmony_ciwrap_nearest_mirror_clamp(float s, unsigned size, int offset, int *icoord) 221bf215546Sopenharmony_ci{ 222bf215546Sopenharmony_ci /* s limited to [0,1] */ 223bf215546Sopenharmony_ci /* i limited to [0,size-1] */ 224bf215546Sopenharmony_ci const float u = fabsf(s * size + offset); 225bf215546Sopenharmony_ci if (u <= 0.0F) 226bf215546Sopenharmony_ci *icoord = 0; 227bf215546Sopenharmony_ci else if (u >= size) 228bf215546Sopenharmony_ci *icoord = size - 1; 229bf215546Sopenharmony_ci else 230bf215546Sopenharmony_ci *icoord = util_ifloor(u); 231bf215546Sopenharmony_ci} 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_cistatic void 235bf215546Sopenharmony_ciwrap_nearest_mirror_clamp_to_edge(float s, unsigned size, int offset, int *icoord) 236bf215546Sopenharmony_ci{ 237bf215546Sopenharmony_ci /* s limited to [min,max] */ 238bf215546Sopenharmony_ci /* i limited to [0, size-1] */ 239bf215546Sopenharmony_ci const float min = 0.5F; 240bf215546Sopenharmony_ci const float max = (float)size - 0.5F; 241bf215546Sopenharmony_ci const float u = fabsf(s * size + offset); 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci if (u < min) 244bf215546Sopenharmony_ci *icoord = 0; 245bf215546Sopenharmony_ci else if (u > max) 246bf215546Sopenharmony_ci *icoord = size - 1; 247bf215546Sopenharmony_ci else 248bf215546Sopenharmony_ci *icoord = util_ifloor(u); 249bf215546Sopenharmony_ci} 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_cistatic void 253bf215546Sopenharmony_ciwrap_nearest_mirror_clamp_to_border(float s, unsigned size, int offset, int *icoord) 254bf215546Sopenharmony_ci{ 255bf215546Sopenharmony_ci /* u limited to [-0.5, size-0.5] */ 256bf215546Sopenharmony_ci const float min = -0.5F; 257bf215546Sopenharmony_ci const float max = (float)size + 0.5F; 258bf215546Sopenharmony_ci const float u = fabsf(s * size + offset); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci if (u < min) 261bf215546Sopenharmony_ci *icoord = -1; 262bf215546Sopenharmony_ci else if (u > max) 263bf215546Sopenharmony_ci *icoord = size; 264bf215546Sopenharmony_ci else 265bf215546Sopenharmony_ci *icoord = util_ifloor(u); 266bf215546Sopenharmony_ci} 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci/** 270bf215546Sopenharmony_ci * Used to compute texel locations for linear sampling 271bf215546Sopenharmony_ci * \param wrapMode PIPE_TEX_WRAP_x 272bf215546Sopenharmony_ci * \param s the texcoord 273bf215546Sopenharmony_ci * \param size the texture image size 274bf215546Sopenharmony_ci * \param icoord0 returns first texture index 275bf215546Sopenharmony_ci * \param icoord1 returns second texture index (usually icoord0 + 1) 276bf215546Sopenharmony_ci * \param w returns blend factor/weight between texture indices 277bf215546Sopenharmony_ci * \param icoord returns the computed integer texture coord 278bf215546Sopenharmony_ci */ 279bf215546Sopenharmony_cistatic void 280bf215546Sopenharmony_ciwrap_linear_repeat(float s, unsigned size, int offset, 281bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 282bf215546Sopenharmony_ci{ 283bf215546Sopenharmony_ci const float u = s * size - 0.5F; 284bf215546Sopenharmony_ci *icoord0 = repeat(util_ifloor(u) + offset, size); 285bf215546Sopenharmony_ci *icoord1 = repeat(*icoord0 + 1, size); 286bf215546Sopenharmony_ci *w = frac(u); 287bf215546Sopenharmony_ci} 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_cistatic void 291bf215546Sopenharmony_ciwrap_linear_clamp(float s, unsigned size, int offset, 292bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 293bf215546Sopenharmony_ci{ 294bf215546Sopenharmony_ci const float u = CLAMP(s * size + offset, 0.0F, (float)size) - 0.5f; 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 297bf215546Sopenharmony_ci *icoord1 = *icoord0 + 1; 298bf215546Sopenharmony_ci *w = frac(u); 299bf215546Sopenharmony_ci} 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_cistatic void 303bf215546Sopenharmony_ciwrap_linear_clamp_to_edge(float s, unsigned size, int offset, 304bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 305bf215546Sopenharmony_ci{ 306bf215546Sopenharmony_ci const float u = CLAMP(s * size + offset, 0.0F, (float)size) - 0.5f; 307bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 308bf215546Sopenharmony_ci *icoord1 = *icoord0 + 1; 309bf215546Sopenharmony_ci if (*icoord0 < 0) 310bf215546Sopenharmony_ci *icoord0 = 0; 311bf215546Sopenharmony_ci if (*icoord1 >= (int) size) 312bf215546Sopenharmony_ci *icoord1 = size - 1; 313bf215546Sopenharmony_ci *w = frac(u); 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_cistatic void 318bf215546Sopenharmony_ciwrap_linear_clamp_to_border(float s, unsigned size, int offset, 319bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 320bf215546Sopenharmony_ci{ 321bf215546Sopenharmony_ci const float min = -1.0F; 322bf215546Sopenharmony_ci const float max = (float)size + 0.5F; 323bf215546Sopenharmony_ci const float u = CLAMP(s * size + offset, min, max) - 0.5f; 324bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 325bf215546Sopenharmony_ci *icoord1 = *icoord0 + 1; 326bf215546Sopenharmony_ci *w = frac(u); 327bf215546Sopenharmony_ci} 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_cistatic void 331bf215546Sopenharmony_ciwrap_linear_mirror_repeat(float s, unsigned size, int offset, 332bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 333bf215546Sopenharmony_ci{ 334bf215546Sopenharmony_ci int flr; 335bf215546Sopenharmony_ci float u; 336bf215546Sopenharmony_ci bool no_mirror; 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci s += (float)offset / size; 339bf215546Sopenharmony_ci flr = util_ifloor(s); 340bf215546Sopenharmony_ci no_mirror = !(flr & 1); 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci u = frac(s); 343bf215546Sopenharmony_ci if (no_mirror) { 344bf215546Sopenharmony_ci u = u * size - 0.5F; 345bf215546Sopenharmony_ci } else { 346bf215546Sopenharmony_ci u = 1.0F - u; 347bf215546Sopenharmony_ci u = u * size + 0.5F; 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 351bf215546Sopenharmony_ci *icoord1 = (no_mirror) ? *icoord0 + 1 : *icoord0 - 1; 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci if (*icoord0 < 0) 354bf215546Sopenharmony_ci *icoord0 = 1 + *icoord0; 355bf215546Sopenharmony_ci if (*icoord0 >= (int) size) 356bf215546Sopenharmony_ci *icoord0 = size - 1; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci if (*icoord1 >= (int) size) 359bf215546Sopenharmony_ci *icoord1 = size - 1; 360bf215546Sopenharmony_ci if (*icoord1 < 0) 361bf215546Sopenharmony_ci *icoord1 = 1 + *icoord1; 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci *w = (no_mirror) ? frac(u) : frac(1.0f - u); 364bf215546Sopenharmony_ci} 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_cistatic void 368bf215546Sopenharmony_ciwrap_linear_mirror_clamp(float s, unsigned size, int offset, 369bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 370bf215546Sopenharmony_ci{ 371bf215546Sopenharmony_ci float u = fabsf(s * size + offset); 372bf215546Sopenharmony_ci if (u >= size) 373bf215546Sopenharmony_ci u = (float) size; 374bf215546Sopenharmony_ci u -= 0.5F; 375bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 376bf215546Sopenharmony_ci *icoord1 = *icoord0 + 1; 377bf215546Sopenharmony_ci *w = frac(u); 378bf215546Sopenharmony_ci} 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_cistatic void 382bf215546Sopenharmony_ciwrap_linear_mirror_clamp_to_edge(float s, unsigned size, int offset, 383bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 384bf215546Sopenharmony_ci{ 385bf215546Sopenharmony_ci float u = fabsf(s * size + offset); 386bf215546Sopenharmony_ci if (u >= size) 387bf215546Sopenharmony_ci u = (float) size; 388bf215546Sopenharmony_ci u -= 0.5F; 389bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 390bf215546Sopenharmony_ci *icoord1 = *icoord0 + 1; 391bf215546Sopenharmony_ci if (*icoord0 < 0) 392bf215546Sopenharmony_ci *icoord0 = 0; 393bf215546Sopenharmony_ci if (*icoord1 >= (int) size) 394bf215546Sopenharmony_ci *icoord1 = size - 1; 395bf215546Sopenharmony_ci *w = frac(u); 396bf215546Sopenharmony_ci} 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_cistatic void 400bf215546Sopenharmony_ciwrap_linear_mirror_clamp_to_border(float s, unsigned size, int offset, 401bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 402bf215546Sopenharmony_ci{ 403bf215546Sopenharmony_ci const float min = -0.5F; 404bf215546Sopenharmony_ci const float max = size + 0.5F; 405bf215546Sopenharmony_ci const float t = fabsf(s * size + offset); 406bf215546Sopenharmony_ci const float u = CLAMP(t, min, max) - 0.5F; 407bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 408bf215546Sopenharmony_ci *icoord1 = *icoord0 + 1; 409bf215546Sopenharmony_ci *w = frac(u); 410bf215546Sopenharmony_ci} 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci/** 414bf215546Sopenharmony_ci * PIPE_TEX_WRAP_CLAMP for nearest sampling, unnormalized coords. 415bf215546Sopenharmony_ci */ 416bf215546Sopenharmony_cistatic void 417bf215546Sopenharmony_ciwrap_nearest_unorm_clamp(float s, unsigned size, int offset, int *icoord) 418bf215546Sopenharmony_ci{ 419bf215546Sopenharmony_ci const int i = util_ifloor(s); 420bf215546Sopenharmony_ci *icoord = CLAMP(i + offset, 0, (int) size-1); 421bf215546Sopenharmony_ci} 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci/** 425bf215546Sopenharmony_ci * PIPE_TEX_WRAP_CLAMP_TO_BORDER for nearest sampling, unnormalized coords. 426bf215546Sopenharmony_ci */ 427bf215546Sopenharmony_cistatic void 428bf215546Sopenharmony_ciwrap_nearest_unorm_clamp_to_border(float s, unsigned size, int offset, int *icoord) 429bf215546Sopenharmony_ci{ 430bf215546Sopenharmony_ci *icoord = util_ifloor( CLAMP(s + offset, -0.5F, (float) size + 0.5F) ); 431bf215546Sopenharmony_ci} 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci/** 435bf215546Sopenharmony_ci * PIPE_TEX_WRAP_CLAMP_TO_EDGE for nearest sampling, unnormalized coords. 436bf215546Sopenharmony_ci */ 437bf215546Sopenharmony_cistatic void 438bf215546Sopenharmony_ciwrap_nearest_unorm_clamp_to_edge(float s, unsigned size, int offset, int *icoord) 439bf215546Sopenharmony_ci{ 440bf215546Sopenharmony_ci *icoord = util_ifloor( CLAMP(s + offset, 0.5F, (float) size - 0.5F) ); 441bf215546Sopenharmony_ci} 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci/** 445bf215546Sopenharmony_ci * PIPE_TEX_WRAP_CLAMP for linear sampling, unnormalized coords. 446bf215546Sopenharmony_ci */ 447bf215546Sopenharmony_cistatic void 448bf215546Sopenharmony_ciwrap_linear_unorm_clamp(float s, unsigned size, int offset, 449bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 450bf215546Sopenharmony_ci{ 451bf215546Sopenharmony_ci /* Not exactly what the spec says, but it matches NVIDIA output */ 452bf215546Sopenharmony_ci const float u = CLAMP(s + offset - 0.5F, 0.0f, (float) size - 1.0f); 453bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 454bf215546Sopenharmony_ci *icoord1 = *icoord0 + 1; 455bf215546Sopenharmony_ci *w = frac(u); 456bf215546Sopenharmony_ci} 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci/** 460bf215546Sopenharmony_ci * PIPE_TEX_WRAP_CLAMP_TO_BORDER for linear sampling, unnormalized coords. 461bf215546Sopenharmony_ci */ 462bf215546Sopenharmony_cistatic void 463bf215546Sopenharmony_ciwrap_linear_unorm_clamp_to_border(float s, unsigned size, int offset, 464bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 465bf215546Sopenharmony_ci{ 466bf215546Sopenharmony_ci const float u = CLAMP(s + offset, -0.5F, (float) size + 0.5F) - 0.5F; 467bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 468bf215546Sopenharmony_ci *icoord1 = *icoord0 + 1; 469bf215546Sopenharmony_ci if (*icoord1 > (int) size - 1) 470bf215546Sopenharmony_ci *icoord1 = size - 1; 471bf215546Sopenharmony_ci *w = frac(u); 472bf215546Sopenharmony_ci} 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci/** 476bf215546Sopenharmony_ci * PIPE_TEX_WRAP_CLAMP_TO_EDGE for linear sampling, unnormalized coords. 477bf215546Sopenharmony_ci */ 478bf215546Sopenharmony_cistatic void 479bf215546Sopenharmony_ciwrap_linear_unorm_clamp_to_edge(float s, unsigned size, int offset, 480bf215546Sopenharmony_ci int *icoord0, int *icoord1, float *w) 481bf215546Sopenharmony_ci{ 482bf215546Sopenharmony_ci const float u = CLAMP(s + offset, +0.5F, (float) size - 0.5F) - 0.5F; 483bf215546Sopenharmony_ci *icoord0 = util_ifloor(u); 484bf215546Sopenharmony_ci *icoord1 = *icoord0 + 1; 485bf215546Sopenharmony_ci if (*icoord1 > (int) size - 1) 486bf215546Sopenharmony_ci *icoord1 = size - 1; 487bf215546Sopenharmony_ci *w = frac(u); 488bf215546Sopenharmony_ci} 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci/** 492bf215546Sopenharmony_ci * Do coordinate to array index conversion. For array textures. 493bf215546Sopenharmony_ci */ 494bf215546Sopenharmony_cistatic inline int 495bf215546Sopenharmony_cicoord_to_layer(float coord, unsigned first_layer, unsigned last_layer) 496bf215546Sopenharmony_ci{ 497bf215546Sopenharmony_ci const int c = util_ifloor(coord + 0.5F); 498bf215546Sopenharmony_ci return CLAMP(c, (int)first_layer, (int)last_layer); 499bf215546Sopenharmony_ci} 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_cistatic void 502bf215546Sopenharmony_cicompute_gradient_1d(const float s[TGSI_QUAD_SIZE], 503bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 504bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 505bf215546Sopenharmony_ci float derivs[3][2][TGSI_QUAD_SIZE]) 506bf215546Sopenharmony_ci{ 507bf215546Sopenharmony_ci memset(derivs, 0, 6 * TGSI_QUAD_SIZE * sizeof(float)); 508bf215546Sopenharmony_ci derivs[0][0][0] = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]; 509bf215546Sopenharmony_ci derivs[0][1][0] = s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]; 510bf215546Sopenharmony_ci} 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_cistatic float 513bf215546Sopenharmony_cicompute_lambda_1d_explicit_gradients(const struct sp_sampler_view *sview, 514bf215546Sopenharmony_ci const float derivs[3][2][TGSI_QUAD_SIZE], 515bf215546Sopenharmony_ci uint quad) 516bf215546Sopenharmony_ci{ 517bf215546Sopenharmony_ci const struct pipe_resource *texture = sview->base.texture; 518bf215546Sopenharmony_ci const float dsdx = fabsf(derivs[0][0][quad]); 519bf215546Sopenharmony_ci const float dsdy = fabsf(derivs[0][1][quad]); 520bf215546Sopenharmony_ci const float rho = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level); 521bf215546Sopenharmony_ci return util_fast_log2(rho); 522bf215546Sopenharmony_ci} 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci/** 526bf215546Sopenharmony_ci * Examine the quad's texture coordinates to compute the partial 527bf215546Sopenharmony_ci * derivatives w.r.t X and Y, then compute lambda (level of detail). 528bf215546Sopenharmony_ci */ 529bf215546Sopenharmony_cistatic float 530bf215546Sopenharmony_cicompute_lambda_1d(const struct sp_sampler_view *sview, 531bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 532bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 533bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE]) 534bf215546Sopenharmony_ci{ 535bf215546Sopenharmony_ci float derivs[3][2][TGSI_QUAD_SIZE]; 536bf215546Sopenharmony_ci compute_gradient_1d(s, t, p, derivs); 537bf215546Sopenharmony_ci return compute_lambda_1d_explicit_gradients(sview, derivs, 0); 538bf215546Sopenharmony_ci} 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_cistatic void 542bf215546Sopenharmony_cicompute_gradient_2d(const float s[TGSI_QUAD_SIZE], 543bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 544bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 545bf215546Sopenharmony_ci float derivs[3][2][TGSI_QUAD_SIZE]) 546bf215546Sopenharmony_ci{ 547bf215546Sopenharmony_ci memset(derivs, 0, 6 * TGSI_QUAD_SIZE * sizeof(float)); 548bf215546Sopenharmony_ci derivs[0][0][0] = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]; 549bf215546Sopenharmony_ci derivs[0][1][0] = s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]; 550bf215546Sopenharmony_ci derivs[1][0][0] = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]; 551bf215546Sopenharmony_ci derivs[1][1][0] = t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]; 552bf215546Sopenharmony_ci} 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_cistatic float 555bf215546Sopenharmony_cicompute_lambda_2d_explicit_gradients(const struct sp_sampler_view *sview, 556bf215546Sopenharmony_ci const float derivs[3][2][TGSI_QUAD_SIZE], 557bf215546Sopenharmony_ci uint quad) 558bf215546Sopenharmony_ci{ 559bf215546Sopenharmony_ci const struct pipe_resource *texture = sview->base.texture; 560bf215546Sopenharmony_ci const float dsdx = fabsf(derivs[0][0][quad]); 561bf215546Sopenharmony_ci const float dsdy = fabsf(derivs[0][1][quad]); 562bf215546Sopenharmony_ci const float dtdx = fabsf(derivs[1][0][quad]); 563bf215546Sopenharmony_ci const float dtdy = fabsf(derivs[1][1][quad]); 564bf215546Sopenharmony_ci const float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level); 565bf215546Sopenharmony_ci const float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level); 566bf215546Sopenharmony_ci const float rho = MAX2(maxx, maxy); 567bf215546Sopenharmony_ci return util_fast_log2(rho); 568bf215546Sopenharmony_ci} 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_cistatic float 572bf215546Sopenharmony_cicompute_lambda_2d(const struct sp_sampler_view *sview, 573bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 574bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 575bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE]) 576bf215546Sopenharmony_ci{ 577bf215546Sopenharmony_ci float derivs[3][2][TGSI_QUAD_SIZE]; 578bf215546Sopenharmony_ci compute_gradient_2d(s, t, p, derivs); 579bf215546Sopenharmony_ci return compute_lambda_2d_explicit_gradients(sview, derivs, 0); 580bf215546Sopenharmony_ci} 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_cistatic void 584bf215546Sopenharmony_cicompute_gradient_3d(const float s[TGSI_QUAD_SIZE], 585bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 586bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 587bf215546Sopenharmony_ci float derivs[3][2][TGSI_QUAD_SIZE]) 588bf215546Sopenharmony_ci{ 589bf215546Sopenharmony_ci memset(derivs, 0, 6 * TGSI_QUAD_SIZE * sizeof(float)); 590bf215546Sopenharmony_ci derivs[0][0][0] = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); 591bf215546Sopenharmony_ci derivs[0][1][0] = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); 592bf215546Sopenharmony_ci derivs[1][0][0] = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); 593bf215546Sopenharmony_ci derivs[1][1][0] = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]); 594bf215546Sopenharmony_ci derivs[2][0][0] = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]); 595bf215546Sopenharmony_ci derivs[2][1][0] = fabsf(p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]); 596bf215546Sopenharmony_ci} 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_cistatic float 599bf215546Sopenharmony_cicompute_lambda_3d_explicit_gradients(const struct sp_sampler_view *sview, 600bf215546Sopenharmony_ci const float derivs[3][2][TGSI_QUAD_SIZE], 601bf215546Sopenharmony_ci uint quad) 602bf215546Sopenharmony_ci{ 603bf215546Sopenharmony_ci const struct pipe_resource *texture = sview->base.texture; 604bf215546Sopenharmony_ci const float dsdx = fabsf(derivs[0][0][quad]); 605bf215546Sopenharmony_ci const float dsdy = fabsf(derivs[0][1][quad]); 606bf215546Sopenharmony_ci const float dtdx = fabsf(derivs[1][0][quad]); 607bf215546Sopenharmony_ci const float dtdy = fabsf(derivs[1][1][quad]); 608bf215546Sopenharmony_ci const float dpdx = fabsf(derivs[2][0][quad]); 609bf215546Sopenharmony_ci const float dpdy = fabsf(derivs[2][1][quad]); 610bf215546Sopenharmony_ci const float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level); 611bf215546Sopenharmony_ci const float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level); 612bf215546Sopenharmony_ci const float maxz = MAX2(dpdx, dpdy) * u_minify(texture->depth0, sview->base.u.tex.first_level); 613bf215546Sopenharmony_ci const float rho = MAX3(maxx, maxy, maxz); 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci return util_fast_log2(rho); 616bf215546Sopenharmony_ci} 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_cistatic float 620bf215546Sopenharmony_cicompute_lambda_3d(const struct sp_sampler_view *sview, 621bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 622bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 623bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE]) 624bf215546Sopenharmony_ci{ 625bf215546Sopenharmony_ci float derivs[3][2][TGSI_QUAD_SIZE]; 626bf215546Sopenharmony_ci compute_gradient_3d(s, t, p, derivs); 627bf215546Sopenharmony_ci return compute_lambda_3d_explicit_gradients(sview, derivs, 0); 628bf215546Sopenharmony_ci} 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_cistatic float 632bf215546Sopenharmony_cicompute_lambda_cube_explicit_gradients(const struct sp_sampler_view *sview, 633bf215546Sopenharmony_ci const float derivs[3][2][TGSI_QUAD_SIZE], 634bf215546Sopenharmony_ci uint quad) 635bf215546Sopenharmony_ci{ 636bf215546Sopenharmony_ci const struct pipe_resource *texture = sview->base.texture; 637bf215546Sopenharmony_ci const float dsdx = fabsf(derivs[0][0][quad]); 638bf215546Sopenharmony_ci const float dsdy = fabsf(derivs[0][1][quad]); 639bf215546Sopenharmony_ci const float dtdx = fabsf(derivs[1][0][quad]); 640bf215546Sopenharmony_ci const float dtdy = fabsf(derivs[1][1][quad]); 641bf215546Sopenharmony_ci const float dpdx = fabsf(derivs[2][0][quad]); 642bf215546Sopenharmony_ci const float dpdy = fabsf(derivs[2][1][quad]); 643bf215546Sopenharmony_ci const float maxx = MAX2(dsdx, dsdy); 644bf215546Sopenharmony_ci const float maxy = MAX2(dtdx, dtdy); 645bf215546Sopenharmony_ci const float maxz = MAX2(dpdx, dpdy); 646bf215546Sopenharmony_ci const float rho = MAX3(maxx, maxy, maxz) * u_minify(texture->width0, sview->base.u.tex.first_level) / 2.0f; 647bf215546Sopenharmony_ci 648bf215546Sopenharmony_ci return util_fast_log2(rho); 649bf215546Sopenharmony_ci} 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_cistatic float 652bf215546Sopenharmony_cicompute_lambda_cube(const struct sp_sampler_view *sview, 653bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 654bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 655bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE]) 656bf215546Sopenharmony_ci{ 657bf215546Sopenharmony_ci float derivs[3][2][TGSI_QUAD_SIZE]; 658bf215546Sopenharmony_ci compute_gradient_3d(s, t, p, derivs); 659bf215546Sopenharmony_ci return compute_lambda_cube_explicit_gradients(sview, derivs, 0); 660bf215546Sopenharmony_ci} 661bf215546Sopenharmony_ci 662bf215546Sopenharmony_ci/** 663bf215546Sopenharmony_ci * Compute lambda for a vertex texture sampler. 664bf215546Sopenharmony_ci * Since there aren't derivatives to use, just return 0. 665bf215546Sopenharmony_ci */ 666bf215546Sopenharmony_cistatic float 667bf215546Sopenharmony_cicompute_lambda_vert(const struct sp_sampler_view *sview, 668bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 669bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 670bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE]) 671bf215546Sopenharmony_ci{ 672bf215546Sopenharmony_ci return 0.0f; 673bf215546Sopenharmony_ci} 674bf215546Sopenharmony_ci 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_cicompute_lambda_from_grad_func 677bf215546Sopenharmony_cisoftpipe_get_lambda_from_grad_func(const struct pipe_sampler_view *view, 678bf215546Sopenharmony_ci enum pipe_shader_type shader) 679bf215546Sopenharmony_ci{ 680bf215546Sopenharmony_ci switch (view->target) { 681bf215546Sopenharmony_ci case PIPE_BUFFER: 682bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 683bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 684bf215546Sopenharmony_ci return compute_lambda_1d_explicit_gradients; 685bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 686bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 687bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 688bf215546Sopenharmony_ci return compute_lambda_2d_explicit_gradients; 689bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 690bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 691bf215546Sopenharmony_ci return compute_lambda_cube_explicit_gradients; 692bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 693bf215546Sopenharmony_ci return compute_lambda_3d_explicit_gradients; 694bf215546Sopenharmony_ci default: 695bf215546Sopenharmony_ci assert(0); 696bf215546Sopenharmony_ci return compute_lambda_1d_explicit_gradients; 697bf215546Sopenharmony_ci } 698bf215546Sopenharmony_ci} 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci/** 702bf215546Sopenharmony_ci * Get a texel from a texture, using the texture tile cache. 703bf215546Sopenharmony_ci * 704bf215546Sopenharmony_ci * \param addr the template tex address containing cube, z, face info. 705bf215546Sopenharmony_ci * \param x the x coord of texel within 2D image 706bf215546Sopenharmony_ci * \param y the y coord of texel within 2D image 707bf215546Sopenharmony_ci * \param rgba the quad to put the texel/color into 708bf215546Sopenharmony_ci * 709bf215546Sopenharmony_ci * XXX maybe move this into sp_tex_tile_cache.c and merge with the 710bf215546Sopenharmony_ci * sp_get_cached_tile_tex() function. 711bf215546Sopenharmony_ci */ 712bf215546Sopenharmony_ci 713bf215546Sopenharmony_ci 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_cistatic inline const float * 716bf215546Sopenharmony_ciget_texel_buffer_no_border(const struct sp_sampler_view *sp_sview, 717bf215546Sopenharmony_ci union tex_tile_address addr, int x, unsigned elmsize) 718bf215546Sopenharmony_ci{ 719bf215546Sopenharmony_ci const struct softpipe_tex_cached_tile *tile; 720bf215546Sopenharmony_ci addr.bits.x = x * elmsize / TEX_TILE_SIZE; 721bf215546Sopenharmony_ci assert(x * elmsize / TEX_TILE_SIZE == addr.bits.x); 722bf215546Sopenharmony_ci 723bf215546Sopenharmony_ci x %= TEX_TILE_SIZE / elmsize; 724bf215546Sopenharmony_ci 725bf215546Sopenharmony_ci tile = sp_get_cached_tile_tex(sp_sview->cache, addr); 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci return &tile->data.color[0][x][0]; 728bf215546Sopenharmony_ci} 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_cistatic inline const float * 732bf215546Sopenharmony_ciget_texel_2d_no_border(const struct sp_sampler_view *sp_sview, 733bf215546Sopenharmony_ci union tex_tile_address addr, int x, int y) 734bf215546Sopenharmony_ci{ 735bf215546Sopenharmony_ci const struct softpipe_tex_cached_tile *tile; 736bf215546Sopenharmony_ci addr.bits.x = x / TEX_TILE_SIZE; 737bf215546Sopenharmony_ci addr.bits.y = y / TEX_TILE_SIZE; 738bf215546Sopenharmony_ci y %= TEX_TILE_SIZE; 739bf215546Sopenharmony_ci x %= TEX_TILE_SIZE; 740bf215546Sopenharmony_ci 741bf215546Sopenharmony_ci tile = sp_get_cached_tile_tex(sp_sview->cache, addr); 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci return &tile->data.color[y][x][0]; 744bf215546Sopenharmony_ci} 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_cistatic inline const float * 748bf215546Sopenharmony_ciget_texel_2d(const struct sp_sampler_view *sp_sview, 749bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 750bf215546Sopenharmony_ci union tex_tile_address addr, int x, int y) 751bf215546Sopenharmony_ci{ 752bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 753bf215546Sopenharmony_ci const unsigned level = addr.bits.level; 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci if (x < 0 || x >= (int) u_minify(texture->width0, level) || 756bf215546Sopenharmony_ci y < 0 || y >= (int) u_minify(texture->height0, level)) { 757bf215546Sopenharmony_ci return sp_sview->border_color.f; 758bf215546Sopenharmony_ci } 759bf215546Sopenharmony_ci else { 760bf215546Sopenharmony_ci return get_texel_2d_no_border( sp_sview, addr, x, y ); 761bf215546Sopenharmony_ci } 762bf215546Sopenharmony_ci} 763bf215546Sopenharmony_ci 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci/* 766bf215546Sopenharmony_ci * Here's the complete logic (HOLY CRAP) for finding next face and doing the 767bf215546Sopenharmony_ci * corresponding coord wrapping, implemented by get_next_face, 768bf215546Sopenharmony_ci * get_next_xcoord, get_next_ycoord. 769bf215546Sopenharmony_ci * Read like that (first line): 770bf215546Sopenharmony_ci * If face is +x and s coord is below zero, then 771bf215546Sopenharmony_ci * new face is +z, new s is max , new t is old t 772bf215546Sopenharmony_ci * (max is always cube size - 1). 773bf215546Sopenharmony_ci * 774bf215546Sopenharmony_ci * +x s- -> +z: s = max, t = t 775bf215546Sopenharmony_ci * +x s+ -> -z: s = 0, t = t 776bf215546Sopenharmony_ci * +x t- -> +y: s = max, t = max-s 777bf215546Sopenharmony_ci * +x t+ -> -y: s = max, t = s 778bf215546Sopenharmony_ci * 779bf215546Sopenharmony_ci * -x s- -> -z: s = max, t = t 780bf215546Sopenharmony_ci * -x s+ -> +z: s = 0, t = t 781bf215546Sopenharmony_ci * -x t- -> +y: s = 0, t = s 782bf215546Sopenharmony_ci * -x t+ -> -y: s = 0, t = max-s 783bf215546Sopenharmony_ci * 784bf215546Sopenharmony_ci * +y s- -> -x: s = t, t = 0 785bf215546Sopenharmony_ci * +y s+ -> +x: s = max-t, t = 0 786bf215546Sopenharmony_ci * +y t- -> -z: s = max-s, t = 0 787bf215546Sopenharmony_ci * +y t+ -> +z: s = s, t = 0 788bf215546Sopenharmony_ci * 789bf215546Sopenharmony_ci * -y s- -> -x: s = max-t, t = max 790bf215546Sopenharmony_ci * -y s+ -> +x: s = t, t = max 791bf215546Sopenharmony_ci * -y t- -> +z: s = s, t = max 792bf215546Sopenharmony_ci * -y t+ -> -z: s = max-s, t = max 793bf215546Sopenharmony_ci 794bf215546Sopenharmony_ci * +z s- -> -x: s = max, t = t 795bf215546Sopenharmony_ci * +z s+ -> +x: s = 0, t = t 796bf215546Sopenharmony_ci * +z t- -> +y: s = s, t = max 797bf215546Sopenharmony_ci * +z t+ -> -y: s = s, t = 0 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci * -z s- -> +x: s = max, t = t 800bf215546Sopenharmony_ci * -z s+ -> -x: s = 0, t = t 801bf215546Sopenharmony_ci * -z t- -> +y: s = max-s, t = 0 802bf215546Sopenharmony_ci * -z t+ -> -y: s = max-s, t = max 803bf215546Sopenharmony_ci */ 804bf215546Sopenharmony_ci 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ci/* 807bf215546Sopenharmony_ci * seamless cubemap neighbour array. 808bf215546Sopenharmony_ci * this array is used to find the adjacent face in each of 4 directions, 809bf215546Sopenharmony_ci * left, right, up, down. (or -x, +x, -y, +y). 810bf215546Sopenharmony_ci */ 811bf215546Sopenharmony_cistatic const unsigned face_array[PIPE_TEX_FACE_MAX][4] = { 812bf215546Sopenharmony_ci /* pos X first then neg X is Z different, Y the same */ 813bf215546Sopenharmony_ci /* PIPE_TEX_FACE_POS_X,*/ 814bf215546Sopenharmony_ci { PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z, 815bf215546Sopenharmony_ci PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y }, 816bf215546Sopenharmony_ci /* PIPE_TEX_FACE_NEG_X */ 817bf215546Sopenharmony_ci { PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z, 818bf215546Sopenharmony_ci PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y }, 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci /* pos Y first then neg Y is X different, X the same */ 821bf215546Sopenharmony_ci /* PIPE_TEX_FACE_POS_Y */ 822bf215546Sopenharmony_ci { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X, 823bf215546Sopenharmony_ci PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z }, 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci /* PIPE_TEX_FACE_NEG_Y */ 826bf215546Sopenharmony_ci { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X, 827bf215546Sopenharmony_ci PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z }, 828bf215546Sopenharmony_ci 829bf215546Sopenharmony_ci /* pos Z first then neg Y is X different, X the same */ 830bf215546Sopenharmony_ci /* PIPE_TEX_FACE_POS_Z */ 831bf215546Sopenharmony_ci { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X, 832bf215546Sopenharmony_ci PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y }, 833bf215546Sopenharmony_ci 834bf215546Sopenharmony_ci /* PIPE_TEX_FACE_NEG_Z */ 835bf215546Sopenharmony_ci { PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_NEG_X, 836bf215546Sopenharmony_ci PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y } 837bf215546Sopenharmony_ci}; 838bf215546Sopenharmony_ci 839bf215546Sopenharmony_cistatic inline unsigned 840bf215546Sopenharmony_ciget_next_face(unsigned face, int idx) 841bf215546Sopenharmony_ci{ 842bf215546Sopenharmony_ci return face_array[face][idx]; 843bf215546Sopenharmony_ci} 844bf215546Sopenharmony_ci 845bf215546Sopenharmony_ci/* 846bf215546Sopenharmony_ci * return a new xcoord based on old face, old coords, cube size 847bf215546Sopenharmony_ci * and fall_off_index (0 for x-, 1 for x+, 2 for y-, 3 for y+) 848bf215546Sopenharmony_ci */ 849bf215546Sopenharmony_cistatic inline int 850bf215546Sopenharmony_ciget_next_xcoord(unsigned face, unsigned fall_off_index, int max, int xc, int yc) 851bf215546Sopenharmony_ci{ 852bf215546Sopenharmony_ci if ((face == 0 && fall_off_index != 1) || 853bf215546Sopenharmony_ci (face == 1 && fall_off_index == 0) || 854bf215546Sopenharmony_ci (face == 4 && fall_off_index == 0) || 855bf215546Sopenharmony_ci (face == 5 && fall_off_index == 0)) { 856bf215546Sopenharmony_ci return max; 857bf215546Sopenharmony_ci } 858bf215546Sopenharmony_ci if ((face == 1 && fall_off_index != 0) || 859bf215546Sopenharmony_ci (face == 0 && fall_off_index == 1) || 860bf215546Sopenharmony_ci (face == 4 && fall_off_index == 1) || 861bf215546Sopenharmony_ci (face == 5 && fall_off_index == 1)) { 862bf215546Sopenharmony_ci return 0; 863bf215546Sopenharmony_ci } 864bf215546Sopenharmony_ci if ((face == 4 && fall_off_index >= 2) || 865bf215546Sopenharmony_ci (face == 2 && fall_off_index == 3) || 866bf215546Sopenharmony_ci (face == 3 && fall_off_index == 2)) { 867bf215546Sopenharmony_ci return xc; 868bf215546Sopenharmony_ci } 869bf215546Sopenharmony_ci if ((face == 5 && fall_off_index >= 2) || 870bf215546Sopenharmony_ci (face == 2 && fall_off_index == 2) || 871bf215546Sopenharmony_ci (face == 3 && fall_off_index == 3)) { 872bf215546Sopenharmony_ci return max - xc; 873bf215546Sopenharmony_ci } 874bf215546Sopenharmony_ci if ((face == 2 && fall_off_index == 0) || 875bf215546Sopenharmony_ci (face == 3 && fall_off_index == 1)) { 876bf215546Sopenharmony_ci return yc; 877bf215546Sopenharmony_ci } 878bf215546Sopenharmony_ci /* (face == 2 && fall_off_index == 1) || 879bf215546Sopenharmony_ci (face == 3 && fall_off_index == 0)) */ 880bf215546Sopenharmony_ci return max - yc; 881bf215546Sopenharmony_ci} 882bf215546Sopenharmony_ci 883bf215546Sopenharmony_ci/* 884bf215546Sopenharmony_ci * return a new ycoord based on old face, old coords, cube size 885bf215546Sopenharmony_ci * and fall_off_index (0 for x-, 1 for x+, 2 for y-, 3 for y+) 886bf215546Sopenharmony_ci */ 887bf215546Sopenharmony_cistatic inline int 888bf215546Sopenharmony_ciget_next_ycoord(unsigned face, unsigned fall_off_index, int max, int xc, int yc) 889bf215546Sopenharmony_ci{ 890bf215546Sopenharmony_ci if ((fall_off_index <= 1) && (face <= 1 || face >= 4)) { 891bf215546Sopenharmony_ci return yc; 892bf215546Sopenharmony_ci } 893bf215546Sopenharmony_ci if (face == 2 || 894bf215546Sopenharmony_ci (face == 4 && fall_off_index == 3) || 895bf215546Sopenharmony_ci (face == 5 && fall_off_index == 2)) { 896bf215546Sopenharmony_ci return 0; 897bf215546Sopenharmony_ci } 898bf215546Sopenharmony_ci if (face == 3 || 899bf215546Sopenharmony_ci (face == 4 && fall_off_index == 2) || 900bf215546Sopenharmony_ci (face == 5 && fall_off_index == 3)) { 901bf215546Sopenharmony_ci return max; 902bf215546Sopenharmony_ci } 903bf215546Sopenharmony_ci if ((face == 0 && fall_off_index == 3) || 904bf215546Sopenharmony_ci (face == 1 && fall_off_index == 2)) { 905bf215546Sopenharmony_ci return xc; 906bf215546Sopenharmony_ci } 907bf215546Sopenharmony_ci /* (face == 0 && fall_off_index == 2) || 908bf215546Sopenharmony_ci (face == 1 && fall_off_index == 3) */ 909bf215546Sopenharmony_ci return max - xc; 910bf215546Sopenharmony_ci} 911bf215546Sopenharmony_ci 912bf215546Sopenharmony_ci 913bf215546Sopenharmony_ci/* Gather a quad of adjacent texels within a tile: 914bf215546Sopenharmony_ci */ 915bf215546Sopenharmony_cistatic inline void 916bf215546Sopenharmony_ciget_texel_quad_2d_no_border_single_tile(const struct sp_sampler_view *sp_sview, 917bf215546Sopenharmony_ci union tex_tile_address addr, 918bf215546Sopenharmony_ci unsigned x, unsigned y, 919bf215546Sopenharmony_ci const float *out[4]) 920bf215546Sopenharmony_ci{ 921bf215546Sopenharmony_ci const struct softpipe_tex_cached_tile *tile; 922bf215546Sopenharmony_ci 923bf215546Sopenharmony_ci addr.bits.x = x / TEX_TILE_SIZE; 924bf215546Sopenharmony_ci addr.bits.y = y / TEX_TILE_SIZE; 925bf215546Sopenharmony_ci y %= TEX_TILE_SIZE; 926bf215546Sopenharmony_ci x %= TEX_TILE_SIZE; 927bf215546Sopenharmony_ci 928bf215546Sopenharmony_ci tile = sp_get_cached_tile_tex(sp_sview->cache, addr); 929bf215546Sopenharmony_ci 930bf215546Sopenharmony_ci out[0] = &tile->data.color[y ][x ][0]; 931bf215546Sopenharmony_ci out[1] = &tile->data.color[y ][x+1][0]; 932bf215546Sopenharmony_ci out[2] = &tile->data.color[y+1][x ][0]; 933bf215546Sopenharmony_ci out[3] = &tile->data.color[y+1][x+1][0]; 934bf215546Sopenharmony_ci} 935bf215546Sopenharmony_ci 936bf215546Sopenharmony_ci 937bf215546Sopenharmony_ci/* Gather a quad of potentially non-adjacent texels: 938bf215546Sopenharmony_ci */ 939bf215546Sopenharmony_cistatic inline void 940bf215546Sopenharmony_ciget_texel_quad_2d_no_border(const struct sp_sampler_view *sp_sview, 941bf215546Sopenharmony_ci union tex_tile_address addr, 942bf215546Sopenharmony_ci int x0, int y0, 943bf215546Sopenharmony_ci int x1, int y1, 944bf215546Sopenharmony_ci const float *out[4]) 945bf215546Sopenharmony_ci{ 946bf215546Sopenharmony_ci out[0] = get_texel_2d_no_border( sp_sview, addr, x0, y0 ); 947bf215546Sopenharmony_ci out[1] = get_texel_2d_no_border( sp_sview, addr, x1, y0 ); 948bf215546Sopenharmony_ci out[2] = get_texel_2d_no_border( sp_sview, addr, x0, y1 ); 949bf215546Sopenharmony_ci out[3] = get_texel_2d_no_border( sp_sview, addr, x1, y1 ); 950bf215546Sopenharmony_ci} 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_ci/* 3d variants: 954bf215546Sopenharmony_ci */ 955bf215546Sopenharmony_cistatic inline const float * 956bf215546Sopenharmony_ciget_texel_3d_no_border(const struct sp_sampler_view *sp_sview, 957bf215546Sopenharmony_ci union tex_tile_address addr, int x, int y, int z) 958bf215546Sopenharmony_ci{ 959bf215546Sopenharmony_ci const struct softpipe_tex_cached_tile *tile; 960bf215546Sopenharmony_ci 961bf215546Sopenharmony_ci addr.bits.x = x / TEX_TILE_SIZE; 962bf215546Sopenharmony_ci addr.bits.y = y / TEX_TILE_SIZE; 963bf215546Sopenharmony_ci addr.bits.z = z; 964bf215546Sopenharmony_ci y %= TEX_TILE_SIZE; 965bf215546Sopenharmony_ci x %= TEX_TILE_SIZE; 966bf215546Sopenharmony_ci 967bf215546Sopenharmony_ci tile = sp_get_cached_tile_tex(sp_sview->cache, addr); 968bf215546Sopenharmony_ci 969bf215546Sopenharmony_ci return &tile->data.color[y][x][0]; 970bf215546Sopenharmony_ci} 971bf215546Sopenharmony_ci 972bf215546Sopenharmony_ci 973bf215546Sopenharmony_cistatic inline const float * 974bf215546Sopenharmony_ciget_texel_3d(const struct sp_sampler_view *sp_sview, 975bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 976bf215546Sopenharmony_ci union tex_tile_address addr, int x, int y, int z) 977bf215546Sopenharmony_ci{ 978bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 979bf215546Sopenharmony_ci const unsigned level = addr.bits.level; 980bf215546Sopenharmony_ci 981bf215546Sopenharmony_ci if (x < 0 || x >= (int) u_minify(texture->width0, level) || 982bf215546Sopenharmony_ci y < 0 || y >= (int) u_minify(texture->height0, level) || 983bf215546Sopenharmony_ci z < 0 || z >= (int) u_minify(texture->depth0, level)) { 984bf215546Sopenharmony_ci return sp_sview->border_color.f; 985bf215546Sopenharmony_ci } 986bf215546Sopenharmony_ci else { 987bf215546Sopenharmony_ci return get_texel_3d_no_border( sp_sview, addr, x, y, z ); 988bf215546Sopenharmony_ci } 989bf215546Sopenharmony_ci} 990bf215546Sopenharmony_ci 991bf215546Sopenharmony_ci 992bf215546Sopenharmony_ci/* Get texel pointer for 1D array texture */ 993bf215546Sopenharmony_cistatic inline const float * 994bf215546Sopenharmony_ciget_texel_1d_array(const struct sp_sampler_view *sp_sview, 995bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 996bf215546Sopenharmony_ci union tex_tile_address addr, int x, int y) 997bf215546Sopenharmony_ci{ 998bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 999bf215546Sopenharmony_ci const unsigned level = addr.bits.level; 1000bf215546Sopenharmony_ci 1001bf215546Sopenharmony_ci if (x < 0 || x >= (int) u_minify(texture->width0, level)) { 1002bf215546Sopenharmony_ci return sp_sview->border_color.f; 1003bf215546Sopenharmony_ci } 1004bf215546Sopenharmony_ci else { 1005bf215546Sopenharmony_ci return get_texel_2d_no_border(sp_sview, addr, x, y); 1006bf215546Sopenharmony_ci } 1007bf215546Sopenharmony_ci} 1008bf215546Sopenharmony_ci 1009bf215546Sopenharmony_ci 1010bf215546Sopenharmony_ci/* Get texel pointer for 2D array texture */ 1011bf215546Sopenharmony_cistatic inline const float * 1012bf215546Sopenharmony_ciget_texel_2d_array(const struct sp_sampler_view *sp_sview, 1013bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1014bf215546Sopenharmony_ci union tex_tile_address addr, int x, int y, int layer) 1015bf215546Sopenharmony_ci{ 1016bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1017bf215546Sopenharmony_ci const unsigned level = addr.bits.level; 1018bf215546Sopenharmony_ci 1019bf215546Sopenharmony_ci assert(layer < (int) texture->array_size); 1020bf215546Sopenharmony_ci assert(layer >= 0); 1021bf215546Sopenharmony_ci 1022bf215546Sopenharmony_ci if (x < 0 || x >= (int) u_minify(texture->width0, level) || 1023bf215546Sopenharmony_ci y < 0 || y >= (int) u_minify(texture->height0, level)) { 1024bf215546Sopenharmony_ci return sp_sview->border_color.f; 1025bf215546Sopenharmony_ci } 1026bf215546Sopenharmony_ci else { 1027bf215546Sopenharmony_ci return get_texel_3d_no_border(sp_sview, addr, x, y, layer); 1028bf215546Sopenharmony_ci } 1029bf215546Sopenharmony_ci} 1030bf215546Sopenharmony_ci 1031bf215546Sopenharmony_ci 1032bf215546Sopenharmony_cistatic inline const float * 1033bf215546Sopenharmony_ciget_texel_cube_seamless(const struct sp_sampler_view *sp_sview, 1034bf215546Sopenharmony_ci union tex_tile_address addr, int x, int y, 1035bf215546Sopenharmony_ci float *corner, int layer, unsigned face) 1036bf215546Sopenharmony_ci{ 1037bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1038bf215546Sopenharmony_ci const unsigned level = addr.bits.level; 1039bf215546Sopenharmony_ci int new_x, new_y, max_x; 1040bf215546Sopenharmony_ci 1041bf215546Sopenharmony_ci max_x = (int) u_minify(texture->width0, level); 1042bf215546Sopenharmony_ci 1043bf215546Sopenharmony_ci assert(texture->width0 == texture->height0); 1044bf215546Sopenharmony_ci new_x = x; 1045bf215546Sopenharmony_ci new_y = y; 1046bf215546Sopenharmony_ci 1047bf215546Sopenharmony_ci /* change the face */ 1048bf215546Sopenharmony_ci if (x < 0) { 1049bf215546Sopenharmony_ci /* 1050bf215546Sopenharmony_ci * Cheat with corners. They are difficult and I believe because we don't get 1051bf215546Sopenharmony_ci * per-pixel faces we can actually have multiple corner texels per pixel, 1052bf215546Sopenharmony_ci * which screws things up majorly in any case (as the per spec behavior is 1053bf215546Sopenharmony_ci * to average the 3 remaining texels, which we might not have). 1054bf215546Sopenharmony_ci * Hence just make sure that the 2nd coord is clamped, will simply pick the 1055bf215546Sopenharmony_ci * sample which would have fallen off the x coord, but not y coord. 1056bf215546Sopenharmony_ci * So the filter weight of the samples will be wrong, but at least this 1057bf215546Sopenharmony_ci * ensures that only valid texels near the corner are used. 1058bf215546Sopenharmony_ci */ 1059bf215546Sopenharmony_ci if (y < 0 || y >= max_x) { 1060bf215546Sopenharmony_ci y = CLAMP(y, 0, max_x - 1); 1061bf215546Sopenharmony_ci } 1062bf215546Sopenharmony_ci new_x = get_next_xcoord(face, 0, max_x -1, x, y); 1063bf215546Sopenharmony_ci new_y = get_next_ycoord(face, 0, max_x -1, x, y); 1064bf215546Sopenharmony_ci face = get_next_face(face, 0); 1065bf215546Sopenharmony_ci } else if (x >= max_x) { 1066bf215546Sopenharmony_ci if (y < 0 || y >= max_x) { 1067bf215546Sopenharmony_ci y = CLAMP(y, 0, max_x - 1); 1068bf215546Sopenharmony_ci } 1069bf215546Sopenharmony_ci new_x = get_next_xcoord(face, 1, max_x -1, x, y); 1070bf215546Sopenharmony_ci new_y = get_next_ycoord(face, 1, max_x -1, x, y); 1071bf215546Sopenharmony_ci face = get_next_face(face, 1); 1072bf215546Sopenharmony_ci } else if (y < 0) { 1073bf215546Sopenharmony_ci new_x = get_next_xcoord(face, 2, max_x -1, x, y); 1074bf215546Sopenharmony_ci new_y = get_next_ycoord(face, 2, max_x -1, x, y); 1075bf215546Sopenharmony_ci face = get_next_face(face, 2); 1076bf215546Sopenharmony_ci } else if (y >= max_x) { 1077bf215546Sopenharmony_ci new_x = get_next_xcoord(face, 3, max_x -1, x, y); 1078bf215546Sopenharmony_ci new_y = get_next_ycoord(face, 3, max_x -1, x, y); 1079bf215546Sopenharmony_ci face = get_next_face(face, 3); 1080bf215546Sopenharmony_ci } 1081bf215546Sopenharmony_ci 1082bf215546Sopenharmony_ci return get_texel_3d_no_border(sp_sview, addr, new_x, new_y, layer + face); 1083bf215546Sopenharmony_ci} 1084bf215546Sopenharmony_ci 1085bf215546Sopenharmony_ci 1086bf215546Sopenharmony_ci/* Get texel pointer for cube array texture */ 1087bf215546Sopenharmony_cistatic inline const float * 1088bf215546Sopenharmony_ciget_texel_cube_array(const struct sp_sampler_view *sp_sview, 1089bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1090bf215546Sopenharmony_ci union tex_tile_address addr, int x, int y, int layer) 1091bf215546Sopenharmony_ci{ 1092bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1093bf215546Sopenharmony_ci const unsigned level = addr.bits.level; 1094bf215546Sopenharmony_ci 1095bf215546Sopenharmony_ci assert(layer < (int) texture->array_size); 1096bf215546Sopenharmony_ci assert(layer >= 0); 1097bf215546Sopenharmony_ci 1098bf215546Sopenharmony_ci if (x < 0 || x >= (int) u_minify(texture->width0, level) || 1099bf215546Sopenharmony_ci y < 0 || y >= (int) u_minify(texture->height0, level)) { 1100bf215546Sopenharmony_ci return sp_sview->border_color.f; 1101bf215546Sopenharmony_ci } 1102bf215546Sopenharmony_ci else { 1103bf215546Sopenharmony_ci return get_texel_3d_no_border(sp_sview, addr, x, y, layer); 1104bf215546Sopenharmony_ci } 1105bf215546Sopenharmony_ci} 1106bf215546Sopenharmony_ci/** 1107bf215546Sopenharmony_ci * Given the logbase2 of a mipmap's base level size and a mipmap level, 1108bf215546Sopenharmony_ci * return the size (in texels) of that mipmap level. 1109bf215546Sopenharmony_ci * For example, if level[0].width = 256 then base_pot will be 8. 1110bf215546Sopenharmony_ci * If level = 2, then we'll return 64 (the width at level=2). 1111bf215546Sopenharmony_ci * Return 1 if level > base_pot. 1112bf215546Sopenharmony_ci */ 1113bf215546Sopenharmony_cistatic inline unsigned 1114bf215546Sopenharmony_cipot_level_size(unsigned base_pot, unsigned level) 1115bf215546Sopenharmony_ci{ 1116bf215546Sopenharmony_ci return (base_pot >= level) ? (1 << (base_pot - level)) : 1; 1117bf215546Sopenharmony_ci} 1118bf215546Sopenharmony_ci 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_cistatic void 1121bf215546Sopenharmony_ciprint_sample(const char *function, const float *rgba) 1122bf215546Sopenharmony_ci{ 1123bf215546Sopenharmony_ci debug_printf("%s %g %g %g %g\n", 1124bf215546Sopenharmony_ci function, 1125bf215546Sopenharmony_ci rgba[0], rgba[TGSI_NUM_CHANNELS], rgba[2*TGSI_NUM_CHANNELS], rgba[3*TGSI_NUM_CHANNELS]); 1126bf215546Sopenharmony_ci} 1127bf215546Sopenharmony_ci 1128bf215546Sopenharmony_ci 1129bf215546Sopenharmony_cistatic void 1130bf215546Sopenharmony_ciprint_sample_4(const char *function, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 1131bf215546Sopenharmony_ci{ 1132bf215546Sopenharmony_ci debug_printf("%s %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n", 1133bf215546Sopenharmony_ci function, 1134bf215546Sopenharmony_ci rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0], 1135bf215546Sopenharmony_ci rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1], 1136bf215546Sopenharmony_ci rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2], 1137bf215546Sopenharmony_ci rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]); 1138bf215546Sopenharmony_ci} 1139bf215546Sopenharmony_ci 1140bf215546Sopenharmony_ci 1141bf215546Sopenharmony_ci/* Some image-filter fastpaths: 1142bf215546Sopenharmony_ci */ 1143bf215546Sopenharmony_cistatic inline void 1144bf215546Sopenharmony_ciimg_filter_2d_linear_repeat_POT(const struct sp_sampler_view *sp_sview, 1145bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1146bf215546Sopenharmony_ci const struct img_filter_args *args, 1147bf215546Sopenharmony_ci float *rgba) 1148bf215546Sopenharmony_ci{ 1149bf215546Sopenharmony_ci const unsigned xpot = pot_level_size(sp_sview->xpot, args->level); 1150bf215546Sopenharmony_ci const unsigned ypot = pot_level_size(sp_sview->ypot, args->level); 1151bf215546Sopenharmony_ci const int xmax = (xpot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, xpot) - 1; */ 1152bf215546Sopenharmony_ci const int ymax = (ypot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, ypot) - 1; */ 1153bf215546Sopenharmony_ci union tex_tile_address addr; 1154bf215546Sopenharmony_ci int c; 1155bf215546Sopenharmony_ci 1156bf215546Sopenharmony_ci const float u = (args->s * xpot - 0.5F) + args->offset[0]; 1157bf215546Sopenharmony_ci const float v = (args->t * ypot - 0.5F) + args->offset[1]; 1158bf215546Sopenharmony_ci 1159bf215546Sopenharmony_ci const int uflr = util_ifloor(u); 1160bf215546Sopenharmony_ci const int vflr = util_ifloor(v); 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_ci const float xw = u - (float)uflr; 1163bf215546Sopenharmony_ci const float yw = v - (float)vflr; 1164bf215546Sopenharmony_ci 1165bf215546Sopenharmony_ci const int x0 = uflr & (xpot - 1); 1166bf215546Sopenharmony_ci const int y0 = vflr & (ypot - 1); 1167bf215546Sopenharmony_ci 1168bf215546Sopenharmony_ci const float *tx[4]; 1169bf215546Sopenharmony_ci 1170bf215546Sopenharmony_ci addr.value = 0; 1171bf215546Sopenharmony_ci addr.bits.level = args->level; 1172bf215546Sopenharmony_ci addr.bits.z = sp_sview->base.u.tex.first_layer; 1173bf215546Sopenharmony_ci 1174bf215546Sopenharmony_ci /* Can we fetch all four at once: 1175bf215546Sopenharmony_ci */ 1176bf215546Sopenharmony_ci if (x0 < xmax && y0 < ymax) { 1177bf215546Sopenharmony_ci get_texel_quad_2d_no_border_single_tile(sp_sview, addr, x0, y0, tx); 1178bf215546Sopenharmony_ci } 1179bf215546Sopenharmony_ci else { 1180bf215546Sopenharmony_ci const unsigned x1 = (x0 + 1) & (xpot - 1); 1181bf215546Sopenharmony_ci const unsigned y1 = (y0 + 1) & (ypot - 1); 1182bf215546Sopenharmony_ci get_texel_quad_2d_no_border(sp_sview, addr, x0, y0, x1, y1, tx); 1183bf215546Sopenharmony_ci } 1184bf215546Sopenharmony_ci 1185bf215546Sopenharmony_ci /* interpolate R, G, B, A */ 1186bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) { 1187bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw, 1188bf215546Sopenharmony_ci tx[0][c], tx[1][c], 1189bf215546Sopenharmony_ci tx[2][c], tx[3][c]); 1190bf215546Sopenharmony_ci } 1191bf215546Sopenharmony_ci 1192bf215546Sopenharmony_ci if (DEBUG_TEX) { 1193bf215546Sopenharmony_ci print_sample(__FUNCTION__, rgba); 1194bf215546Sopenharmony_ci } 1195bf215546Sopenharmony_ci} 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_ci 1198bf215546Sopenharmony_cistatic inline void 1199bf215546Sopenharmony_ciimg_filter_2d_nearest_repeat_POT(const struct sp_sampler_view *sp_sview, 1200bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1201bf215546Sopenharmony_ci const struct img_filter_args *args, 1202bf215546Sopenharmony_ci float *rgba) 1203bf215546Sopenharmony_ci{ 1204bf215546Sopenharmony_ci const unsigned xpot = pot_level_size(sp_sview->xpot, args->level); 1205bf215546Sopenharmony_ci const unsigned ypot = pot_level_size(sp_sview->ypot, args->level); 1206bf215546Sopenharmony_ci const float *out; 1207bf215546Sopenharmony_ci union tex_tile_address addr; 1208bf215546Sopenharmony_ci int c; 1209bf215546Sopenharmony_ci 1210bf215546Sopenharmony_ci const float u = args->s * xpot + args->offset[0]; 1211bf215546Sopenharmony_ci const float v = args->t * ypot + args->offset[1]; 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_ci const int uflr = util_ifloor(u); 1214bf215546Sopenharmony_ci const int vflr = util_ifloor(v); 1215bf215546Sopenharmony_ci 1216bf215546Sopenharmony_ci const int x0 = uflr & (xpot - 1); 1217bf215546Sopenharmony_ci const int y0 = vflr & (ypot - 1); 1218bf215546Sopenharmony_ci 1219bf215546Sopenharmony_ci addr.value = 0; 1220bf215546Sopenharmony_ci addr.bits.level = args->level; 1221bf215546Sopenharmony_ci addr.bits.z = sp_sview->base.u.tex.first_layer; 1222bf215546Sopenharmony_ci 1223bf215546Sopenharmony_ci out = get_texel_2d_no_border(sp_sview, addr, x0, y0); 1224bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1225bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = out[c]; 1226bf215546Sopenharmony_ci 1227bf215546Sopenharmony_ci if (DEBUG_TEX) { 1228bf215546Sopenharmony_ci print_sample(__FUNCTION__, rgba); 1229bf215546Sopenharmony_ci } 1230bf215546Sopenharmony_ci} 1231bf215546Sopenharmony_ci 1232bf215546Sopenharmony_ci 1233bf215546Sopenharmony_cistatic inline void 1234bf215546Sopenharmony_ciimg_filter_2d_nearest_clamp_POT(const struct sp_sampler_view *sp_sview, 1235bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1236bf215546Sopenharmony_ci const struct img_filter_args *args, 1237bf215546Sopenharmony_ci float *rgba) 1238bf215546Sopenharmony_ci{ 1239bf215546Sopenharmony_ci const unsigned xpot = pot_level_size(sp_sview->xpot, args->level); 1240bf215546Sopenharmony_ci const unsigned ypot = pot_level_size(sp_sview->ypot, args->level); 1241bf215546Sopenharmony_ci union tex_tile_address addr; 1242bf215546Sopenharmony_ci int c; 1243bf215546Sopenharmony_ci 1244bf215546Sopenharmony_ci const float u = args->s * xpot + args->offset[0]; 1245bf215546Sopenharmony_ci const float v = args->t * ypot + args->offset[1]; 1246bf215546Sopenharmony_ci 1247bf215546Sopenharmony_ci int x0, y0; 1248bf215546Sopenharmony_ci const float *out; 1249bf215546Sopenharmony_ci 1250bf215546Sopenharmony_ci addr.value = 0; 1251bf215546Sopenharmony_ci addr.bits.level = args->level; 1252bf215546Sopenharmony_ci addr.bits.z = sp_sview->base.u.tex.first_layer; 1253bf215546Sopenharmony_ci 1254bf215546Sopenharmony_ci x0 = util_ifloor(u); 1255bf215546Sopenharmony_ci if (x0 < 0) 1256bf215546Sopenharmony_ci x0 = 0; 1257bf215546Sopenharmony_ci else if (x0 > (int) xpot - 1) 1258bf215546Sopenharmony_ci x0 = xpot - 1; 1259bf215546Sopenharmony_ci 1260bf215546Sopenharmony_ci y0 = util_ifloor(v); 1261bf215546Sopenharmony_ci if (y0 < 0) 1262bf215546Sopenharmony_ci y0 = 0; 1263bf215546Sopenharmony_ci else if (y0 > (int) ypot - 1) 1264bf215546Sopenharmony_ci y0 = ypot - 1; 1265bf215546Sopenharmony_ci 1266bf215546Sopenharmony_ci out = get_texel_2d_no_border(sp_sview, addr, x0, y0); 1267bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1268bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = out[c]; 1269bf215546Sopenharmony_ci 1270bf215546Sopenharmony_ci if (DEBUG_TEX) { 1271bf215546Sopenharmony_ci print_sample(__FUNCTION__, rgba); 1272bf215546Sopenharmony_ci } 1273bf215546Sopenharmony_ci} 1274bf215546Sopenharmony_ci 1275bf215546Sopenharmony_ci 1276bf215546Sopenharmony_cistatic void 1277bf215546Sopenharmony_ciimg_filter_1d_nearest(const struct sp_sampler_view *sp_sview, 1278bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1279bf215546Sopenharmony_ci const struct img_filter_args *args, 1280bf215546Sopenharmony_ci float *rgba) 1281bf215546Sopenharmony_ci{ 1282bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1283bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1284bf215546Sopenharmony_ci int x; 1285bf215546Sopenharmony_ci union tex_tile_address addr; 1286bf215546Sopenharmony_ci const float *out; 1287bf215546Sopenharmony_ci int c; 1288bf215546Sopenharmony_ci 1289bf215546Sopenharmony_ci assert(width > 0); 1290bf215546Sopenharmony_ci 1291bf215546Sopenharmony_ci addr.value = 0; 1292bf215546Sopenharmony_ci addr.bits.level = args->level; 1293bf215546Sopenharmony_ci 1294bf215546Sopenharmony_ci sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x); 1295bf215546Sopenharmony_ci 1296bf215546Sopenharmony_ci out = get_texel_1d_array(sp_sview, sp_samp, addr, x, 1297bf215546Sopenharmony_ci sp_sview->base.u.tex.first_layer); 1298bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1299bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = out[c]; 1300bf215546Sopenharmony_ci 1301bf215546Sopenharmony_ci if (DEBUG_TEX) { 1302bf215546Sopenharmony_ci print_sample(__FUNCTION__, rgba); 1303bf215546Sopenharmony_ci } 1304bf215546Sopenharmony_ci} 1305bf215546Sopenharmony_ci 1306bf215546Sopenharmony_ci 1307bf215546Sopenharmony_cistatic void 1308bf215546Sopenharmony_ciimg_filter_1d_array_nearest(const struct sp_sampler_view *sp_sview, 1309bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1310bf215546Sopenharmony_ci const struct img_filter_args *args, 1311bf215546Sopenharmony_ci float *rgba) 1312bf215546Sopenharmony_ci{ 1313bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1314bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1315bf215546Sopenharmony_ci const int layer = coord_to_layer(args->t, sp_sview->base.u.tex.first_layer, 1316bf215546Sopenharmony_ci sp_sview->base.u.tex.last_layer); 1317bf215546Sopenharmony_ci int x; 1318bf215546Sopenharmony_ci union tex_tile_address addr; 1319bf215546Sopenharmony_ci const float *out; 1320bf215546Sopenharmony_ci int c; 1321bf215546Sopenharmony_ci 1322bf215546Sopenharmony_ci assert(width > 0); 1323bf215546Sopenharmony_ci 1324bf215546Sopenharmony_ci addr.value = 0; 1325bf215546Sopenharmony_ci addr.bits.level = args->level; 1326bf215546Sopenharmony_ci 1327bf215546Sopenharmony_ci sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x); 1328bf215546Sopenharmony_ci 1329bf215546Sopenharmony_ci out = get_texel_1d_array(sp_sview, sp_samp, addr, x, layer); 1330bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1331bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = out[c]; 1332bf215546Sopenharmony_ci 1333bf215546Sopenharmony_ci if (DEBUG_TEX) { 1334bf215546Sopenharmony_ci print_sample(__FUNCTION__, rgba); 1335bf215546Sopenharmony_ci } 1336bf215546Sopenharmony_ci} 1337bf215546Sopenharmony_ci 1338bf215546Sopenharmony_ci 1339bf215546Sopenharmony_cistatic void 1340bf215546Sopenharmony_ciimg_filter_2d_nearest(const struct sp_sampler_view *sp_sview, 1341bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1342bf215546Sopenharmony_ci const struct img_filter_args *args, 1343bf215546Sopenharmony_ci float *rgba) 1344bf215546Sopenharmony_ci{ 1345bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1346bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1347bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1348bf215546Sopenharmony_ci int x, y; 1349bf215546Sopenharmony_ci union tex_tile_address addr; 1350bf215546Sopenharmony_ci const float *out; 1351bf215546Sopenharmony_ci int c; 1352bf215546Sopenharmony_ci 1353bf215546Sopenharmony_ci assert(width > 0); 1354bf215546Sopenharmony_ci assert(height > 0); 1355bf215546Sopenharmony_ci 1356bf215546Sopenharmony_ci addr.value = 0; 1357bf215546Sopenharmony_ci addr.bits.level = args->level; 1358bf215546Sopenharmony_ci addr.bits.z = sp_sview->base.u.tex.first_layer; 1359bf215546Sopenharmony_ci 1360bf215546Sopenharmony_ci sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x); 1361bf215546Sopenharmony_ci sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y); 1362bf215546Sopenharmony_ci 1363bf215546Sopenharmony_ci out = get_texel_2d(sp_sview, sp_samp, addr, x, y); 1364bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1365bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = out[c]; 1366bf215546Sopenharmony_ci 1367bf215546Sopenharmony_ci if (DEBUG_TEX) { 1368bf215546Sopenharmony_ci print_sample(__FUNCTION__, rgba); 1369bf215546Sopenharmony_ci } 1370bf215546Sopenharmony_ci} 1371bf215546Sopenharmony_ci 1372bf215546Sopenharmony_ci 1373bf215546Sopenharmony_cistatic void 1374bf215546Sopenharmony_ciimg_filter_2d_array_nearest(const struct sp_sampler_view *sp_sview, 1375bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1376bf215546Sopenharmony_ci const struct img_filter_args *args, 1377bf215546Sopenharmony_ci float *rgba) 1378bf215546Sopenharmony_ci{ 1379bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1380bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1381bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1382bf215546Sopenharmony_ci const int layer = coord_to_layer(args->p, sp_sview->base.u.tex.first_layer, 1383bf215546Sopenharmony_ci sp_sview->base.u.tex.last_layer); 1384bf215546Sopenharmony_ci int x, y; 1385bf215546Sopenharmony_ci union tex_tile_address addr; 1386bf215546Sopenharmony_ci const float *out; 1387bf215546Sopenharmony_ci int c; 1388bf215546Sopenharmony_ci 1389bf215546Sopenharmony_ci assert(width > 0); 1390bf215546Sopenharmony_ci assert(height > 0); 1391bf215546Sopenharmony_ci 1392bf215546Sopenharmony_ci addr.value = 0; 1393bf215546Sopenharmony_ci addr.bits.level = args->level; 1394bf215546Sopenharmony_ci 1395bf215546Sopenharmony_ci sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x); 1396bf215546Sopenharmony_ci sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y); 1397bf215546Sopenharmony_ci 1398bf215546Sopenharmony_ci out = get_texel_2d_array(sp_sview, sp_samp, addr, x, y, layer); 1399bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1400bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = out[c]; 1401bf215546Sopenharmony_ci 1402bf215546Sopenharmony_ci if (DEBUG_TEX) { 1403bf215546Sopenharmony_ci print_sample(__FUNCTION__, rgba); 1404bf215546Sopenharmony_ci } 1405bf215546Sopenharmony_ci} 1406bf215546Sopenharmony_ci 1407bf215546Sopenharmony_ci 1408bf215546Sopenharmony_cistatic void 1409bf215546Sopenharmony_ciimg_filter_cube_nearest(const struct sp_sampler_view *sp_sview, 1410bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1411bf215546Sopenharmony_ci const struct img_filter_args *args, 1412bf215546Sopenharmony_ci float *rgba) 1413bf215546Sopenharmony_ci{ 1414bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1415bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1416bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1417bf215546Sopenharmony_ci const int layerface = args->face_id + sp_sview->base.u.tex.first_layer; 1418bf215546Sopenharmony_ci int x, y; 1419bf215546Sopenharmony_ci union tex_tile_address addr; 1420bf215546Sopenharmony_ci const float *out; 1421bf215546Sopenharmony_ci int c; 1422bf215546Sopenharmony_ci 1423bf215546Sopenharmony_ci assert(width > 0); 1424bf215546Sopenharmony_ci assert(height > 0); 1425bf215546Sopenharmony_ci 1426bf215546Sopenharmony_ci addr.value = 0; 1427bf215546Sopenharmony_ci addr.bits.level = args->level; 1428bf215546Sopenharmony_ci 1429bf215546Sopenharmony_ci /* 1430bf215546Sopenharmony_ci * If NEAREST filtering is done within a miplevel, always apply wrap 1431bf215546Sopenharmony_ci * mode CLAMP_TO_EDGE. 1432bf215546Sopenharmony_ci */ 1433bf215546Sopenharmony_ci if (sp_samp->base.seamless_cube_map) { 1434bf215546Sopenharmony_ci wrap_nearest_clamp_to_edge(args->s, width, args->offset[0], &x); 1435bf215546Sopenharmony_ci wrap_nearest_clamp_to_edge(args->t, height, args->offset[1], &y); 1436bf215546Sopenharmony_ci } else { 1437bf215546Sopenharmony_ci /* Would probably make sense to ignore mode and just do edge clamp */ 1438bf215546Sopenharmony_ci sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x); 1439bf215546Sopenharmony_ci sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y); 1440bf215546Sopenharmony_ci } 1441bf215546Sopenharmony_ci 1442bf215546Sopenharmony_ci out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layerface); 1443bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1444bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = out[c]; 1445bf215546Sopenharmony_ci 1446bf215546Sopenharmony_ci if (DEBUG_TEX) { 1447bf215546Sopenharmony_ci print_sample(__FUNCTION__, rgba); 1448bf215546Sopenharmony_ci } 1449bf215546Sopenharmony_ci} 1450bf215546Sopenharmony_ci 1451bf215546Sopenharmony_cistatic void 1452bf215546Sopenharmony_ciimg_filter_cube_array_nearest(const struct sp_sampler_view *sp_sview, 1453bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1454bf215546Sopenharmony_ci const struct img_filter_args *args, 1455bf215546Sopenharmony_ci float *rgba) 1456bf215546Sopenharmony_ci{ 1457bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1458bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1459bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1460bf215546Sopenharmony_ci const int layerface = CLAMP(6 * util_ifloor(args->p + 0.5f) + sp_sview->base.u.tex.first_layer, 1461bf215546Sopenharmony_ci sp_sview->base.u.tex.first_layer, 1462bf215546Sopenharmony_ci sp_sview->base.u.tex.last_layer - 5) + args->face_id; 1463bf215546Sopenharmony_ci int x, y; 1464bf215546Sopenharmony_ci union tex_tile_address addr; 1465bf215546Sopenharmony_ci const float *out; 1466bf215546Sopenharmony_ci int c; 1467bf215546Sopenharmony_ci 1468bf215546Sopenharmony_ci assert(width > 0); 1469bf215546Sopenharmony_ci assert(height > 0); 1470bf215546Sopenharmony_ci 1471bf215546Sopenharmony_ci addr.value = 0; 1472bf215546Sopenharmony_ci addr.bits.level = args->level; 1473bf215546Sopenharmony_ci 1474bf215546Sopenharmony_ci sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x); 1475bf215546Sopenharmony_ci sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y); 1476bf215546Sopenharmony_ci 1477bf215546Sopenharmony_ci out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layerface); 1478bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1479bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = out[c]; 1480bf215546Sopenharmony_ci 1481bf215546Sopenharmony_ci if (DEBUG_TEX) { 1482bf215546Sopenharmony_ci print_sample(__FUNCTION__, rgba); 1483bf215546Sopenharmony_ci } 1484bf215546Sopenharmony_ci} 1485bf215546Sopenharmony_ci 1486bf215546Sopenharmony_cistatic void 1487bf215546Sopenharmony_ciimg_filter_3d_nearest(const struct sp_sampler_view *sp_sview, 1488bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1489bf215546Sopenharmony_ci const struct img_filter_args *args, 1490bf215546Sopenharmony_ci float *rgba) 1491bf215546Sopenharmony_ci{ 1492bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1493bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1494bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1495bf215546Sopenharmony_ci const int depth = u_minify(texture->depth0, args->level); 1496bf215546Sopenharmony_ci int x, y, z; 1497bf215546Sopenharmony_ci union tex_tile_address addr; 1498bf215546Sopenharmony_ci const float *out; 1499bf215546Sopenharmony_ci int c; 1500bf215546Sopenharmony_ci 1501bf215546Sopenharmony_ci assert(width > 0); 1502bf215546Sopenharmony_ci assert(height > 0); 1503bf215546Sopenharmony_ci assert(depth > 0); 1504bf215546Sopenharmony_ci 1505bf215546Sopenharmony_ci sp_samp->nearest_texcoord_s(args->s, width, args->offset[0], &x); 1506bf215546Sopenharmony_ci sp_samp->nearest_texcoord_t(args->t, height, args->offset[1], &y); 1507bf215546Sopenharmony_ci sp_samp->nearest_texcoord_p(args->p, depth, args->offset[2], &z); 1508bf215546Sopenharmony_ci 1509bf215546Sopenharmony_ci addr.value = 0; 1510bf215546Sopenharmony_ci addr.bits.level = args->level; 1511bf215546Sopenharmony_ci 1512bf215546Sopenharmony_ci out = get_texel_3d(sp_sview, sp_samp, addr, x, y, z); 1513bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1514bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = out[c]; 1515bf215546Sopenharmony_ci} 1516bf215546Sopenharmony_ci 1517bf215546Sopenharmony_ci 1518bf215546Sopenharmony_cistatic void 1519bf215546Sopenharmony_ciimg_filter_1d_linear(const struct sp_sampler_view *sp_sview, 1520bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1521bf215546Sopenharmony_ci const struct img_filter_args *args, 1522bf215546Sopenharmony_ci float *rgba) 1523bf215546Sopenharmony_ci{ 1524bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1525bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1526bf215546Sopenharmony_ci int x0, x1; 1527bf215546Sopenharmony_ci float xw; /* weights */ 1528bf215546Sopenharmony_ci union tex_tile_address addr; 1529bf215546Sopenharmony_ci const float *tx0, *tx1; 1530bf215546Sopenharmony_ci int c; 1531bf215546Sopenharmony_ci 1532bf215546Sopenharmony_ci assert(width > 0); 1533bf215546Sopenharmony_ci 1534bf215546Sopenharmony_ci addr.value = 0; 1535bf215546Sopenharmony_ci addr.bits.level = args->level; 1536bf215546Sopenharmony_ci 1537bf215546Sopenharmony_ci sp_samp->linear_texcoord_s(args->s, width, args->offset[0], &x0, &x1, &xw); 1538bf215546Sopenharmony_ci 1539bf215546Sopenharmony_ci tx0 = get_texel_1d_array(sp_sview, sp_samp, addr, x0, 1540bf215546Sopenharmony_ci sp_sview->base.u.tex.first_layer); 1541bf215546Sopenharmony_ci tx1 = get_texel_1d_array(sp_sview, sp_samp, addr, x1, 1542bf215546Sopenharmony_ci sp_sview->base.u.tex.first_layer); 1543bf215546Sopenharmony_ci 1544bf215546Sopenharmony_ci /* interpolate R, G, B, A */ 1545bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1546bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]); 1547bf215546Sopenharmony_ci} 1548bf215546Sopenharmony_ci 1549bf215546Sopenharmony_ci 1550bf215546Sopenharmony_cistatic void 1551bf215546Sopenharmony_ciimg_filter_1d_array_linear(const struct sp_sampler_view *sp_sview, 1552bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1553bf215546Sopenharmony_ci const struct img_filter_args *args, 1554bf215546Sopenharmony_ci float *rgba) 1555bf215546Sopenharmony_ci{ 1556bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1557bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1558bf215546Sopenharmony_ci const int layer = coord_to_layer(args->t, sp_sview->base.u.tex.first_layer, 1559bf215546Sopenharmony_ci sp_sview->base.u.tex.last_layer); 1560bf215546Sopenharmony_ci int x0, x1; 1561bf215546Sopenharmony_ci float xw; /* weights */ 1562bf215546Sopenharmony_ci union tex_tile_address addr; 1563bf215546Sopenharmony_ci const float *tx0, *tx1; 1564bf215546Sopenharmony_ci int c; 1565bf215546Sopenharmony_ci 1566bf215546Sopenharmony_ci assert(width > 0); 1567bf215546Sopenharmony_ci 1568bf215546Sopenharmony_ci addr.value = 0; 1569bf215546Sopenharmony_ci addr.bits.level = args->level; 1570bf215546Sopenharmony_ci 1571bf215546Sopenharmony_ci sp_samp->linear_texcoord_s(args->s, width, args->offset[0], &x0, &x1, &xw); 1572bf215546Sopenharmony_ci 1573bf215546Sopenharmony_ci tx0 = get_texel_1d_array(sp_sview, sp_samp, addr, x0, layer); 1574bf215546Sopenharmony_ci tx1 = get_texel_1d_array(sp_sview, sp_samp, addr, x1, layer); 1575bf215546Sopenharmony_ci 1576bf215546Sopenharmony_ci /* interpolate R, G, B, A */ 1577bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1578bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]); 1579bf215546Sopenharmony_ci} 1580bf215546Sopenharmony_ci 1581bf215546Sopenharmony_ci/* 1582bf215546Sopenharmony_ci * Retrieve the gathered value, need to convert to the 1583bf215546Sopenharmony_ci * TGSI expected interface, and take component select 1584bf215546Sopenharmony_ci * and swizzling into account. 1585bf215546Sopenharmony_ci */ 1586bf215546Sopenharmony_cistatic float 1587bf215546Sopenharmony_ciget_gather_value(const struct sp_sampler_view *sp_sview, 1588bf215546Sopenharmony_ci int chan_in, int comp_sel, 1589bf215546Sopenharmony_ci const float *tx[4]) 1590bf215546Sopenharmony_ci{ 1591bf215546Sopenharmony_ci int chan; 1592bf215546Sopenharmony_ci unsigned swizzle; 1593bf215546Sopenharmony_ci 1594bf215546Sopenharmony_ci /* 1595bf215546Sopenharmony_ci * softpipe samples in a different order 1596bf215546Sopenharmony_ci * to TGSI expects, so we need to swizzle, 1597bf215546Sopenharmony_ci * the samples into the correct slots. 1598bf215546Sopenharmony_ci */ 1599bf215546Sopenharmony_ci switch (chan_in) { 1600bf215546Sopenharmony_ci case 0: 1601bf215546Sopenharmony_ci chan = 2; 1602bf215546Sopenharmony_ci break; 1603bf215546Sopenharmony_ci case 1: 1604bf215546Sopenharmony_ci chan = 3; 1605bf215546Sopenharmony_ci break; 1606bf215546Sopenharmony_ci case 2: 1607bf215546Sopenharmony_ci chan = 1; 1608bf215546Sopenharmony_ci break; 1609bf215546Sopenharmony_ci case 3: 1610bf215546Sopenharmony_ci chan = 0; 1611bf215546Sopenharmony_ci break; 1612bf215546Sopenharmony_ci default: 1613bf215546Sopenharmony_ci assert(0); 1614bf215546Sopenharmony_ci return 0.0; 1615bf215546Sopenharmony_ci } 1616bf215546Sopenharmony_ci 1617bf215546Sopenharmony_ci /* pick which component to use for the swizzle */ 1618bf215546Sopenharmony_ci switch (comp_sel) { 1619bf215546Sopenharmony_ci case 0: 1620bf215546Sopenharmony_ci swizzle = sp_sview->base.swizzle_r; 1621bf215546Sopenharmony_ci break; 1622bf215546Sopenharmony_ci case 1: 1623bf215546Sopenharmony_ci swizzle = sp_sview->base.swizzle_g; 1624bf215546Sopenharmony_ci break; 1625bf215546Sopenharmony_ci case 2: 1626bf215546Sopenharmony_ci swizzle = sp_sview->base.swizzle_b; 1627bf215546Sopenharmony_ci break; 1628bf215546Sopenharmony_ci case 3: 1629bf215546Sopenharmony_ci swizzle = sp_sview->base.swizzle_a; 1630bf215546Sopenharmony_ci break; 1631bf215546Sopenharmony_ci default: 1632bf215546Sopenharmony_ci assert(0); 1633bf215546Sopenharmony_ci return 0.0; 1634bf215546Sopenharmony_ci } 1635bf215546Sopenharmony_ci 1636bf215546Sopenharmony_ci /* get correct result using the channel and swizzle */ 1637bf215546Sopenharmony_ci switch (swizzle) { 1638bf215546Sopenharmony_ci case PIPE_SWIZZLE_0: 1639bf215546Sopenharmony_ci return 0.0; 1640bf215546Sopenharmony_ci case PIPE_SWIZZLE_1: 1641bf215546Sopenharmony_ci return sp_sview->oneval; 1642bf215546Sopenharmony_ci default: 1643bf215546Sopenharmony_ci return tx[chan][swizzle]; 1644bf215546Sopenharmony_ci } 1645bf215546Sopenharmony_ci} 1646bf215546Sopenharmony_ci 1647bf215546Sopenharmony_ci 1648bf215546Sopenharmony_cistatic void 1649bf215546Sopenharmony_ciimg_filter_2d_linear(const struct sp_sampler_view *sp_sview, 1650bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1651bf215546Sopenharmony_ci const struct img_filter_args *args, 1652bf215546Sopenharmony_ci float *rgba) 1653bf215546Sopenharmony_ci{ 1654bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1655bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1656bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1657bf215546Sopenharmony_ci int x0, y0, x1, y1; 1658bf215546Sopenharmony_ci float xw, yw; /* weights */ 1659bf215546Sopenharmony_ci union tex_tile_address addr; 1660bf215546Sopenharmony_ci const float *tx[4]; 1661bf215546Sopenharmony_ci int c; 1662bf215546Sopenharmony_ci 1663bf215546Sopenharmony_ci assert(width > 0); 1664bf215546Sopenharmony_ci assert(height > 0); 1665bf215546Sopenharmony_ci 1666bf215546Sopenharmony_ci addr.value = 0; 1667bf215546Sopenharmony_ci addr.bits.level = args->level; 1668bf215546Sopenharmony_ci addr.bits.z = sp_sview->base.u.tex.first_layer; 1669bf215546Sopenharmony_ci 1670bf215546Sopenharmony_ci sp_samp->linear_texcoord_s(args->s, width, args->offset[0], &x0, &x1, &xw); 1671bf215546Sopenharmony_ci sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw); 1672bf215546Sopenharmony_ci 1673bf215546Sopenharmony_ci tx[0] = get_texel_2d(sp_sview, sp_samp, addr, x0, y0); 1674bf215546Sopenharmony_ci tx[1] = get_texel_2d(sp_sview, sp_samp, addr, x1, y0); 1675bf215546Sopenharmony_ci tx[2] = get_texel_2d(sp_sview, sp_samp, addr, x0, y1); 1676bf215546Sopenharmony_ci tx[3] = get_texel_2d(sp_sview, sp_samp, addr, x1, y1); 1677bf215546Sopenharmony_ci 1678bf215546Sopenharmony_ci if (args->gather_only) { 1679bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1680bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = get_gather_value(sp_sview, c, 1681bf215546Sopenharmony_ci args->gather_comp, 1682bf215546Sopenharmony_ci tx); 1683bf215546Sopenharmony_ci } else { 1684bf215546Sopenharmony_ci /* interpolate R, G, B, A */ 1685bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1686bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw, 1687bf215546Sopenharmony_ci tx[0][c], tx[1][c], 1688bf215546Sopenharmony_ci tx[2][c], tx[3][c]); 1689bf215546Sopenharmony_ci } 1690bf215546Sopenharmony_ci} 1691bf215546Sopenharmony_ci 1692bf215546Sopenharmony_ci 1693bf215546Sopenharmony_cistatic void 1694bf215546Sopenharmony_ciimg_filter_2d_array_linear(const struct sp_sampler_view *sp_sview, 1695bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1696bf215546Sopenharmony_ci const struct img_filter_args *args, 1697bf215546Sopenharmony_ci float *rgba) 1698bf215546Sopenharmony_ci{ 1699bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1700bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1701bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1702bf215546Sopenharmony_ci const int layer = coord_to_layer(args->p, sp_sview->base.u.tex.first_layer, 1703bf215546Sopenharmony_ci sp_sview->base.u.tex.last_layer); 1704bf215546Sopenharmony_ci int x0, y0, x1, y1; 1705bf215546Sopenharmony_ci float xw, yw; /* weights */ 1706bf215546Sopenharmony_ci union tex_tile_address addr; 1707bf215546Sopenharmony_ci const float *tx[4]; 1708bf215546Sopenharmony_ci int c; 1709bf215546Sopenharmony_ci 1710bf215546Sopenharmony_ci assert(width > 0); 1711bf215546Sopenharmony_ci assert(height > 0); 1712bf215546Sopenharmony_ci 1713bf215546Sopenharmony_ci addr.value = 0; 1714bf215546Sopenharmony_ci addr.bits.level = args->level; 1715bf215546Sopenharmony_ci 1716bf215546Sopenharmony_ci sp_samp->linear_texcoord_s(args->s, width, args->offset[0], &x0, &x1, &xw); 1717bf215546Sopenharmony_ci sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw); 1718bf215546Sopenharmony_ci 1719bf215546Sopenharmony_ci tx[0] = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y0, layer); 1720bf215546Sopenharmony_ci tx[1] = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y0, layer); 1721bf215546Sopenharmony_ci tx[2] = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y1, layer); 1722bf215546Sopenharmony_ci tx[3] = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y1, layer); 1723bf215546Sopenharmony_ci 1724bf215546Sopenharmony_ci if (args->gather_only) { 1725bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1726bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = get_gather_value(sp_sview, c, 1727bf215546Sopenharmony_ci args->gather_comp, 1728bf215546Sopenharmony_ci tx); 1729bf215546Sopenharmony_ci } else { 1730bf215546Sopenharmony_ci /* interpolate R, G, B, A */ 1731bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1732bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw, 1733bf215546Sopenharmony_ci tx[0][c], tx[1][c], 1734bf215546Sopenharmony_ci tx[2][c], tx[3][c]); 1735bf215546Sopenharmony_ci } 1736bf215546Sopenharmony_ci} 1737bf215546Sopenharmony_ci 1738bf215546Sopenharmony_ci 1739bf215546Sopenharmony_cistatic void 1740bf215546Sopenharmony_ciimg_filter_cube_linear(const struct sp_sampler_view *sp_sview, 1741bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1742bf215546Sopenharmony_ci const struct img_filter_args *args, 1743bf215546Sopenharmony_ci float *rgba) 1744bf215546Sopenharmony_ci{ 1745bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1746bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1747bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1748bf215546Sopenharmony_ci const int layer = sp_sview->base.u.tex.first_layer; 1749bf215546Sopenharmony_ci int x0, y0, x1, y1; 1750bf215546Sopenharmony_ci float xw, yw; /* weights */ 1751bf215546Sopenharmony_ci union tex_tile_address addr; 1752bf215546Sopenharmony_ci const float *tx[4]; 1753bf215546Sopenharmony_ci float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE], 1754bf215546Sopenharmony_ci corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE]; 1755bf215546Sopenharmony_ci int c; 1756bf215546Sopenharmony_ci 1757bf215546Sopenharmony_ci assert(width > 0); 1758bf215546Sopenharmony_ci assert(height > 0); 1759bf215546Sopenharmony_ci 1760bf215546Sopenharmony_ci addr.value = 0; 1761bf215546Sopenharmony_ci addr.bits.level = args->level; 1762bf215546Sopenharmony_ci 1763bf215546Sopenharmony_ci /* 1764bf215546Sopenharmony_ci * For seamless if LINEAR filtering is done within a miplevel, 1765bf215546Sopenharmony_ci * always apply wrap mode CLAMP_TO_BORDER. 1766bf215546Sopenharmony_ci */ 1767bf215546Sopenharmony_ci if (sp_samp->base.seamless_cube_map) { 1768bf215546Sopenharmony_ci /* Note this is a bit overkill, actual clamping is not required */ 1769bf215546Sopenharmony_ci wrap_linear_clamp_to_border(args->s, width, args->offset[0], &x0, &x1, &xw); 1770bf215546Sopenharmony_ci wrap_linear_clamp_to_border(args->t, height, args->offset[1], &y0, &y1, &yw); 1771bf215546Sopenharmony_ci } else { 1772bf215546Sopenharmony_ci /* Would probably make sense to ignore mode and just do edge clamp */ 1773bf215546Sopenharmony_ci sp_samp->linear_texcoord_s(args->s, width, args->offset[0], &x0, &x1, &xw); 1774bf215546Sopenharmony_ci sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw); 1775bf215546Sopenharmony_ci } 1776bf215546Sopenharmony_ci 1777bf215546Sopenharmony_ci if (sp_samp->base.seamless_cube_map) { 1778bf215546Sopenharmony_ci tx[0] = get_texel_cube_seamless(sp_sview, addr, x0, y0, corner0, layer, args->face_id); 1779bf215546Sopenharmony_ci tx[1] = get_texel_cube_seamless(sp_sview, addr, x1, y0, corner1, layer, args->face_id); 1780bf215546Sopenharmony_ci tx[2] = get_texel_cube_seamless(sp_sview, addr, x0, y1, corner2, layer, args->face_id); 1781bf215546Sopenharmony_ci tx[3] = get_texel_cube_seamless(sp_sview, addr, x1, y1, corner3, layer, args->face_id); 1782bf215546Sopenharmony_ci } else { 1783bf215546Sopenharmony_ci tx[0] = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer + args->face_id); 1784bf215546Sopenharmony_ci tx[1] = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer + args->face_id); 1785bf215546Sopenharmony_ci tx[2] = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer + args->face_id); 1786bf215546Sopenharmony_ci tx[3] = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer + args->face_id); 1787bf215546Sopenharmony_ci } 1788bf215546Sopenharmony_ci 1789bf215546Sopenharmony_ci if (args->gather_only) { 1790bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1791bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = get_gather_value(sp_sview, c, 1792bf215546Sopenharmony_ci args->gather_comp, 1793bf215546Sopenharmony_ci tx); 1794bf215546Sopenharmony_ci } else { 1795bf215546Sopenharmony_ci /* interpolate R, G, B, A */ 1796bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1797bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw, 1798bf215546Sopenharmony_ci tx[0][c], tx[1][c], 1799bf215546Sopenharmony_ci tx[2][c], tx[3][c]); 1800bf215546Sopenharmony_ci } 1801bf215546Sopenharmony_ci} 1802bf215546Sopenharmony_ci 1803bf215546Sopenharmony_ci 1804bf215546Sopenharmony_cistatic void 1805bf215546Sopenharmony_ciimg_filter_cube_array_linear(const struct sp_sampler_view *sp_sview, 1806bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1807bf215546Sopenharmony_ci const struct img_filter_args *args, 1808bf215546Sopenharmony_ci float *rgba) 1809bf215546Sopenharmony_ci{ 1810bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1811bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1812bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1813bf215546Sopenharmony_ci 1814bf215546Sopenharmony_ci const int layer = CLAMP(6 * util_ifloor(args->p + 0.5f) + sp_sview->base.u.tex.first_layer, 1815bf215546Sopenharmony_ci sp_sview->base.u.tex.first_layer, 1816bf215546Sopenharmony_ci sp_sview->base.u.tex.last_layer - 5); 1817bf215546Sopenharmony_ci 1818bf215546Sopenharmony_ci int x0, y0, x1, y1; 1819bf215546Sopenharmony_ci float xw, yw; /* weights */ 1820bf215546Sopenharmony_ci union tex_tile_address addr; 1821bf215546Sopenharmony_ci const float *tx[4]; 1822bf215546Sopenharmony_ci float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE], 1823bf215546Sopenharmony_ci corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE]; 1824bf215546Sopenharmony_ci int c; 1825bf215546Sopenharmony_ci 1826bf215546Sopenharmony_ci assert(width > 0); 1827bf215546Sopenharmony_ci assert(height > 0); 1828bf215546Sopenharmony_ci 1829bf215546Sopenharmony_ci addr.value = 0; 1830bf215546Sopenharmony_ci addr.bits.level = args->level; 1831bf215546Sopenharmony_ci 1832bf215546Sopenharmony_ci /* 1833bf215546Sopenharmony_ci * For seamless if LINEAR filtering is done within a miplevel, 1834bf215546Sopenharmony_ci * always apply wrap mode CLAMP_TO_BORDER. 1835bf215546Sopenharmony_ci */ 1836bf215546Sopenharmony_ci if (sp_samp->base.seamless_cube_map) { 1837bf215546Sopenharmony_ci /* Note this is a bit overkill, actual clamping is not required */ 1838bf215546Sopenharmony_ci wrap_linear_clamp_to_border(args->s, width, args->offset[0], &x0, &x1, &xw); 1839bf215546Sopenharmony_ci wrap_linear_clamp_to_border(args->t, height, args->offset[1], &y0, &y1, &yw); 1840bf215546Sopenharmony_ci } else { 1841bf215546Sopenharmony_ci /* Would probably make sense to ignore mode and just do edge clamp */ 1842bf215546Sopenharmony_ci sp_samp->linear_texcoord_s(args->s, width, args->offset[0], &x0, &x1, &xw); 1843bf215546Sopenharmony_ci sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw); 1844bf215546Sopenharmony_ci } 1845bf215546Sopenharmony_ci 1846bf215546Sopenharmony_ci if (sp_samp->base.seamless_cube_map) { 1847bf215546Sopenharmony_ci tx[0] = get_texel_cube_seamless(sp_sview, addr, x0, y0, corner0, layer, args->face_id); 1848bf215546Sopenharmony_ci tx[1] = get_texel_cube_seamless(sp_sview, addr, x1, y0, corner1, layer, args->face_id); 1849bf215546Sopenharmony_ci tx[2] = get_texel_cube_seamless(sp_sview, addr, x0, y1, corner2, layer, args->face_id); 1850bf215546Sopenharmony_ci tx[3] = get_texel_cube_seamless(sp_sview, addr, x1, y1, corner3, layer, args->face_id); 1851bf215546Sopenharmony_ci } else { 1852bf215546Sopenharmony_ci tx[0] = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer + args->face_id); 1853bf215546Sopenharmony_ci tx[1] = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer + args->face_id); 1854bf215546Sopenharmony_ci tx[2] = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer + args->face_id); 1855bf215546Sopenharmony_ci tx[3] = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer + args->face_id); 1856bf215546Sopenharmony_ci } 1857bf215546Sopenharmony_ci 1858bf215546Sopenharmony_ci if (args->gather_only) { 1859bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1860bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = get_gather_value(sp_sview, c, 1861bf215546Sopenharmony_ci args->gather_comp, 1862bf215546Sopenharmony_ci tx); 1863bf215546Sopenharmony_ci } else { 1864bf215546Sopenharmony_ci /* interpolate R, G, B, A */ 1865bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1866bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw, 1867bf215546Sopenharmony_ci tx[0][c], tx[1][c], 1868bf215546Sopenharmony_ci tx[2][c], tx[3][c]); 1869bf215546Sopenharmony_ci } 1870bf215546Sopenharmony_ci} 1871bf215546Sopenharmony_ci 1872bf215546Sopenharmony_cistatic void 1873bf215546Sopenharmony_ciimg_filter_3d_linear(const struct sp_sampler_view *sp_sview, 1874bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1875bf215546Sopenharmony_ci const struct img_filter_args *args, 1876bf215546Sopenharmony_ci float *rgba) 1877bf215546Sopenharmony_ci{ 1878bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 1879bf215546Sopenharmony_ci const int width = u_minify(texture->width0, args->level); 1880bf215546Sopenharmony_ci const int height = u_minify(texture->height0, args->level); 1881bf215546Sopenharmony_ci const int depth = u_minify(texture->depth0, args->level); 1882bf215546Sopenharmony_ci int x0, x1, y0, y1, z0, z1; 1883bf215546Sopenharmony_ci float xw, yw, zw; /* interpolation weights */ 1884bf215546Sopenharmony_ci union tex_tile_address addr; 1885bf215546Sopenharmony_ci const float *tx00, *tx01, *tx02, *tx03, *tx10, *tx11, *tx12, *tx13; 1886bf215546Sopenharmony_ci int c; 1887bf215546Sopenharmony_ci 1888bf215546Sopenharmony_ci addr.value = 0; 1889bf215546Sopenharmony_ci addr.bits.level = args->level; 1890bf215546Sopenharmony_ci 1891bf215546Sopenharmony_ci assert(width > 0); 1892bf215546Sopenharmony_ci assert(height > 0); 1893bf215546Sopenharmony_ci assert(depth > 0); 1894bf215546Sopenharmony_ci 1895bf215546Sopenharmony_ci sp_samp->linear_texcoord_s(args->s, width, args->offset[0], &x0, &x1, &xw); 1896bf215546Sopenharmony_ci sp_samp->linear_texcoord_t(args->t, height, args->offset[1], &y0, &y1, &yw); 1897bf215546Sopenharmony_ci sp_samp->linear_texcoord_p(args->p, depth, args->offset[2], &z0, &z1, &zw); 1898bf215546Sopenharmony_ci 1899bf215546Sopenharmony_ci tx00 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z0); 1900bf215546Sopenharmony_ci tx01 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z0); 1901bf215546Sopenharmony_ci tx02 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z0); 1902bf215546Sopenharmony_ci tx03 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z0); 1903bf215546Sopenharmony_ci 1904bf215546Sopenharmony_ci tx10 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z1); 1905bf215546Sopenharmony_ci tx11 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z1); 1906bf215546Sopenharmony_ci tx12 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z1); 1907bf215546Sopenharmony_ci tx13 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z1); 1908bf215546Sopenharmony_ci 1909bf215546Sopenharmony_ci /* interpolate R, G, B, A */ 1910bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 1911bf215546Sopenharmony_ci rgba[TGSI_NUM_CHANNELS*c] = lerp_3d(xw, yw, zw, 1912bf215546Sopenharmony_ci tx00[c], tx01[c], 1913bf215546Sopenharmony_ci tx02[c], tx03[c], 1914bf215546Sopenharmony_ci tx10[c], tx11[c], 1915bf215546Sopenharmony_ci tx12[c], tx13[c]); 1916bf215546Sopenharmony_ci} 1917bf215546Sopenharmony_ci 1918bf215546Sopenharmony_ci 1919bf215546Sopenharmony_ci/* Calculate level of detail for every fragment, 1920bf215546Sopenharmony_ci * with lambda already computed. 1921bf215546Sopenharmony_ci * Note that lambda has already been biased by global LOD bias. 1922bf215546Sopenharmony_ci * \param biased_lambda per-quad lambda. 1923bf215546Sopenharmony_ci * \param lod_in per-fragment lod_bias or explicit_lod. 1924bf215546Sopenharmony_ci * \param lod returns the per-fragment lod. 1925bf215546Sopenharmony_ci */ 1926bf215546Sopenharmony_cistatic inline void 1927bf215546Sopenharmony_cicompute_lod(const struct pipe_sampler_state *sampler, 1928bf215546Sopenharmony_ci enum tgsi_sampler_control control, 1929bf215546Sopenharmony_ci const float biased_lambda, 1930bf215546Sopenharmony_ci const float lod_in[TGSI_QUAD_SIZE], 1931bf215546Sopenharmony_ci float lod[TGSI_QUAD_SIZE]) 1932bf215546Sopenharmony_ci{ 1933bf215546Sopenharmony_ci const float min_lod = sampler->min_lod; 1934bf215546Sopenharmony_ci const float max_lod = sampler->max_lod; 1935bf215546Sopenharmony_ci uint i; 1936bf215546Sopenharmony_ci 1937bf215546Sopenharmony_ci switch (control) { 1938bf215546Sopenharmony_ci case TGSI_SAMPLER_LOD_NONE: 1939bf215546Sopenharmony_ci case TGSI_SAMPLER_LOD_ZERO: 1940bf215546Sopenharmony_ci lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(biased_lambda, min_lod, max_lod); 1941bf215546Sopenharmony_ci break; 1942bf215546Sopenharmony_ci case TGSI_SAMPLER_DERIVS_EXPLICIT: 1943bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) 1944bf215546Sopenharmony_ci lod[i] = lod_in[i]; 1945bf215546Sopenharmony_ci break; 1946bf215546Sopenharmony_ci case TGSI_SAMPLER_LOD_BIAS: 1947bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) { 1948bf215546Sopenharmony_ci lod[i] = biased_lambda + lod_in[i]; 1949bf215546Sopenharmony_ci lod[i] = CLAMP(lod[i], min_lod, max_lod); 1950bf215546Sopenharmony_ci } 1951bf215546Sopenharmony_ci break; 1952bf215546Sopenharmony_ci case TGSI_SAMPLER_LOD_EXPLICIT: 1953bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) { 1954bf215546Sopenharmony_ci lod[i] = CLAMP(lod_in[i], min_lod, max_lod); 1955bf215546Sopenharmony_ci } 1956bf215546Sopenharmony_ci break; 1957bf215546Sopenharmony_ci default: 1958bf215546Sopenharmony_ci assert(0); 1959bf215546Sopenharmony_ci lod[0] = lod[1] = lod[2] = lod[3] = 0.0f; 1960bf215546Sopenharmony_ci } 1961bf215546Sopenharmony_ci} 1962bf215546Sopenharmony_ci 1963bf215546Sopenharmony_ci 1964bf215546Sopenharmony_ci/* Calculate level of detail for every fragment. The computed value is not 1965bf215546Sopenharmony_ci * clamped to lod_min and lod_max. 1966bf215546Sopenharmony_ci * \param lod_in per-fragment lod_bias or explicit_lod. 1967bf215546Sopenharmony_ci * \param lod results per-fragment lod. 1968bf215546Sopenharmony_ci */ 1969bf215546Sopenharmony_cistatic inline void 1970bf215546Sopenharmony_cicompute_lambda_lod_unclamped(const struct sp_sampler_view *sp_sview, 1971bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 1972bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 1973bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 1974bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 1975bf215546Sopenharmony_ci const float derivs[3][2][TGSI_QUAD_SIZE], 1976bf215546Sopenharmony_ci const float lod_in[TGSI_QUAD_SIZE], 1977bf215546Sopenharmony_ci enum tgsi_sampler_control control, 1978bf215546Sopenharmony_ci float lod[TGSI_QUAD_SIZE]) 1979bf215546Sopenharmony_ci{ 1980bf215546Sopenharmony_ci const struct pipe_sampler_state *sampler = &sp_samp->base; 1981bf215546Sopenharmony_ci const float lod_bias = sampler->lod_bias; 1982bf215546Sopenharmony_ci float lambda; 1983bf215546Sopenharmony_ci uint i; 1984bf215546Sopenharmony_ci 1985bf215546Sopenharmony_ci switch (control) { 1986bf215546Sopenharmony_ci case TGSI_SAMPLER_LOD_NONE: 1987bf215546Sopenharmony_ci lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias; 1988bf215546Sopenharmony_ci lod[0] = lod[1] = lod[2] = lod[3] = lambda; 1989bf215546Sopenharmony_ci break; 1990bf215546Sopenharmony_ci case TGSI_SAMPLER_DERIVS_EXPLICIT: 1991bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) 1992bf215546Sopenharmony_ci lod[i] = sp_sview->compute_lambda_from_grad(sp_sview, derivs, i); 1993bf215546Sopenharmony_ci break; 1994bf215546Sopenharmony_ci case TGSI_SAMPLER_LOD_BIAS: 1995bf215546Sopenharmony_ci lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias; 1996bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) { 1997bf215546Sopenharmony_ci lod[i] = lambda + lod_in[i]; 1998bf215546Sopenharmony_ci } 1999bf215546Sopenharmony_ci break; 2000bf215546Sopenharmony_ci case TGSI_SAMPLER_LOD_EXPLICIT: 2001bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) { 2002bf215546Sopenharmony_ci lod[i] = lod_in[i] + lod_bias; 2003bf215546Sopenharmony_ci } 2004bf215546Sopenharmony_ci break; 2005bf215546Sopenharmony_ci case TGSI_SAMPLER_LOD_ZERO: 2006bf215546Sopenharmony_ci case TGSI_SAMPLER_GATHER: 2007bf215546Sopenharmony_ci lod[0] = lod[1] = lod[2] = lod[3] = lod_bias; 2008bf215546Sopenharmony_ci break; 2009bf215546Sopenharmony_ci default: 2010bf215546Sopenharmony_ci assert(0); 2011bf215546Sopenharmony_ci lod[0] = lod[1] = lod[2] = lod[3] = 0.0f; 2012bf215546Sopenharmony_ci } 2013bf215546Sopenharmony_ci} 2014bf215546Sopenharmony_ci 2015bf215546Sopenharmony_ci/* Calculate level of detail for every fragment. 2016bf215546Sopenharmony_ci * \param lod_in per-fragment lod_bias or explicit_lod. 2017bf215546Sopenharmony_ci * \param lod results per-fragment lod. 2018bf215546Sopenharmony_ci */ 2019bf215546Sopenharmony_cistatic inline void 2020bf215546Sopenharmony_cicompute_lambda_lod(const struct sp_sampler_view *sp_sview, 2021bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2022bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 2023bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 2024bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 2025bf215546Sopenharmony_ci float derivs[3][2][TGSI_QUAD_SIZE], 2026bf215546Sopenharmony_ci const float lod_in[TGSI_QUAD_SIZE], 2027bf215546Sopenharmony_ci enum tgsi_sampler_control control, 2028bf215546Sopenharmony_ci float lod[TGSI_QUAD_SIZE]) 2029bf215546Sopenharmony_ci{ 2030bf215546Sopenharmony_ci const struct pipe_sampler_state *sampler = &sp_samp->base; 2031bf215546Sopenharmony_ci const float min_lod = sampler->min_lod; 2032bf215546Sopenharmony_ci const float max_lod = sampler->max_lod; 2033bf215546Sopenharmony_ci int i; 2034bf215546Sopenharmony_ci 2035bf215546Sopenharmony_ci compute_lambda_lod_unclamped(sp_sview, sp_samp, 2036bf215546Sopenharmony_ci s, t, p, derivs, lod_in, control, lod); 2037bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) { 2038bf215546Sopenharmony_ci lod[i] = CLAMP(lod[i], min_lod, max_lod); 2039bf215546Sopenharmony_ci } 2040bf215546Sopenharmony_ci} 2041bf215546Sopenharmony_ci 2042bf215546Sopenharmony_cistatic inline unsigned 2043bf215546Sopenharmony_ciget_gather_component(const float lod_in[TGSI_QUAD_SIZE]) 2044bf215546Sopenharmony_ci{ 2045bf215546Sopenharmony_ci /* gather component is stored in lod_in slot as unsigned */ 2046bf215546Sopenharmony_ci return (*(unsigned int *)lod_in) & 0x3; 2047bf215546Sopenharmony_ci} 2048bf215546Sopenharmony_ci 2049bf215546Sopenharmony_ci/** 2050bf215546Sopenharmony_ci * Clamps given lod to both lod limits and mip level limits. Clamping to the 2051bf215546Sopenharmony_ci * latter limits is done so that lod is relative to the first (base) level. 2052bf215546Sopenharmony_ci */ 2053bf215546Sopenharmony_cistatic void 2054bf215546Sopenharmony_ciclamp_lod(const struct sp_sampler_view *sp_sview, 2055bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2056bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2057bf215546Sopenharmony_ci float clamped[TGSI_QUAD_SIZE]) 2058bf215546Sopenharmony_ci{ 2059bf215546Sopenharmony_ci const float min_lod = sp_samp->base.min_lod; 2060bf215546Sopenharmony_ci const float max_lod = sp_samp->base.max_lod; 2061bf215546Sopenharmony_ci const float min_level = sp_sview->base.u.tex.first_level; 2062bf215546Sopenharmony_ci const float max_level = sp_sview->base.u.tex.last_level; 2063bf215546Sopenharmony_ci int i; 2064bf215546Sopenharmony_ci 2065bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) { 2066bf215546Sopenharmony_ci float cl = lod[i]; 2067bf215546Sopenharmony_ci 2068bf215546Sopenharmony_ci cl = CLAMP(cl, min_lod, max_lod); 2069bf215546Sopenharmony_ci cl = CLAMP(cl, 0, max_level - min_level); 2070bf215546Sopenharmony_ci clamped[i] = cl; 2071bf215546Sopenharmony_ci } 2072bf215546Sopenharmony_ci} 2073bf215546Sopenharmony_ci 2074bf215546Sopenharmony_ci/** 2075bf215546Sopenharmony_ci * Get mip level relative to base level for linear mip filter 2076bf215546Sopenharmony_ci */ 2077bf215546Sopenharmony_cistatic void 2078bf215546Sopenharmony_cimip_rel_level_linear(const struct sp_sampler_view *sp_sview, 2079bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2080bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2081bf215546Sopenharmony_ci float level[TGSI_QUAD_SIZE]) 2082bf215546Sopenharmony_ci{ 2083bf215546Sopenharmony_ci clamp_lod(sp_sview, sp_samp, lod, level); 2084bf215546Sopenharmony_ci} 2085bf215546Sopenharmony_ci 2086bf215546Sopenharmony_cistatic void 2087bf215546Sopenharmony_cimip_filter_linear(const struct sp_sampler_view *sp_sview, 2088bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2089bf215546Sopenharmony_ci img_filter_func min_filter, 2090bf215546Sopenharmony_ci img_filter_func mag_filter, 2091bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 2092bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 2093bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 2094bf215546Sopenharmony_ci int gather_comp, 2095bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2096bf215546Sopenharmony_ci const struct filter_args *filt_args, 2097bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 2098bf215546Sopenharmony_ci{ 2099bf215546Sopenharmony_ci const struct pipe_sampler_view *psview = &sp_sview->base; 2100bf215546Sopenharmony_ci int j; 2101bf215546Sopenharmony_ci struct img_filter_args args; 2102bf215546Sopenharmony_ci 2103bf215546Sopenharmony_ci args.offset = filt_args->offset; 2104bf215546Sopenharmony_ci args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER; 2105bf215546Sopenharmony_ci args.gather_comp = gather_comp; 2106bf215546Sopenharmony_ci 2107bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2108bf215546Sopenharmony_ci const int level0 = psview->u.tex.first_level + (int)lod[j]; 2109bf215546Sopenharmony_ci 2110bf215546Sopenharmony_ci args.s = s[j]; 2111bf215546Sopenharmony_ci args.t = t[j]; 2112bf215546Sopenharmony_ci args.p = p[j]; 2113bf215546Sopenharmony_ci args.face_id = filt_args->faces[j]; 2114bf215546Sopenharmony_ci 2115bf215546Sopenharmony_ci if (lod[j] <= 0.0 && !args.gather_only) { 2116bf215546Sopenharmony_ci args.level = psview->u.tex.first_level; 2117bf215546Sopenharmony_ci mag_filter(sp_sview, sp_samp, &args, &rgba[0][j]); 2118bf215546Sopenharmony_ci } 2119bf215546Sopenharmony_ci else if (level0 >= (int) psview->u.tex.last_level) { 2120bf215546Sopenharmony_ci args.level = psview->u.tex.last_level; 2121bf215546Sopenharmony_ci min_filter(sp_sview, sp_samp, &args, &rgba[0][j]); 2122bf215546Sopenharmony_ci } 2123bf215546Sopenharmony_ci else { 2124bf215546Sopenharmony_ci float levelBlend = frac(lod[j]); 2125bf215546Sopenharmony_ci float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]; 2126bf215546Sopenharmony_ci int c; 2127bf215546Sopenharmony_ci 2128bf215546Sopenharmony_ci args.level = level0; 2129bf215546Sopenharmony_ci min_filter(sp_sview, sp_samp, &args, &rgbax[0][0]); 2130bf215546Sopenharmony_ci args.level = level0+1; 2131bf215546Sopenharmony_ci min_filter(sp_sview, sp_samp, &args, &rgbax[0][1]); 2132bf215546Sopenharmony_ci 2133bf215546Sopenharmony_ci for (c = 0; c < 4; c++) { 2134bf215546Sopenharmony_ci rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]); 2135bf215546Sopenharmony_ci } 2136bf215546Sopenharmony_ci } 2137bf215546Sopenharmony_ci } 2138bf215546Sopenharmony_ci 2139bf215546Sopenharmony_ci if (DEBUG_TEX) { 2140bf215546Sopenharmony_ci print_sample_4(__FUNCTION__, rgba); 2141bf215546Sopenharmony_ci } 2142bf215546Sopenharmony_ci} 2143bf215546Sopenharmony_ci 2144bf215546Sopenharmony_ci 2145bf215546Sopenharmony_ci/** 2146bf215546Sopenharmony_ci * Get mip level relative to base level for nearest mip filter 2147bf215546Sopenharmony_ci */ 2148bf215546Sopenharmony_cistatic void 2149bf215546Sopenharmony_cimip_rel_level_nearest(const struct sp_sampler_view *sp_sview, 2150bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2151bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2152bf215546Sopenharmony_ci float level[TGSI_QUAD_SIZE]) 2153bf215546Sopenharmony_ci{ 2154bf215546Sopenharmony_ci int j; 2155bf215546Sopenharmony_ci 2156bf215546Sopenharmony_ci clamp_lod(sp_sview, sp_samp, lod, level); 2157bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) 2158bf215546Sopenharmony_ci /* TODO: It should rather be: 2159bf215546Sopenharmony_ci * level[j] = ceil(level[j] + 0.5F) - 1.0F; 2160bf215546Sopenharmony_ci */ 2161bf215546Sopenharmony_ci level[j] = (int)(level[j] + 0.5F); 2162bf215546Sopenharmony_ci} 2163bf215546Sopenharmony_ci 2164bf215546Sopenharmony_ci/** 2165bf215546Sopenharmony_ci * Compute nearest mipmap level from texcoords. 2166bf215546Sopenharmony_ci * Then sample the texture level for four elements of a quad. 2167bf215546Sopenharmony_ci * \param c0 the LOD bias factors, or absolute LODs (depending on control) 2168bf215546Sopenharmony_ci */ 2169bf215546Sopenharmony_cistatic void 2170bf215546Sopenharmony_cimip_filter_nearest(const struct sp_sampler_view *sp_sview, 2171bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2172bf215546Sopenharmony_ci img_filter_func min_filter, 2173bf215546Sopenharmony_ci img_filter_func mag_filter, 2174bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 2175bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 2176bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 2177bf215546Sopenharmony_ci int gather_component, 2178bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2179bf215546Sopenharmony_ci const struct filter_args *filt_args, 2180bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 2181bf215546Sopenharmony_ci{ 2182bf215546Sopenharmony_ci const struct pipe_sampler_view *psview = &sp_sview->base; 2183bf215546Sopenharmony_ci int j; 2184bf215546Sopenharmony_ci struct img_filter_args args; 2185bf215546Sopenharmony_ci 2186bf215546Sopenharmony_ci args.offset = filt_args->offset; 2187bf215546Sopenharmony_ci args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER; 2188bf215546Sopenharmony_ci args.gather_comp = gather_component; 2189bf215546Sopenharmony_ci 2190bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2191bf215546Sopenharmony_ci args.s = s[j]; 2192bf215546Sopenharmony_ci args.t = t[j]; 2193bf215546Sopenharmony_ci args.p = p[j]; 2194bf215546Sopenharmony_ci args.face_id = filt_args->faces[j]; 2195bf215546Sopenharmony_ci 2196bf215546Sopenharmony_ci if (lod[j] <= 0.0f && !args.gather_only) { 2197bf215546Sopenharmony_ci args.level = psview->u.tex.first_level; 2198bf215546Sopenharmony_ci mag_filter(sp_sview, sp_samp, &args, &rgba[0][j]); 2199bf215546Sopenharmony_ci } else { 2200bf215546Sopenharmony_ci const int level = psview->u.tex.first_level + (int)(lod[j] + 0.5F); 2201bf215546Sopenharmony_ci args.level = MIN2(level, (int)psview->u.tex.last_level); 2202bf215546Sopenharmony_ci min_filter(sp_sview, sp_samp, &args, &rgba[0][j]); 2203bf215546Sopenharmony_ci } 2204bf215546Sopenharmony_ci } 2205bf215546Sopenharmony_ci 2206bf215546Sopenharmony_ci if (DEBUG_TEX) { 2207bf215546Sopenharmony_ci print_sample_4(__FUNCTION__, rgba); 2208bf215546Sopenharmony_ci } 2209bf215546Sopenharmony_ci} 2210bf215546Sopenharmony_ci 2211bf215546Sopenharmony_ci 2212bf215546Sopenharmony_ci/** 2213bf215546Sopenharmony_ci * Get mip level relative to base level for none mip filter 2214bf215546Sopenharmony_ci */ 2215bf215546Sopenharmony_cistatic void 2216bf215546Sopenharmony_cimip_rel_level_none(const struct sp_sampler_view *sp_sview, 2217bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2218bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2219bf215546Sopenharmony_ci float level[TGSI_QUAD_SIZE]) 2220bf215546Sopenharmony_ci{ 2221bf215546Sopenharmony_ci int j; 2222bf215546Sopenharmony_ci 2223bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2224bf215546Sopenharmony_ci level[j] = 0; 2225bf215546Sopenharmony_ci } 2226bf215546Sopenharmony_ci} 2227bf215546Sopenharmony_ci 2228bf215546Sopenharmony_cistatic void 2229bf215546Sopenharmony_cimip_filter_none(const struct sp_sampler_view *sp_sview, 2230bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2231bf215546Sopenharmony_ci img_filter_func min_filter, 2232bf215546Sopenharmony_ci img_filter_func mag_filter, 2233bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 2234bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 2235bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 2236bf215546Sopenharmony_ci int gather_component, 2237bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2238bf215546Sopenharmony_ci const struct filter_args *filt_args, 2239bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 2240bf215546Sopenharmony_ci{ 2241bf215546Sopenharmony_ci int j; 2242bf215546Sopenharmony_ci struct img_filter_args args; 2243bf215546Sopenharmony_ci 2244bf215546Sopenharmony_ci args.level = sp_sview->base.u.tex.first_level; 2245bf215546Sopenharmony_ci args.offset = filt_args->offset; 2246bf215546Sopenharmony_ci args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER; 2247bf215546Sopenharmony_ci args.gather_comp = gather_component; 2248bf215546Sopenharmony_ci 2249bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2250bf215546Sopenharmony_ci args.s = s[j]; 2251bf215546Sopenharmony_ci args.t = t[j]; 2252bf215546Sopenharmony_ci args.p = p[j]; 2253bf215546Sopenharmony_ci args.face_id = filt_args->faces[j]; 2254bf215546Sopenharmony_ci if (lod[j] <= 0.0f && !args.gather_only) { 2255bf215546Sopenharmony_ci mag_filter(sp_sview, sp_samp, &args, &rgba[0][j]); 2256bf215546Sopenharmony_ci } 2257bf215546Sopenharmony_ci else { 2258bf215546Sopenharmony_ci min_filter(sp_sview, sp_samp, &args, &rgba[0][j]); 2259bf215546Sopenharmony_ci } 2260bf215546Sopenharmony_ci } 2261bf215546Sopenharmony_ci} 2262bf215546Sopenharmony_ci 2263bf215546Sopenharmony_ci 2264bf215546Sopenharmony_ci/** 2265bf215546Sopenharmony_ci * Get mip level relative to base level for none mip filter 2266bf215546Sopenharmony_ci */ 2267bf215546Sopenharmony_cistatic void 2268bf215546Sopenharmony_cimip_rel_level_none_no_filter_select(const struct sp_sampler_view *sp_sview, 2269bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2270bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2271bf215546Sopenharmony_ci float level[TGSI_QUAD_SIZE]) 2272bf215546Sopenharmony_ci{ 2273bf215546Sopenharmony_ci mip_rel_level_none(sp_sview, sp_samp, lod, level); 2274bf215546Sopenharmony_ci} 2275bf215546Sopenharmony_ci 2276bf215546Sopenharmony_cistatic void 2277bf215546Sopenharmony_cimip_filter_none_no_filter_select(const struct sp_sampler_view *sp_sview, 2278bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2279bf215546Sopenharmony_ci img_filter_func min_filter, 2280bf215546Sopenharmony_ci img_filter_func mag_filter, 2281bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 2282bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 2283bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 2284bf215546Sopenharmony_ci int gather_comp, 2285bf215546Sopenharmony_ci const float lod_in[TGSI_QUAD_SIZE], 2286bf215546Sopenharmony_ci const struct filter_args *filt_args, 2287bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 2288bf215546Sopenharmony_ci{ 2289bf215546Sopenharmony_ci int j; 2290bf215546Sopenharmony_ci struct img_filter_args args; 2291bf215546Sopenharmony_ci args.level = sp_sview->base.u.tex.first_level; 2292bf215546Sopenharmony_ci args.offset = filt_args->offset; 2293bf215546Sopenharmony_ci args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER; 2294bf215546Sopenharmony_ci args.gather_comp = gather_comp; 2295bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2296bf215546Sopenharmony_ci args.s = s[j]; 2297bf215546Sopenharmony_ci args.t = t[j]; 2298bf215546Sopenharmony_ci args.p = p[j]; 2299bf215546Sopenharmony_ci args.face_id = filt_args->faces[j]; 2300bf215546Sopenharmony_ci mag_filter(sp_sview, sp_samp, &args, &rgba[0][j]); 2301bf215546Sopenharmony_ci } 2302bf215546Sopenharmony_ci} 2303bf215546Sopenharmony_ci 2304bf215546Sopenharmony_ci 2305bf215546Sopenharmony_ci/* For anisotropic filtering */ 2306bf215546Sopenharmony_ci#define WEIGHT_LUT_SIZE 1024 2307bf215546Sopenharmony_ci 2308bf215546Sopenharmony_cistatic const float *weightLut = NULL; 2309bf215546Sopenharmony_ci 2310bf215546Sopenharmony_ci/** 2311bf215546Sopenharmony_ci * Creates the look-up table used to speed-up EWA sampling 2312bf215546Sopenharmony_ci */ 2313bf215546Sopenharmony_cistatic void 2314bf215546Sopenharmony_cicreate_filter_table(void) 2315bf215546Sopenharmony_ci{ 2316bf215546Sopenharmony_ci unsigned i; 2317bf215546Sopenharmony_ci if (!weightLut) { 2318bf215546Sopenharmony_ci float *lut = (float *) MALLOC(WEIGHT_LUT_SIZE * sizeof(float)); 2319bf215546Sopenharmony_ci 2320bf215546Sopenharmony_ci for (i = 0; i < WEIGHT_LUT_SIZE; ++i) { 2321bf215546Sopenharmony_ci const float alpha = 2; 2322bf215546Sopenharmony_ci const float r2 = (float) i / (float) (WEIGHT_LUT_SIZE - 1); 2323bf215546Sopenharmony_ci const float weight = (float) expf(-alpha * r2); 2324bf215546Sopenharmony_ci lut[i] = weight; 2325bf215546Sopenharmony_ci } 2326bf215546Sopenharmony_ci weightLut = lut; 2327bf215546Sopenharmony_ci } 2328bf215546Sopenharmony_ci} 2329bf215546Sopenharmony_ci 2330bf215546Sopenharmony_ci 2331bf215546Sopenharmony_ci/** 2332bf215546Sopenharmony_ci * Elliptical weighted average (EWA) filter for producing high quality 2333bf215546Sopenharmony_ci * anisotropic filtered results. 2334bf215546Sopenharmony_ci * Based on the Higher Quality Elliptical Weighted Average Filter 2335bf215546Sopenharmony_ci * published by Paul S. Heckbert in his Master's Thesis 2336bf215546Sopenharmony_ci * "Fundamentals of Texture Mapping and Image Warping" (1989) 2337bf215546Sopenharmony_ci */ 2338bf215546Sopenharmony_cistatic void 2339bf215546Sopenharmony_ciimg_filter_2d_ewa(const struct sp_sampler_view *sp_sview, 2340bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2341bf215546Sopenharmony_ci img_filter_func min_filter, 2342bf215546Sopenharmony_ci img_filter_func mag_filter, 2343bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 2344bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 2345bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 2346bf215546Sopenharmony_ci const uint faces[TGSI_QUAD_SIZE], 2347bf215546Sopenharmony_ci const int8_t *offset, 2348bf215546Sopenharmony_ci unsigned level, 2349bf215546Sopenharmony_ci const float dudx, const float dvdx, 2350bf215546Sopenharmony_ci const float dudy, const float dvdy, 2351bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 2352bf215546Sopenharmony_ci{ 2353bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 2354bf215546Sopenharmony_ci 2355bf215546Sopenharmony_ci // ??? Won't the image filters blow up if level is negative? 2356bf215546Sopenharmony_ci const unsigned level0 = level > 0 ? level : 0; 2357bf215546Sopenharmony_ci const float scaling = 1.0f / (1 << level0); 2358bf215546Sopenharmony_ci const int width = u_minify(texture->width0, level0); 2359bf215546Sopenharmony_ci const int height = u_minify(texture->height0, level0); 2360bf215546Sopenharmony_ci struct img_filter_args args; 2361bf215546Sopenharmony_ci const float ux = dudx * scaling; 2362bf215546Sopenharmony_ci const float vx = dvdx * scaling; 2363bf215546Sopenharmony_ci const float uy = dudy * scaling; 2364bf215546Sopenharmony_ci const float vy = dvdy * scaling; 2365bf215546Sopenharmony_ci 2366bf215546Sopenharmony_ci /* compute ellipse coefficients to bound the region: 2367bf215546Sopenharmony_ci * A*x*x + B*x*y + C*y*y = F. 2368bf215546Sopenharmony_ci */ 2369bf215546Sopenharmony_ci float A = vx*vx+vy*vy+1; 2370bf215546Sopenharmony_ci float B = -2*(ux*vx+uy*vy); 2371bf215546Sopenharmony_ci float C = ux*ux+uy*uy+1; 2372bf215546Sopenharmony_ci float F = A*C-B*B/4.0f; 2373bf215546Sopenharmony_ci 2374bf215546Sopenharmony_ci /* check if it is an ellipse */ 2375bf215546Sopenharmony_ci /* assert(F > 0.0); */ 2376bf215546Sopenharmony_ci 2377bf215546Sopenharmony_ci /* Compute the ellipse's (u,v) bounding box in texture space */ 2378bf215546Sopenharmony_ci const float d = -B*B+4.0f*C*A; 2379bf215546Sopenharmony_ci const float box_u = 2.0f / d * sqrtf(d*C*F); /* box_u -> half of bbox with */ 2380bf215546Sopenharmony_ci const float box_v = 2.0f / d * sqrtf(A*d*F); /* box_v -> half of bbox height */ 2381bf215546Sopenharmony_ci 2382bf215546Sopenharmony_ci float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]; 2383bf215546Sopenharmony_ci float s_buffer[TGSI_QUAD_SIZE]; 2384bf215546Sopenharmony_ci float t_buffer[TGSI_QUAD_SIZE]; 2385bf215546Sopenharmony_ci float weight_buffer[TGSI_QUAD_SIZE]; 2386bf215546Sopenharmony_ci int j; 2387bf215546Sopenharmony_ci 2388bf215546Sopenharmony_ci /* Scale ellipse formula to directly index the Filter Lookup Table. 2389bf215546Sopenharmony_ci * i.e. scale so that F = WEIGHT_LUT_SIZE-1 2390bf215546Sopenharmony_ci */ 2391bf215546Sopenharmony_ci const double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F; 2392bf215546Sopenharmony_ci A *= formScale; 2393bf215546Sopenharmony_ci B *= formScale; 2394bf215546Sopenharmony_ci C *= formScale; 2395bf215546Sopenharmony_ci /* F *= formScale; */ /* no need to scale F as we don't use it below here */ 2396bf215546Sopenharmony_ci 2397bf215546Sopenharmony_ci /* For each quad, the du and dx values are the same and so the ellipse is 2398bf215546Sopenharmony_ci * also the same. Note that texel/image access can only be performed using 2399bf215546Sopenharmony_ci * a quad, i.e. it is not possible to get the pixel value for a single 2400bf215546Sopenharmony_ci * tex coord. In order to have a better performance, the access is buffered 2401bf215546Sopenharmony_ci * using the s_buffer/t_buffer and weight_buffer. Only when the buffer is 2402bf215546Sopenharmony_ci * full, then the pixel values are read from the image. 2403bf215546Sopenharmony_ci */ 2404bf215546Sopenharmony_ci const float ddq = 2 * A; 2405bf215546Sopenharmony_ci 2406bf215546Sopenharmony_ci args.level = level; 2407bf215546Sopenharmony_ci args.offset = offset; 2408bf215546Sopenharmony_ci 2409bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2410bf215546Sopenharmony_ci /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse 2411bf215546Sopenharmony_ci * and incrementally update the value of Ax^2+Bxy*Cy^2; when this 2412bf215546Sopenharmony_ci * value, q, is less than F, we're inside the ellipse 2413bf215546Sopenharmony_ci */ 2414bf215546Sopenharmony_ci const float tex_u = -0.5F + s[j] * texture->width0 * scaling; 2415bf215546Sopenharmony_ci const float tex_v = -0.5F + t[j] * texture->height0 * scaling; 2416bf215546Sopenharmony_ci 2417bf215546Sopenharmony_ci const int u0 = (int) floorf(tex_u - box_u); 2418bf215546Sopenharmony_ci const int u1 = (int) ceilf(tex_u + box_u); 2419bf215546Sopenharmony_ci const int v0 = (int) floorf(tex_v - box_v); 2420bf215546Sopenharmony_ci const int v1 = (int) ceilf(tex_v + box_v); 2421bf215546Sopenharmony_ci const float U = u0 - tex_u; 2422bf215546Sopenharmony_ci 2423bf215546Sopenharmony_ci float num[4] = {0.0F, 0.0F, 0.0F, 0.0F}; 2424bf215546Sopenharmony_ci unsigned buffer_next = 0; 2425bf215546Sopenharmony_ci float den = 0; 2426bf215546Sopenharmony_ci int v; 2427bf215546Sopenharmony_ci args.face_id = faces[j]; 2428bf215546Sopenharmony_ci 2429bf215546Sopenharmony_ci for (v = v0; v <= v1; ++v) { 2430bf215546Sopenharmony_ci const float V = v - tex_v; 2431bf215546Sopenharmony_ci float dq = A * (2 * U + 1) + B * V; 2432bf215546Sopenharmony_ci float q = (C * V + B * U) * V + A * U * U; 2433bf215546Sopenharmony_ci 2434bf215546Sopenharmony_ci int u; 2435bf215546Sopenharmony_ci for (u = u0; u <= u1; ++u) { 2436bf215546Sopenharmony_ci /* Note that the ellipse has been pre-scaled so F = 2437bf215546Sopenharmony_ci * WEIGHT_LUT_SIZE - 1 2438bf215546Sopenharmony_ci */ 2439bf215546Sopenharmony_ci if (q < WEIGHT_LUT_SIZE) { 2440bf215546Sopenharmony_ci /* as a LUT is used, q must never be negative; 2441bf215546Sopenharmony_ci * should not happen, though 2442bf215546Sopenharmony_ci */ 2443bf215546Sopenharmony_ci const int qClamped = q >= 0.0F ? q : 0; 2444bf215546Sopenharmony_ci const float weight = weightLut[qClamped]; 2445bf215546Sopenharmony_ci 2446bf215546Sopenharmony_ci weight_buffer[buffer_next] = weight; 2447bf215546Sopenharmony_ci s_buffer[buffer_next] = u / ((float) width); 2448bf215546Sopenharmony_ci t_buffer[buffer_next] = v / ((float) height); 2449bf215546Sopenharmony_ci 2450bf215546Sopenharmony_ci buffer_next++; 2451bf215546Sopenharmony_ci if (buffer_next == TGSI_QUAD_SIZE) { 2452bf215546Sopenharmony_ci /* 4 texel coords are in the buffer -> read it now */ 2453bf215546Sopenharmony_ci unsigned jj; 2454bf215546Sopenharmony_ci /* it is assumed that samp->min_img_filter is set to 2455bf215546Sopenharmony_ci * img_filter_2d_nearest or one of the 2456bf215546Sopenharmony_ci * accelerated img_filter_2d_nearest_XXX functions. 2457bf215546Sopenharmony_ci */ 2458bf215546Sopenharmony_ci for (jj = 0; jj < buffer_next; jj++) { 2459bf215546Sopenharmony_ci args.s = s_buffer[jj]; 2460bf215546Sopenharmony_ci args.t = t_buffer[jj]; 2461bf215546Sopenharmony_ci args.p = p[jj]; 2462bf215546Sopenharmony_ci min_filter(sp_sview, sp_samp, &args, &rgba_temp[0][jj]); 2463bf215546Sopenharmony_ci num[0] += weight_buffer[jj] * rgba_temp[0][jj]; 2464bf215546Sopenharmony_ci num[1] += weight_buffer[jj] * rgba_temp[1][jj]; 2465bf215546Sopenharmony_ci num[2] += weight_buffer[jj] * rgba_temp[2][jj]; 2466bf215546Sopenharmony_ci num[3] += weight_buffer[jj] * rgba_temp[3][jj]; 2467bf215546Sopenharmony_ci } 2468bf215546Sopenharmony_ci 2469bf215546Sopenharmony_ci buffer_next = 0; 2470bf215546Sopenharmony_ci } 2471bf215546Sopenharmony_ci 2472bf215546Sopenharmony_ci den += weight; 2473bf215546Sopenharmony_ci } 2474bf215546Sopenharmony_ci q += dq; 2475bf215546Sopenharmony_ci dq += ddq; 2476bf215546Sopenharmony_ci } 2477bf215546Sopenharmony_ci } 2478bf215546Sopenharmony_ci 2479bf215546Sopenharmony_ci /* if the tex coord buffer contains unread values, we will read 2480bf215546Sopenharmony_ci * them now. 2481bf215546Sopenharmony_ci */ 2482bf215546Sopenharmony_ci if (buffer_next > 0) { 2483bf215546Sopenharmony_ci unsigned jj; 2484bf215546Sopenharmony_ci /* it is assumed that samp->min_img_filter is set to 2485bf215546Sopenharmony_ci * img_filter_2d_nearest or one of the 2486bf215546Sopenharmony_ci * accelerated img_filter_2d_nearest_XXX functions. 2487bf215546Sopenharmony_ci */ 2488bf215546Sopenharmony_ci for (jj = 0; jj < buffer_next; jj++) { 2489bf215546Sopenharmony_ci args.s = s_buffer[jj]; 2490bf215546Sopenharmony_ci args.t = t_buffer[jj]; 2491bf215546Sopenharmony_ci args.p = p[jj]; 2492bf215546Sopenharmony_ci min_filter(sp_sview, sp_samp, &args, &rgba_temp[0][jj]); 2493bf215546Sopenharmony_ci num[0] += weight_buffer[jj] * rgba_temp[0][jj]; 2494bf215546Sopenharmony_ci num[1] += weight_buffer[jj] * rgba_temp[1][jj]; 2495bf215546Sopenharmony_ci num[2] += weight_buffer[jj] * rgba_temp[2][jj]; 2496bf215546Sopenharmony_ci num[3] += weight_buffer[jj] * rgba_temp[3][jj]; 2497bf215546Sopenharmony_ci } 2498bf215546Sopenharmony_ci } 2499bf215546Sopenharmony_ci 2500bf215546Sopenharmony_ci if (den <= 0.0F) { 2501bf215546Sopenharmony_ci /* Reaching this place would mean that no pixels intersected 2502bf215546Sopenharmony_ci * the ellipse. This should never happen because the filter 2503bf215546Sopenharmony_ci * we use always intersects at least one pixel. 2504bf215546Sopenharmony_ci */ 2505bf215546Sopenharmony_ci 2506bf215546Sopenharmony_ci /*rgba[0]=0; 2507bf215546Sopenharmony_ci rgba[1]=0; 2508bf215546Sopenharmony_ci rgba[2]=0; 2509bf215546Sopenharmony_ci rgba[3]=0;*/ 2510bf215546Sopenharmony_ci /* not enough pixels in resampling, resort to direct interpolation */ 2511bf215546Sopenharmony_ci args.s = s[j]; 2512bf215546Sopenharmony_ci args.t = t[j]; 2513bf215546Sopenharmony_ci args.p = p[j]; 2514bf215546Sopenharmony_ci min_filter(sp_sview, sp_samp, &args, &rgba_temp[0][j]); 2515bf215546Sopenharmony_ci den = 1; 2516bf215546Sopenharmony_ci num[0] = rgba_temp[0][j]; 2517bf215546Sopenharmony_ci num[1] = rgba_temp[1][j]; 2518bf215546Sopenharmony_ci num[2] = rgba_temp[2][j]; 2519bf215546Sopenharmony_ci num[3] = rgba_temp[3][j]; 2520bf215546Sopenharmony_ci } 2521bf215546Sopenharmony_ci 2522bf215546Sopenharmony_ci rgba[0][j] = num[0] / den; 2523bf215546Sopenharmony_ci rgba[1][j] = num[1] / den; 2524bf215546Sopenharmony_ci rgba[2][j] = num[2] / den; 2525bf215546Sopenharmony_ci rgba[3][j] = num[3] / den; 2526bf215546Sopenharmony_ci } 2527bf215546Sopenharmony_ci} 2528bf215546Sopenharmony_ci 2529bf215546Sopenharmony_ci 2530bf215546Sopenharmony_ci/** 2531bf215546Sopenharmony_ci * Get mip level relative to base level for linear mip filter 2532bf215546Sopenharmony_ci */ 2533bf215546Sopenharmony_cistatic void 2534bf215546Sopenharmony_cimip_rel_level_linear_aniso(const struct sp_sampler_view *sp_sview, 2535bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2536bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2537bf215546Sopenharmony_ci float level[TGSI_QUAD_SIZE]) 2538bf215546Sopenharmony_ci{ 2539bf215546Sopenharmony_ci mip_rel_level_linear(sp_sview, sp_samp, lod, level); 2540bf215546Sopenharmony_ci} 2541bf215546Sopenharmony_ci 2542bf215546Sopenharmony_ci/** 2543bf215546Sopenharmony_ci * Sample 2D texture using an anisotropic filter. 2544bf215546Sopenharmony_ci */ 2545bf215546Sopenharmony_cistatic void 2546bf215546Sopenharmony_cimip_filter_linear_aniso(const struct sp_sampler_view *sp_sview, 2547bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2548bf215546Sopenharmony_ci img_filter_func min_filter, 2549bf215546Sopenharmony_ci img_filter_func mag_filter, 2550bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 2551bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 2552bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 2553bf215546Sopenharmony_ci UNUSED int gather_comp, 2554bf215546Sopenharmony_ci const float lod_in[TGSI_QUAD_SIZE], 2555bf215546Sopenharmony_ci const struct filter_args *filt_args, 2556bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 2557bf215546Sopenharmony_ci{ 2558bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 2559bf215546Sopenharmony_ci const struct pipe_sampler_view *psview = &sp_sview->base; 2560bf215546Sopenharmony_ci int level0; 2561bf215546Sopenharmony_ci float lambda; 2562bf215546Sopenharmony_ci float lod[TGSI_QUAD_SIZE]; 2563bf215546Sopenharmony_ci 2564bf215546Sopenharmony_ci const float s_to_u = u_minify(texture->width0, psview->u.tex.first_level); 2565bf215546Sopenharmony_ci const float t_to_v = u_minify(texture->height0, psview->u.tex.first_level); 2566bf215546Sopenharmony_ci const float dudx = (s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]) * s_to_u; 2567bf215546Sopenharmony_ci const float dudy = (s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]) * s_to_u; 2568bf215546Sopenharmony_ci const float dvdx = (t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]) * t_to_v; 2569bf215546Sopenharmony_ci const float dvdy = (t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]) * t_to_v; 2570bf215546Sopenharmony_ci struct img_filter_args args; 2571bf215546Sopenharmony_ci 2572bf215546Sopenharmony_ci args.offset = filt_args->offset; 2573bf215546Sopenharmony_ci 2574bf215546Sopenharmony_ci if (filt_args->control == TGSI_SAMPLER_LOD_BIAS || 2575bf215546Sopenharmony_ci filt_args->control == TGSI_SAMPLER_LOD_NONE || 2576bf215546Sopenharmony_ci /* XXX FIXME */ 2577bf215546Sopenharmony_ci filt_args->control == TGSI_SAMPLER_DERIVS_EXPLICIT) { 2578bf215546Sopenharmony_ci /* note: instead of working with Px and Py, we will use the 2579bf215546Sopenharmony_ci * squared length instead, to avoid sqrt. 2580bf215546Sopenharmony_ci */ 2581bf215546Sopenharmony_ci const float Px2 = dudx * dudx + dvdx * dvdx; 2582bf215546Sopenharmony_ci const float Py2 = dudy * dudy + dvdy * dvdy; 2583bf215546Sopenharmony_ci 2584bf215546Sopenharmony_ci float Pmax2; 2585bf215546Sopenharmony_ci float Pmin2; 2586bf215546Sopenharmony_ci float e; 2587bf215546Sopenharmony_ci const float maxEccentricity = sp_samp->base.max_anisotropy * sp_samp->base.max_anisotropy; 2588bf215546Sopenharmony_ci 2589bf215546Sopenharmony_ci if (Px2 < Py2) { 2590bf215546Sopenharmony_ci Pmax2 = Py2; 2591bf215546Sopenharmony_ci Pmin2 = Px2; 2592bf215546Sopenharmony_ci } 2593bf215546Sopenharmony_ci else { 2594bf215546Sopenharmony_ci Pmax2 = Px2; 2595bf215546Sopenharmony_ci Pmin2 = Py2; 2596bf215546Sopenharmony_ci } 2597bf215546Sopenharmony_ci 2598bf215546Sopenharmony_ci /* if the eccentricity of the ellipse is too big, scale up the shorter 2599bf215546Sopenharmony_ci * of the two vectors to limit the maximum amount of work per pixel 2600bf215546Sopenharmony_ci */ 2601bf215546Sopenharmony_ci e = Pmax2 / Pmin2; 2602bf215546Sopenharmony_ci if (e > maxEccentricity) { 2603bf215546Sopenharmony_ci /* float s=e / maxEccentricity; 2604bf215546Sopenharmony_ci minor[0] *= s; 2605bf215546Sopenharmony_ci minor[1] *= s; 2606bf215546Sopenharmony_ci Pmin2 *= s; */ 2607bf215546Sopenharmony_ci Pmin2 = Pmax2 / maxEccentricity; 2608bf215546Sopenharmony_ci } 2609bf215546Sopenharmony_ci 2610bf215546Sopenharmony_ci /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid 2611bf215546Sopenharmony_ci * this since 0.5*log(x) = log(sqrt(x)) 2612bf215546Sopenharmony_ci */ 2613bf215546Sopenharmony_ci lambda = 0.5F * util_fast_log2(Pmin2) + sp_samp->base.lod_bias; 2614bf215546Sopenharmony_ci compute_lod(&sp_samp->base, filt_args->control, lambda, lod_in, lod); 2615bf215546Sopenharmony_ci } 2616bf215546Sopenharmony_ci else { 2617bf215546Sopenharmony_ci assert(filt_args->control == TGSI_SAMPLER_LOD_EXPLICIT || 2618bf215546Sopenharmony_ci filt_args->control == TGSI_SAMPLER_LOD_ZERO); 2619bf215546Sopenharmony_ci compute_lod(&sp_samp->base, filt_args->control, sp_samp->base.lod_bias, lod_in, lod); 2620bf215546Sopenharmony_ci } 2621bf215546Sopenharmony_ci 2622bf215546Sopenharmony_ci /* XXX: Take into account all lod values. 2623bf215546Sopenharmony_ci */ 2624bf215546Sopenharmony_ci lambda = lod[0]; 2625bf215546Sopenharmony_ci level0 = psview->u.tex.first_level + (int)lambda; 2626bf215546Sopenharmony_ci 2627bf215546Sopenharmony_ci /* If the ellipse covers the whole image, we can 2628bf215546Sopenharmony_ci * simply return the average of the whole image. 2629bf215546Sopenharmony_ci */ 2630bf215546Sopenharmony_ci if (level0 >= (int) psview->u.tex.last_level) { 2631bf215546Sopenharmony_ci int j; 2632bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2633bf215546Sopenharmony_ci args.s = s[j]; 2634bf215546Sopenharmony_ci args.t = t[j]; 2635bf215546Sopenharmony_ci args.p = p[j]; 2636bf215546Sopenharmony_ci args.level = psview->u.tex.last_level; 2637bf215546Sopenharmony_ci args.face_id = filt_args->faces[j]; 2638bf215546Sopenharmony_ci /* 2639bf215546Sopenharmony_ci * XXX: we overwrote any linear filter with nearest, so this 2640bf215546Sopenharmony_ci * isn't right (albeit if last level is 1x1 and no border it 2641bf215546Sopenharmony_ci * will work just the same). 2642bf215546Sopenharmony_ci */ 2643bf215546Sopenharmony_ci min_filter(sp_sview, sp_samp, &args, &rgba[0][j]); 2644bf215546Sopenharmony_ci } 2645bf215546Sopenharmony_ci } 2646bf215546Sopenharmony_ci else { 2647bf215546Sopenharmony_ci /* don't bother interpolating between multiple LODs; it doesn't 2648bf215546Sopenharmony_ci * seem to be worth the extra running time. 2649bf215546Sopenharmony_ci */ 2650bf215546Sopenharmony_ci img_filter_2d_ewa(sp_sview, sp_samp, min_filter, mag_filter, 2651bf215546Sopenharmony_ci s, t, p, filt_args->faces, filt_args->offset, 2652bf215546Sopenharmony_ci level0, dudx, dvdx, dudy, dvdy, rgba); 2653bf215546Sopenharmony_ci } 2654bf215546Sopenharmony_ci 2655bf215546Sopenharmony_ci if (DEBUG_TEX) { 2656bf215546Sopenharmony_ci print_sample_4(__FUNCTION__, rgba); 2657bf215546Sopenharmony_ci } 2658bf215546Sopenharmony_ci} 2659bf215546Sopenharmony_ci 2660bf215546Sopenharmony_ci/** 2661bf215546Sopenharmony_ci * Get mip level relative to base level for linear mip filter 2662bf215546Sopenharmony_ci */ 2663bf215546Sopenharmony_cistatic void 2664bf215546Sopenharmony_cimip_rel_level_linear_2d_linear_repeat_POT( 2665bf215546Sopenharmony_ci const struct sp_sampler_view *sp_sview, 2666bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2667bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2668bf215546Sopenharmony_ci float level[TGSI_QUAD_SIZE]) 2669bf215546Sopenharmony_ci{ 2670bf215546Sopenharmony_ci mip_rel_level_linear(sp_sview, sp_samp, lod, level); 2671bf215546Sopenharmony_ci} 2672bf215546Sopenharmony_ci 2673bf215546Sopenharmony_ci/** 2674bf215546Sopenharmony_ci * Specialized version of mip_filter_linear with hard-wired calls to 2675bf215546Sopenharmony_ci * 2d lambda calculation and 2d_linear_repeat_POT img filters. 2676bf215546Sopenharmony_ci */ 2677bf215546Sopenharmony_cistatic void 2678bf215546Sopenharmony_cimip_filter_linear_2d_linear_repeat_POT( 2679bf215546Sopenharmony_ci const struct sp_sampler_view *sp_sview, 2680bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2681bf215546Sopenharmony_ci img_filter_func min_filter, 2682bf215546Sopenharmony_ci img_filter_func mag_filter, 2683bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 2684bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 2685bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 2686bf215546Sopenharmony_ci int gather_comp, 2687bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 2688bf215546Sopenharmony_ci const struct filter_args *filt_args, 2689bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 2690bf215546Sopenharmony_ci{ 2691bf215546Sopenharmony_ci const struct pipe_sampler_view *psview = &sp_sview->base; 2692bf215546Sopenharmony_ci int j; 2693bf215546Sopenharmony_ci 2694bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2695bf215546Sopenharmony_ci const int level0 = psview->u.tex.first_level + (int)lod[j]; 2696bf215546Sopenharmony_ci struct img_filter_args args; 2697bf215546Sopenharmony_ci /* Catches both negative and large values of level0: 2698bf215546Sopenharmony_ci */ 2699bf215546Sopenharmony_ci args.s = s[j]; 2700bf215546Sopenharmony_ci args.t = t[j]; 2701bf215546Sopenharmony_ci args.p = p[j]; 2702bf215546Sopenharmony_ci args.face_id = filt_args->faces[j]; 2703bf215546Sopenharmony_ci args.offset = filt_args->offset; 2704bf215546Sopenharmony_ci args.gather_only = filt_args->control == TGSI_SAMPLER_GATHER; 2705bf215546Sopenharmony_ci args.gather_comp = gather_comp; 2706bf215546Sopenharmony_ci if ((unsigned)level0 >= psview->u.tex.last_level) { 2707bf215546Sopenharmony_ci if (level0 < 0) 2708bf215546Sopenharmony_ci args.level = psview->u.tex.first_level; 2709bf215546Sopenharmony_ci else 2710bf215546Sopenharmony_ci args.level = psview->u.tex.last_level; 2711bf215546Sopenharmony_ci img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, &args, 2712bf215546Sopenharmony_ci &rgba[0][j]); 2713bf215546Sopenharmony_ci 2714bf215546Sopenharmony_ci } 2715bf215546Sopenharmony_ci else { 2716bf215546Sopenharmony_ci const float levelBlend = frac(lod[j]); 2717bf215546Sopenharmony_ci float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]; 2718bf215546Sopenharmony_ci int c; 2719bf215546Sopenharmony_ci 2720bf215546Sopenharmony_ci args.level = level0; 2721bf215546Sopenharmony_ci img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, &args, &rgbax[0][0]); 2722bf215546Sopenharmony_ci args.level = level0+1; 2723bf215546Sopenharmony_ci img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, &args, &rgbax[0][1]); 2724bf215546Sopenharmony_ci 2725bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 2726bf215546Sopenharmony_ci rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]); 2727bf215546Sopenharmony_ci } 2728bf215546Sopenharmony_ci } 2729bf215546Sopenharmony_ci 2730bf215546Sopenharmony_ci if (DEBUG_TEX) { 2731bf215546Sopenharmony_ci print_sample_4(__FUNCTION__, rgba); 2732bf215546Sopenharmony_ci } 2733bf215546Sopenharmony_ci} 2734bf215546Sopenharmony_ci 2735bf215546Sopenharmony_cistatic const struct sp_filter_funcs funcs_linear = { 2736bf215546Sopenharmony_ci mip_rel_level_linear, 2737bf215546Sopenharmony_ci mip_filter_linear 2738bf215546Sopenharmony_ci}; 2739bf215546Sopenharmony_ci 2740bf215546Sopenharmony_cistatic const struct sp_filter_funcs funcs_nearest = { 2741bf215546Sopenharmony_ci mip_rel_level_nearest, 2742bf215546Sopenharmony_ci mip_filter_nearest 2743bf215546Sopenharmony_ci}; 2744bf215546Sopenharmony_ci 2745bf215546Sopenharmony_cistatic const struct sp_filter_funcs funcs_none = { 2746bf215546Sopenharmony_ci mip_rel_level_none, 2747bf215546Sopenharmony_ci mip_filter_none 2748bf215546Sopenharmony_ci}; 2749bf215546Sopenharmony_ci 2750bf215546Sopenharmony_cistatic const struct sp_filter_funcs funcs_none_no_filter_select = { 2751bf215546Sopenharmony_ci mip_rel_level_none_no_filter_select, 2752bf215546Sopenharmony_ci mip_filter_none_no_filter_select 2753bf215546Sopenharmony_ci}; 2754bf215546Sopenharmony_ci 2755bf215546Sopenharmony_cistatic const struct sp_filter_funcs funcs_linear_aniso = { 2756bf215546Sopenharmony_ci mip_rel_level_linear_aniso, 2757bf215546Sopenharmony_ci mip_filter_linear_aniso 2758bf215546Sopenharmony_ci}; 2759bf215546Sopenharmony_ci 2760bf215546Sopenharmony_cistatic const struct sp_filter_funcs funcs_linear_2d_linear_repeat_POT = { 2761bf215546Sopenharmony_ci mip_rel_level_linear_2d_linear_repeat_POT, 2762bf215546Sopenharmony_ci mip_filter_linear_2d_linear_repeat_POT 2763bf215546Sopenharmony_ci}; 2764bf215546Sopenharmony_ci 2765bf215546Sopenharmony_ci/** 2766bf215546Sopenharmony_ci * Do shadow/depth comparisons. 2767bf215546Sopenharmony_ci */ 2768bf215546Sopenharmony_cistatic void 2769bf215546Sopenharmony_cisample_compare(const struct sp_sampler_view *sp_sview, 2770bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 2771bf215546Sopenharmony_ci const float c0[TGSI_QUAD_SIZE], 2772bf215546Sopenharmony_ci enum tgsi_sampler_control control, 2773bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 2774bf215546Sopenharmony_ci{ 2775bf215546Sopenharmony_ci const struct pipe_sampler_state *sampler = &sp_samp->base; 2776bf215546Sopenharmony_ci int j, v; 2777bf215546Sopenharmony_ci int k[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]; 2778bf215546Sopenharmony_ci float pc[4]; 2779bf215546Sopenharmony_ci const struct util_format_description *format_desc = 2780bf215546Sopenharmony_ci util_format_description(sp_sview->base.format); 2781bf215546Sopenharmony_ci /* not entirely sure we couldn't end up with non-valid swizzle here */ 2782bf215546Sopenharmony_ci const unsigned chan_type = 2783bf215546Sopenharmony_ci format_desc->swizzle[0] <= PIPE_SWIZZLE_W ? 2784bf215546Sopenharmony_ci format_desc->channel[format_desc->swizzle[0]].type : 2785bf215546Sopenharmony_ci UTIL_FORMAT_TYPE_FLOAT; 2786bf215546Sopenharmony_ci const bool is_gather = (control == TGSI_SAMPLER_GATHER); 2787bf215546Sopenharmony_ci 2788bf215546Sopenharmony_ci /** 2789bf215546Sopenharmony_ci * Compare texcoord 'p' (aka R) against texture value 'rgba[0]' 2790bf215546Sopenharmony_ci * for 2D Array texture we need to use the 'c0' (aka Q). 2791bf215546Sopenharmony_ci * When we sampled the depth texture, the depth value was put into all 2792bf215546Sopenharmony_ci * RGBA channels. We look at the red channel here. 2793bf215546Sopenharmony_ci */ 2794bf215546Sopenharmony_ci 2795bf215546Sopenharmony_ci 2796bf215546Sopenharmony_ci 2797bf215546Sopenharmony_ci if (chan_type != UTIL_FORMAT_TYPE_FLOAT) { 2798bf215546Sopenharmony_ci /* 2799bf215546Sopenharmony_ci * clamping is a result of conversion to texture format, hence 2800bf215546Sopenharmony_ci * doesn't happen with floats. Technically also should do comparison 2801bf215546Sopenharmony_ci * in texture format (quantization!). 2802bf215546Sopenharmony_ci */ 2803bf215546Sopenharmony_ci pc[0] = CLAMP(c0[0], 0.0F, 1.0F); 2804bf215546Sopenharmony_ci pc[1] = CLAMP(c0[1], 0.0F, 1.0F); 2805bf215546Sopenharmony_ci pc[2] = CLAMP(c0[2], 0.0F, 1.0F); 2806bf215546Sopenharmony_ci pc[3] = CLAMP(c0[3], 0.0F, 1.0F); 2807bf215546Sopenharmony_ci } else { 2808bf215546Sopenharmony_ci pc[0] = c0[0]; 2809bf215546Sopenharmony_ci pc[1] = c0[1]; 2810bf215546Sopenharmony_ci pc[2] = c0[2]; 2811bf215546Sopenharmony_ci pc[3] = c0[3]; 2812bf215546Sopenharmony_ci } 2813bf215546Sopenharmony_ci 2814bf215546Sopenharmony_ci for (v = 0; v < (is_gather ? TGSI_NUM_CHANNELS : 1); v++) { 2815bf215546Sopenharmony_ci /* compare four texcoords vs. four texture samples */ 2816bf215546Sopenharmony_ci switch (sampler->compare_func) { 2817bf215546Sopenharmony_ci case PIPE_FUNC_LESS: 2818bf215546Sopenharmony_ci k[v][0] = pc[0] < rgba[v][0]; 2819bf215546Sopenharmony_ci k[v][1] = pc[1] < rgba[v][1]; 2820bf215546Sopenharmony_ci k[v][2] = pc[2] < rgba[v][2]; 2821bf215546Sopenharmony_ci k[v][3] = pc[3] < rgba[v][3]; 2822bf215546Sopenharmony_ci break; 2823bf215546Sopenharmony_ci case PIPE_FUNC_LEQUAL: 2824bf215546Sopenharmony_ci k[v][0] = pc[0] <= rgba[v][0]; 2825bf215546Sopenharmony_ci k[v][1] = pc[1] <= rgba[v][1]; 2826bf215546Sopenharmony_ci k[v][2] = pc[2] <= rgba[v][2]; 2827bf215546Sopenharmony_ci k[v][3] = pc[3] <= rgba[v][3]; 2828bf215546Sopenharmony_ci break; 2829bf215546Sopenharmony_ci case PIPE_FUNC_GREATER: 2830bf215546Sopenharmony_ci k[v][0] = pc[0] > rgba[v][0]; 2831bf215546Sopenharmony_ci k[v][1] = pc[1] > rgba[v][1]; 2832bf215546Sopenharmony_ci k[v][2] = pc[2] > rgba[v][2]; 2833bf215546Sopenharmony_ci k[v][3] = pc[3] > rgba[v][3]; 2834bf215546Sopenharmony_ci break; 2835bf215546Sopenharmony_ci case PIPE_FUNC_GEQUAL: 2836bf215546Sopenharmony_ci k[v][0] = pc[0] >= rgba[v][0]; 2837bf215546Sopenharmony_ci k[v][1] = pc[1] >= rgba[v][1]; 2838bf215546Sopenharmony_ci k[v][2] = pc[2] >= rgba[v][2]; 2839bf215546Sopenharmony_ci k[v][3] = pc[3] >= rgba[v][3]; 2840bf215546Sopenharmony_ci break; 2841bf215546Sopenharmony_ci case PIPE_FUNC_EQUAL: 2842bf215546Sopenharmony_ci k[v][0] = pc[0] == rgba[v][0]; 2843bf215546Sopenharmony_ci k[v][1] = pc[1] == rgba[v][1]; 2844bf215546Sopenharmony_ci k[v][2] = pc[2] == rgba[v][2]; 2845bf215546Sopenharmony_ci k[v][3] = pc[3] == rgba[v][3]; 2846bf215546Sopenharmony_ci break; 2847bf215546Sopenharmony_ci case PIPE_FUNC_NOTEQUAL: 2848bf215546Sopenharmony_ci k[v][0] = pc[0] != rgba[v][0]; 2849bf215546Sopenharmony_ci k[v][1] = pc[1] != rgba[v][1]; 2850bf215546Sopenharmony_ci k[v][2] = pc[2] != rgba[v][2]; 2851bf215546Sopenharmony_ci k[v][3] = pc[3] != rgba[v][3]; 2852bf215546Sopenharmony_ci break; 2853bf215546Sopenharmony_ci case PIPE_FUNC_ALWAYS: 2854bf215546Sopenharmony_ci k[v][0] = k[v][1] = k[v][2] = k[v][3] = 1; 2855bf215546Sopenharmony_ci break; 2856bf215546Sopenharmony_ci case PIPE_FUNC_NEVER: 2857bf215546Sopenharmony_ci k[v][0] = k[v][1] = k[v][2] = k[v][3] = 0; 2858bf215546Sopenharmony_ci break; 2859bf215546Sopenharmony_ci default: 2860bf215546Sopenharmony_ci k[v][0] = k[v][1] = k[v][2] = k[v][3] = 0; 2861bf215546Sopenharmony_ci assert(0); 2862bf215546Sopenharmony_ci break; 2863bf215546Sopenharmony_ci } 2864bf215546Sopenharmony_ci } 2865bf215546Sopenharmony_ci 2866bf215546Sopenharmony_ci if (is_gather) { 2867bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2868bf215546Sopenharmony_ci for (v = 0; v < TGSI_NUM_CHANNELS; v++) { 2869bf215546Sopenharmony_ci rgba[v][j] = k[v][j]; 2870bf215546Sopenharmony_ci } 2871bf215546Sopenharmony_ci } 2872bf215546Sopenharmony_ci } else { 2873bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 2874bf215546Sopenharmony_ci rgba[0][j] = k[0][j]; 2875bf215546Sopenharmony_ci rgba[1][j] = k[0][j]; 2876bf215546Sopenharmony_ci rgba[2][j] = k[0][j]; 2877bf215546Sopenharmony_ci rgba[3][j] = 1.0F; 2878bf215546Sopenharmony_ci } 2879bf215546Sopenharmony_ci } 2880bf215546Sopenharmony_ci} 2881bf215546Sopenharmony_ci 2882bf215546Sopenharmony_cistatic void 2883bf215546Sopenharmony_cido_swizzling(const struct pipe_sampler_view *sview, 2884bf215546Sopenharmony_ci float in[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE], 2885bf215546Sopenharmony_ci float out[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 2886bf215546Sopenharmony_ci{ 2887bf215546Sopenharmony_ci struct sp_sampler_view *sp_sview = (struct sp_sampler_view *)sview; 2888bf215546Sopenharmony_ci int j; 2889bf215546Sopenharmony_ci const unsigned swizzle_r = sview->swizzle_r; 2890bf215546Sopenharmony_ci const unsigned swizzle_g = sview->swizzle_g; 2891bf215546Sopenharmony_ci const unsigned swizzle_b = sview->swizzle_b; 2892bf215546Sopenharmony_ci const unsigned swizzle_a = sview->swizzle_a; 2893bf215546Sopenharmony_ci 2894bf215546Sopenharmony_ci switch (swizzle_r) { 2895bf215546Sopenharmony_ci case PIPE_SWIZZLE_0: 2896bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2897bf215546Sopenharmony_ci out[0][j] = 0.0f; 2898bf215546Sopenharmony_ci break; 2899bf215546Sopenharmony_ci case PIPE_SWIZZLE_1: 2900bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2901bf215546Sopenharmony_ci out[0][j] = sp_sview->oneval; 2902bf215546Sopenharmony_ci break; 2903bf215546Sopenharmony_ci default: 2904bf215546Sopenharmony_ci assert(swizzle_r < 4); 2905bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2906bf215546Sopenharmony_ci out[0][j] = in[swizzle_r][j]; 2907bf215546Sopenharmony_ci } 2908bf215546Sopenharmony_ci 2909bf215546Sopenharmony_ci switch (swizzle_g) { 2910bf215546Sopenharmony_ci case PIPE_SWIZZLE_0: 2911bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2912bf215546Sopenharmony_ci out[1][j] = 0.0f; 2913bf215546Sopenharmony_ci break; 2914bf215546Sopenharmony_ci case PIPE_SWIZZLE_1: 2915bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2916bf215546Sopenharmony_ci out[1][j] = sp_sview->oneval; 2917bf215546Sopenharmony_ci break; 2918bf215546Sopenharmony_ci default: 2919bf215546Sopenharmony_ci assert(swizzle_g < 4); 2920bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2921bf215546Sopenharmony_ci out[1][j] = in[swizzle_g][j]; 2922bf215546Sopenharmony_ci } 2923bf215546Sopenharmony_ci 2924bf215546Sopenharmony_ci switch (swizzle_b) { 2925bf215546Sopenharmony_ci case PIPE_SWIZZLE_0: 2926bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2927bf215546Sopenharmony_ci out[2][j] = 0.0f; 2928bf215546Sopenharmony_ci break; 2929bf215546Sopenharmony_ci case PIPE_SWIZZLE_1: 2930bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2931bf215546Sopenharmony_ci out[2][j] = sp_sview->oneval; 2932bf215546Sopenharmony_ci break; 2933bf215546Sopenharmony_ci default: 2934bf215546Sopenharmony_ci assert(swizzle_b < 4); 2935bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2936bf215546Sopenharmony_ci out[2][j] = in[swizzle_b][j]; 2937bf215546Sopenharmony_ci } 2938bf215546Sopenharmony_ci 2939bf215546Sopenharmony_ci switch (swizzle_a) { 2940bf215546Sopenharmony_ci case PIPE_SWIZZLE_0: 2941bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2942bf215546Sopenharmony_ci out[3][j] = 0.0f; 2943bf215546Sopenharmony_ci break; 2944bf215546Sopenharmony_ci case PIPE_SWIZZLE_1: 2945bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2946bf215546Sopenharmony_ci out[3][j] = sp_sview->oneval; 2947bf215546Sopenharmony_ci break; 2948bf215546Sopenharmony_ci default: 2949bf215546Sopenharmony_ci assert(swizzle_a < 4); 2950bf215546Sopenharmony_ci for (j = 0; j < 4; j++) 2951bf215546Sopenharmony_ci out[3][j] = in[swizzle_a][j]; 2952bf215546Sopenharmony_ci } 2953bf215546Sopenharmony_ci} 2954bf215546Sopenharmony_ci 2955bf215546Sopenharmony_ci 2956bf215546Sopenharmony_cistatic wrap_nearest_func 2957bf215546Sopenharmony_ciget_nearest_unorm_wrap(unsigned mode) 2958bf215546Sopenharmony_ci{ 2959bf215546Sopenharmony_ci switch (mode) { 2960bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP: 2961bf215546Sopenharmony_ci return wrap_nearest_unorm_clamp; 2962bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2963bf215546Sopenharmony_ci return wrap_nearest_unorm_clamp_to_edge; 2964bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2965bf215546Sopenharmony_ci return wrap_nearest_unorm_clamp_to_border; 2966bf215546Sopenharmony_ci default: 2967bf215546Sopenharmony_ci debug_printf("illegal wrap mode %d with non-normalized coords\n", mode); 2968bf215546Sopenharmony_ci return wrap_nearest_unorm_clamp; 2969bf215546Sopenharmony_ci } 2970bf215546Sopenharmony_ci} 2971bf215546Sopenharmony_ci 2972bf215546Sopenharmony_ci 2973bf215546Sopenharmony_cistatic wrap_nearest_func 2974bf215546Sopenharmony_ciget_nearest_wrap(unsigned mode) 2975bf215546Sopenharmony_ci{ 2976bf215546Sopenharmony_ci switch (mode) { 2977bf215546Sopenharmony_ci case PIPE_TEX_WRAP_REPEAT: 2978bf215546Sopenharmony_ci return wrap_nearest_repeat; 2979bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP: 2980bf215546Sopenharmony_ci return wrap_nearest_clamp; 2981bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 2982bf215546Sopenharmony_ci return wrap_nearest_clamp_to_edge; 2983bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 2984bf215546Sopenharmony_ci return wrap_nearest_clamp_to_border; 2985bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_REPEAT: 2986bf215546Sopenharmony_ci return wrap_nearest_mirror_repeat; 2987bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_CLAMP: 2988bf215546Sopenharmony_ci return wrap_nearest_mirror_clamp; 2989bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 2990bf215546Sopenharmony_ci return wrap_nearest_mirror_clamp_to_edge; 2991bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 2992bf215546Sopenharmony_ci return wrap_nearest_mirror_clamp_to_border; 2993bf215546Sopenharmony_ci default: 2994bf215546Sopenharmony_ci assert(0); 2995bf215546Sopenharmony_ci return wrap_nearest_repeat; 2996bf215546Sopenharmony_ci } 2997bf215546Sopenharmony_ci} 2998bf215546Sopenharmony_ci 2999bf215546Sopenharmony_ci 3000bf215546Sopenharmony_cistatic wrap_linear_func 3001bf215546Sopenharmony_ciget_linear_unorm_wrap(unsigned mode) 3002bf215546Sopenharmony_ci{ 3003bf215546Sopenharmony_ci switch (mode) { 3004bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP: 3005bf215546Sopenharmony_ci return wrap_linear_unorm_clamp; 3006bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 3007bf215546Sopenharmony_ci return wrap_linear_unorm_clamp_to_edge; 3008bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 3009bf215546Sopenharmony_ci return wrap_linear_unorm_clamp_to_border; 3010bf215546Sopenharmony_ci default: 3011bf215546Sopenharmony_ci debug_printf("illegal wrap mode %d with non-normalized coords\n", mode); 3012bf215546Sopenharmony_ci return wrap_linear_unorm_clamp; 3013bf215546Sopenharmony_ci } 3014bf215546Sopenharmony_ci} 3015bf215546Sopenharmony_ci 3016bf215546Sopenharmony_ci 3017bf215546Sopenharmony_cistatic wrap_linear_func 3018bf215546Sopenharmony_ciget_linear_wrap(unsigned mode) 3019bf215546Sopenharmony_ci{ 3020bf215546Sopenharmony_ci switch (mode) { 3021bf215546Sopenharmony_ci case PIPE_TEX_WRAP_REPEAT: 3022bf215546Sopenharmony_ci return wrap_linear_repeat; 3023bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP: 3024bf215546Sopenharmony_ci return wrap_linear_clamp; 3025bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 3026bf215546Sopenharmony_ci return wrap_linear_clamp_to_edge; 3027bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 3028bf215546Sopenharmony_ci return wrap_linear_clamp_to_border; 3029bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_REPEAT: 3030bf215546Sopenharmony_ci return wrap_linear_mirror_repeat; 3031bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_CLAMP: 3032bf215546Sopenharmony_ci return wrap_linear_mirror_clamp; 3033bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 3034bf215546Sopenharmony_ci return wrap_linear_mirror_clamp_to_edge; 3035bf215546Sopenharmony_ci case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 3036bf215546Sopenharmony_ci return wrap_linear_mirror_clamp_to_border; 3037bf215546Sopenharmony_ci default: 3038bf215546Sopenharmony_ci assert(0); 3039bf215546Sopenharmony_ci return wrap_linear_repeat; 3040bf215546Sopenharmony_ci } 3041bf215546Sopenharmony_ci} 3042bf215546Sopenharmony_ci 3043bf215546Sopenharmony_ci 3044bf215546Sopenharmony_ci/** 3045bf215546Sopenharmony_ci * Is swizzling needed for the given state key? 3046bf215546Sopenharmony_ci */ 3047bf215546Sopenharmony_cistatic inline bool 3048bf215546Sopenharmony_ciany_swizzle(const struct pipe_sampler_view *view) 3049bf215546Sopenharmony_ci{ 3050bf215546Sopenharmony_ci return (view->swizzle_r != PIPE_SWIZZLE_X || 3051bf215546Sopenharmony_ci view->swizzle_g != PIPE_SWIZZLE_Y || 3052bf215546Sopenharmony_ci view->swizzle_b != PIPE_SWIZZLE_Z || 3053bf215546Sopenharmony_ci view->swizzle_a != PIPE_SWIZZLE_W); 3054bf215546Sopenharmony_ci} 3055bf215546Sopenharmony_ci 3056bf215546Sopenharmony_ci 3057bf215546Sopenharmony_cistatic img_filter_func 3058bf215546Sopenharmony_ciget_img_filter(const struct sp_sampler_view *sp_sview, 3059bf215546Sopenharmony_ci const struct pipe_sampler_state *sampler, 3060bf215546Sopenharmony_ci unsigned filter, bool gather) 3061bf215546Sopenharmony_ci{ 3062bf215546Sopenharmony_ci switch (sp_sview->base.target) { 3063bf215546Sopenharmony_ci case PIPE_BUFFER: 3064bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 3065bf215546Sopenharmony_ci if (filter == PIPE_TEX_FILTER_NEAREST) 3066bf215546Sopenharmony_ci return img_filter_1d_nearest; 3067bf215546Sopenharmony_ci else 3068bf215546Sopenharmony_ci return img_filter_1d_linear; 3069bf215546Sopenharmony_ci break; 3070bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 3071bf215546Sopenharmony_ci if (filter == PIPE_TEX_FILTER_NEAREST) 3072bf215546Sopenharmony_ci return img_filter_1d_array_nearest; 3073bf215546Sopenharmony_ci else 3074bf215546Sopenharmony_ci return img_filter_1d_array_linear; 3075bf215546Sopenharmony_ci break; 3076bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 3077bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 3078bf215546Sopenharmony_ci /* Try for fast path: 3079bf215546Sopenharmony_ci */ 3080bf215546Sopenharmony_ci if (!gather && sp_sview->pot2d && 3081bf215546Sopenharmony_ci sampler->wrap_s == sampler->wrap_t && 3082bf215546Sopenharmony_ci sampler->normalized_coords) 3083bf215546Sopenharmony_ci { 3084bf215546Sopenharmony_ci switch (sampler->wrap_s) { 3085bf215546Sopenharmony_ci case PIPE_TEX_WRAP_REPEAT: 3086bf215546Sopenharmony_ci switch (filter) { 3087bf215546Sopenharmony_ci case PIPE_TEX_FILTER_NEAREST: 3088bf215546Sopenharmony_ci return img_filter_2d_nearest_repeat_POT; 3089bf215546Sopenharmony_ci case PIPE_TEX_FILTER_LINEAR: 3090bf215546Sopenharmony_ci return img_filter_2d_linear_repeat_POT; 3091bf215546Sopenharmony_ci default: 3092bf215546Sopenharmony_ci break; 3093bf215546Sopenharmony_ci } 3094bf215546Sopenharmony_ci break; 3095bf215546Sopenharmony_ci case PIPE_TEX_WRAP_CLAMP: 3096bf215546Sopenharmony_ci switch (filter) { 3097bf215546Sopenharmony_ci case PIPE_TEX_FILTER_NEAREST: 3098bf215546Sopenharmony_ci return img_filter_2d_nearest_clamp_POT; 3099bf215546Sopenharmony_ci default: 3100bf215546Sopenharmony_ci break; 3101bf215546Sopenharmony_ci } 3102bf215546Sopenharmony_ci } 3103bf215546Sopenharmony_ci } 3104bf215546Sopenharmony_ci /* Otherwise use default versions: 3105bf215546Sopenharmony_ci */ 3106bf215546Sopenharmony_ci if (filter == PIPE_TEX_FILTER_NEAREST) 3107bf215546Sopenharmony_ci return img_filter_2d_nearest; 3108bf215546Sopenharmony_ci else 3109bf215546Sopenharmony_ci return img_filter_2d_linear; 3110bf215546Sopenharmony_ci break; 3111bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 3112bf215546Sopenharmony_ci if (filter == PIPE_TEX_FILTER_NEAREST) 3113bf215546Sopenharmony_ci return img_filter_2d_array_nearest; 3114bf215546Sopenharmony_ci else 3115bf215546Sopenharmony_ci return img_filter_2d_array_linear; 3116bf215546Sopenharmony_ci break; 3117bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 3118bf215546Sopenharmony_ci if (filter == PIPE_TEX_FILTER_NEAREST) 3119bf215546Sopenharmony_ci return img_filter_cube_nearest; 3120bf215546Sopenharmony_ci else 3121bf215546Sopenharmony_ci return img_filter_cube_linear; 3122bf215546Sopenharmony_ci break; 3123bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 3124bf215546Sopenharmony_ci if (filter == PIPE_TEX_FILTER_NEAREST) 3125bf215546Sopenharmony_ci return img_filter_cube_array_nearest; 3126bf215546Sopenharmony_ci else 3127bf215546Sopenharmony_ci return img_filter_cube_array_linear; 3128bf215546Sopenharmony_ci break; 3129bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 3130bf215546Sopenharmony_ci if (filter == PIPE_TEX_FILTER_NEAREST) 3131bf215546Sopenharmony_ci return img_filter_3d_nearest; 3132bf215546Sopenharmony_ci else 3133bf215546Sopenharmony_ci return img_filter_3d_linear; 3134bf215546Sopenharmony_ci break; 3135bf215546Sopenharmony_ci default: 3136bf215546Sopenharmony_ci assert(0); 3137bf215546Sopenharmony_ci return img_filter_1d_nearest; 3138bf215546Sopenharmony_ci } 3139bf215546Sopenharmony_ci} 3140bf215546Sopenharmony_ci 3141bf215546Sopenharmony_ci/** 3142bf215546Sopenharmony_ci * Get mip filter funcs, and optionally both img min filter and img mag 3143bf215546Sopenharmony_ci * filter. Note that both img filter function pointers must be either non-NULL 3144bf215546Sopenharmony_ci * or NULL. 3145bf215546Sopenharmony_ci */ 3146bf215546Sopenharmony_cistatic void 3147bf215546Sopenharmony_ciget_filters(const struct sp_sampler_view *sp_sview, 3148bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 3149bf215546Sopenharmony_ci const enum tgsi_sampler_control control, 3150bf215546Sopenharmony_ci const struct sp_filter_funcs **funcs, 3151bf215546Sopenharmony_ci img_filter_func *min, 3152bf215546Sopenharmony_ci img_filter_func *mag) 3153bf215546Sopenharmony_ci{ 3154bf215546Sopenharmony_ci assert(funcs); 3155bf215546Sopenharmony_ci if (control == TGSI_SAMPLER_GATHER) { 3156bf215546Sopenharmony_ci *funcs = &funcs_nearest; 3157bf215546Sopenharmony_ci if (min) { 3158bf215546Sopenharmony_ci *min = get_img_filter(sp_sview, &sp_samp->base, 3159bf215546Sopenharmony_ci PIPE_TEX_FILTER_LINEAR, true); 3160bf215546Sopenharmony_ci } 3161bf215546Sopenharmony_ci } else if (sp_sview->pot2d & sp_samp->min_mag_equal_repeat_linear) { 3162bf215546Sopenharmony_ci *funcs = &funcs_linear_2d_linear_repeat_POT; 3163bf215546Sopenharmony_ci } else { 3164bf215546Sopenharmony_ci *funcs = sp_samp->filter_funcs; 3165bf215546Sopenharmony_ci if (min) { 3166bf215546Sopenharmony_ci assert(mag); 3167bf215546Sopenharmony_ci *min = get_img_filter(sp_sview, &sp_samp->base, 3168bf215546Sopenharmony_ci sp_samp->min_img_filter, false); 3169bf215546Sopenharmony_ci if (sp_samp->min_mag_equal) { 3170bf215546Sopenharmony_ci *mag = *min; 3171bf215546Sopenharmony_ci } else { 3172bf215546Sopenharmony_ci *mag = get_img_filter(sp_sview, &sp_samp->base, 3173bf215546Sopenharmony_ci sp_samp->base.mag_img_filter, false); 3174bf215546Sopenharmony_ci } 3175bf215546Sopenharmony_ci } 3176bf215546Sopenharmony_ci } 3177bf215546Sopenharmony_ci} 3178bf215546Sopenharmony_ci 3179bf215546Sopenharmony_cistatic void 3180bf215546Sopenharmony_cisample_mip(const struct sp_sampler_view *sp_sview, 3181bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 3182bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 3183bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 3184bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 3185bf215546Sopenharmony_ci const float c0[TGSI_QUAD_SIZE], 3186bf215546Sopenharmony_ci int gather_comp, 3187bf215546Sopenharmony_ci const float lod[TGSI_QUAD_SIZE], 3188bf215546Sopenharmony_ci const struct filter_args *filt_args, 3189bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 3190bf215546Sopenharmony_ci{ 3191bf215546Sopenharmony_ci const struct sp_filter_funcs *funcs = NULL; 3192bf215546Sopenharmony_ci img_filter_func min_img_filter = NULL; 3193bf215546Sopenharmony_ci img_filter_func mag_img_filter = NULL; 3194bf215546Sopenharmony_ci 3195bf215546Sopenharmony_ci get_filters(sp_sview, sp_samp, filt_args->control, 3196bf215546Sopenharmony_ci &funcs, &min_img_filter, &mag_img_filter); 3197bf215546Sopenharmony_ci 3198bf215546Sopenharmony_ci funcs->filter(sp_sview, sp_samp, min_img_filter, mag_img_filter, 3199bf215546Sopenharmony_ci s, t, p, gather_comp, lod, filt_args, rgba); 3200bf215546Sopenharmony_ci 3201bf215546Sopenharmony_ci if (sp_samp->base.compare_mode != PIPE_TEX_COMPARE_NONE) { 3202bf215546Sopenharmony_ci sample_compare(sp_sview, sp_samp, c0, filt_args->control, rgba); 3203bf215546Sopenharmony_ci } 3204bf215546Sopenharmony_ci 3205bf215546Sopenharmony_ci if (sp_sview->need_swizzle && filt_args->control != TGSI_SAMPLER_GATHER) { 3206bf215546Sopenharmony_ci float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]; 3207bf215546Sopenharmony_ci memcpy(rgba_temp, rgba, sizeof(rgba_temp)); 3208bf215546Sopenharmony_ci do_swizzling(&sp_sview->base, rgba_temp, rgba); 3209bf215546Sopenharmony_ci } 3210bf215546Sopenharmony_ci 3211bf215546Sopenharmony_ci} 3212bf215546Sopenharmony_ci 3213bf215546Sopenharmony_ci 3214bf215546Sopenharmony_ci/** 3215bf215546Sopenharmony_ci * This function uses cube texture coordinates to choose a face of a cube and 3216bf215546Sopenharmony_ci * computes the 2D cube face coordinates. Puts face info into the sampler 3217bf215546Sopenharmony_ci * faces[] array. 3218bf215546Sopenharmony_ci */ 3219bf215546Sopenharmony_cistatic void 3220bf215546Sopenharmony_ciconvert_cube(const struct sp_sampler_view *sp_sview, 3221bf215546Sopenharmony_ci const struct sp_sampler *sp_samp, 3222bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 3223bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 3224bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 3225bf215546Sopenharmony_ci const float c0[TGSI_QUAD_SIZE], 3226bf215546Sopenharmony_ci float ssss[TGSI_QUAD_SIZE], 3227bf215546Sopenharmony_ci float tttt[TGSI_QUAD_SIZE], 3228bf215546Sopenharmony_ci float pppp[TGSI_QUAD_SIZE], 3229bf215546Sopenharmony_ci uint faces[TGSI_QUAD_SIZE]) 3230bf215546Sopenharmony_ci{ 3231bf215546Sopenharmony_ci unsigned j; 3232bf215546Sopenharmony_ci 3233bf215546Sopenharmony_ci pppp[0] = c0[0]; 3234bf215546Sopenharmony_ci pppp[1] = c0[1]; 3235bf215546Sopenharmony_ci pppp[2] = c0[2]; 3236bf215546Sopenharmony_ci pppp[3] = c0[3]; 3237bf215546Sopenharmony_ci /* 3238bf215546Sopenharmony_ci major axis 3239bf215546Sopenharmony_ci direction target sc tc ma 3240bf215546Sopenharmony_ci ---------- ------------------------------- --- --- --- 3241bf215546Sopenharmony_ci +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx 3242bf215546Sopenharmony_ci -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx 3243bf215546Sopenharmony_ci +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry 3244bf215546Sopenharmony_ci -ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry 3245bf215546Sopenharmony_ci +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz 3246bf215546Sopenharmony_ci -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz 3247bf215546Sopenharmony_ci */ 3248bf215546Sopenharmony_ci 3249bf215546Sopenharmony_ci /* Choose the cube face and compute new s/t coords for the 2D face. 3250bf215546Sopenharmony_ci * 3251bf215546Sopenharmony_ci * Use the same cube face for all four pixels in the quad. 3252bf215546Sopenharmony_ci * 3253bf215546Sopenharmony_ci * This isn't ideal, but if we want to use a different cube face 3254bf215546Sopenharmony_ci * per pixel in the quad, we'd have to also compute the per-face 3255bf215546Sopenharmony_ci * LOD here too. That's because the four post-face-selection 3256bf215546Sopenharmony_ci * texcoords are no longer related to each other (they're 3257bf215546Sopenharmony_ci * per-face!) so we can't use subtraction to compute the partial 3258bf215546Sopenharmony_ci * deriviates to compute the LOD. Doing so (near cube edges 3259bf215546Sopenharmony_ci * anyway) gives us pretty much random values. 3260bf215546Sopenharmony_ci */ 3261bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 3262bf215546Sopenharmony_ci const float rx = s[j], ry = t[j], rz = p[j]; 3263bf215546Sopenharmony_ci const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); 3264bf215546Sopenharmony_ci 3265bf215546Sopenharmony_ci if (arx >= ary && arx >= arz) { 3266bf215546Sopenharmony_ci const float sign = (rx >= 0.0F) ? 1.0F : -1.0F; 3267bf215546Sopenharmony_ci const uint face = (rx >= 0.0F) ? 3268bf215546Sopenharmony_ci PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X; 3269bf215546Sopenharmony_ci const float ima = -0.5F / fabsf(s[j]); 3270bf215546Sopenharmony_ci ssss[j] = sign * p[j] * ima + 0.5F; 3271bf215546Sopenharmony_ci tttt[j] = t[j] * ima + 0.5F; 3272bf215546Sopenharmony_ci faces[j] = face; 3273bf215546Sopenharmony_ci } 3274bf215546Sopenharmony_ci else if (ary >= arx && ary >= arz) { 3275bf215546Sopenharmony_ci const float sign = (ry >= 0.0F) ? 1.0F : -1.0F; 3276bf215546Sopenharmony_ci const uint face = (ry >= 0.0F) ? 3277bf215546Sopenharmony_ci PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y; 3278bf215546Sopenharmony_ci const float ima = -0.5F / fabsf(t[j]); 3279bf215546Sopenharmony_ci ssss[j] = -s[j] * ima + 0.5F; 3280bf215546Sopenharmony_ci tttt[j] = sign * -p[j] * ima + 0.5F; 3281bf215546Sopenharmony_ci faces[j] = face; 3282bf215546Sopenharmony_ci } 3283bf215546Sopenharmony_ci else { 3284bf215546Sopenharmony_ci const float sign = (rz >= 0.0F) ? 1.0F : -1.0F; 3285bf215546Sopenharmony_ci const uint face = (rz >= 0.0F) ? 3286bf215546Sopenharmony_ci PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z; 3287bf215546Sopenharmony_ci const float ima = -0.5F / fabsf(p[j]); 3288bf215546Sopenharmony_ci ssss[j] = sign * -s[j] * ima + 0.5F; 3289bf215546Sopenharmony_ci tttt[j] = t[j] * ima + 0.5F; 3290bf215546Sopenharmony_ci faces[j] = face; 3291bf215546Sopenharmony_ci } 3292bf215546Sopenharmony_ci } 3293bf215546Sopenharmony_ci} 3294bf215546Sopenharmony_ci 3295bf215546Sopenharmony_ci 3296bf215546Sopenharmony_cistatic void 3297bf215546Sopenharmony_cisp_get_dims(const struct sp_sampler_view *sp_sview, 3298bf215546Sopenharmony_ci int level, 3299bf215546Sopenharmony_ci int dims[4]) 3300bf215546Sopenharmony_ci{ 3301bf215546Sopenharmony_ci const struct pipe_sampler_view *view = &sp_sview->base; 3302bf215546Sopenharmony_ci const struct pipe_resource *texture = view->texture; 3303bf215546Sopenharmony_ci 3304bf215546Sopenharmony_ci if (view->target == PIPE_BUFFER) { 3305bf215546Sopenharmony_ci dims[0] = view->u.buf.size / util_format_get_blocksize(view->format); 3306bf215546Sopenharmony_ci /* the other values are undefined, but let's avoid potential valgrind 3307bf215546Sopenharmony_ci * warnings. 3308bf215546Sopenharmony_ci */ 3309bf215546Sopenharmony_ci dims[1] = dims[2] = dims[3] = 0; 3310bf215546Sopenharmony_ci return; 3311bf215546Sopenharmony_ci } 3312bf215546Sopenharmony_ci 3313bf215546Sopenharmony_ci /* undefined according to EXT_gpu_program */ 3314bf215546Sopenharmony_ci level += view->u.tex.first_level; 3315bf215546Sopenharmony_ci if (level > view->u.tex.last_level) 3316bf215546Sopenharmony_ci return; 3317bf215546Sopenharmony_ci 3318bf215546Sopenharmony_ci dims[3] = view->u.tex.last_level - view->u.tex.first_level + 1; 3319bf215546Sopenharmony_ci dims[0] = u_minify(texture->width0, level); 3320bf215546Sopenharmony_ci 3321bf215546Sopenharmony_ci switch (view->target) { 3322bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 3323bf215546Sopenharmony_ci dims[1] = view->u.tex.last_layer - view->u.tex.first_layer + 1; 3324bf215546Sopenharmony_ci FALLTHROUGH; 3325bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 3326bf215546Sopenharmony_ci return; 3327bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 3328bf215546Sopenharmony_ci dims[2] = view->u.tex.last_layer - view->u.tex.first_layer + 1; 3329bf215546Sopenharmony_ci FALLTHROUGH; 3330bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 3331bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 3332bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 3333bf215546Sopenharmony_ci dims[1] = u_minify(texture->height0, level); 3334bf215546Sopenharmony_ci return; 3335bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 3336bf215546Sopenharmony_ci dims[1] = u_minify(texture->height0, level); 3337bf215546Sopenharmony_ci dims[2] = u_minify(texture->depth0, level); 3338bf215546Sopenharmony_ci return; 3339bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 3340bf215546Sopenharmony_ci dims[1] = u_minify(texture->height0, level); 3341bf215546Sopenharmony_ci dims[2] = (view->u.tex.last_layer - view->u.tex.first_layer + 1) / 6; 3342bf215546Sopenharmony_ci break; 3343bf215546Sopenharmony_ci default: 3344bf215546Sopenharmony_ci assert(!"unexpected texture target in sp_get_dims()"); 3345bf215546Sopenharmony_ci return; 3346bf215546Sopenharmony_ci } 3347bf215546Sopenharmony_ci} 3348bf215546Sopenharmony_ci 3349bf215546Sopenharmony_ci/** 3350bf215546Sopenharmony_ci * This function is only used for getting unfiltered texels via the 3351bf215546Sopenharmony_ci * TXF opcode. The GL spec says that out-of-bounds texel fetches 3352bf215546Sopenharmony_ci * produce undefined results. Instead of crashing, lets just clamp 3353bf215546Sopenharmony_ci * coords to the texture image size. 3354bf215546Sopenharmony_ci */ 3355bf215546Sopenharmony_cistatic void 3356bf215546Sopenharmony_cisp_get_texels(const struct sp_sampler_view *sp_sview, 3357bf215546Sopenharmony_ci const int v_i[TGSI_QUAD_SIZE], 3358bf215546Sopenharmony_ci const int v_j[TGSI_QUAD_SIZE], 3359bf215546Sopenharmony_ci const int v_k[TGSI_QUAD_SIZE], 3360bf215546Sopenharmony_ci const int lod[TGSI_QUAD_SIZE], 3361bf215546Sopenharmony_ci const int8_t offset[3], 3362bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 3363bf215546Sopenharmony_ci{ 3364bf215546Sopenharmony_ci union tex_tile_address addr; 3365bf215546Sopenharmony_ci const struct pipe_resource *texture = sp_sview->base.texture; 3366bf215546Sopenharmony_ci int j, c; 3367bf215546Sopenharmony_ci const float *tx; 3368bf215546Sopenharmony_ci /* TODO write a better test for LOD */ 3369bf215546Sopenharmony_ci const unsigned level = 3370bf215546Sopenharmony_ci sp_sview->base.target == PIPE_BUFFER ? 0 : 3371bf215546Sopenharmony_ci CLAMP(lod[0] + sp_sview->base.u.tex.first_level, 3372bf215546Sopenharmony_ci sp_sview->base.u.tex.first_level, 3373bf215546Sopenharmony_ci sp_sview->base.u.tex.last_level); 3374bf215546Sopenharmony_ci const int width = u_minify(texture->width0, level); 3375bf215546Sopenharmony_ci const int height = u_minify(texture->height0, level); 3376bf215546Sopenharmony_ci const int depth = u_minify(texture->depth0, level); 3377bf215546Sopenharmony_ci unsigned elem_size, first_element, last_element; 3378bf215546Sopenharmony_ci 3379bf215546Sopenharmony_ci addr.value = 0; 3380bf215546Sopenharmony_ci addr.bits.level = level; 3381bf215546Sopenharmony_ci 3382bf215546Sopenharmony_ci switch (sp_sview->base.target) { 3383bf215546Sopenharmony_ci case PIPE_BUFFER: 3384bf215546Sopenharmony_ci elem_size = util_format_get_blocksize(sp_sview->base.format); 3385bf215546Sopenharmony_ci first_element = sp_sview->base.u.buf.offset / elem_size; 3386bf215546Sopenharmony_ci last_element = (sp_sview->base.u.buf.offset + 3387bf215546Sopenharmony_ci sp_sview->base.u.buf.size) / elem_size - 1; 3388bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 3389bf215546Sopenharmony_ci const int x = CLAMP(v_i[j] + offset[0] + 3390bf215546Sopenharmony_ci first_element, 3391bf215546Sopenharmony_ci first_element, 3392bf215546Sopenharmony_ci last_element); 3393bf215546Sopenharmony_ci tx = get_texel_buffer_no_border(sp_sview, addr, x, elem_size); 3394bf215546Sopenharmony_ci for (c = 0; c < 4; c++) { 3395bf215546Sopenharmony_ci rgba[c][j] = tx[c]; 3396bf215546Sopenharmony_ci } 3397bf215546Sopenharmony_ci } 3398bf215546Sopenharmony_ci break; 3399bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 3400bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 3401bf215546Sopenharmony_ci const int x = CLAMP(v_i[j] + offset[0], 0, width - 1); 3402bf215546Sopenharmony_ci tx = get_texel_2d_no_border(sp_sview, addr, x, 3403bf215546Sopenharmony_ci sp_sview->base.u.tex.first_layer); 3404bf215546Sopenharmony_ci for (c = 0; c < 4; c++) { 3405bf215546Sopenharmony_ci rgba[c][j] = tx[c]; 3406bf215546Sopenharmony_ci } 3407bf215546Sopenharmony_ci } 3408bf215546Sopenharmony_ci break; 3409bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 3410bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 3411bf215546Sopenharmony_ci const int x = CLAMP(v_i[j] + offset[0], 0, width - 1); 3412bf215546Sopenharmony_ci const int y = CLAMP(v_j[j], sp_sview->base.u.tex.first_layer, 3413bf215546Sopenharmony_ci sp_sview->base.u.tex.last_layer); 3414bf215546Sopenharmony_ci tx = get_texel_2d_no_border(sp_sview, addr, x, y); 3415bf215546Sopenharmony_ci for (c = 0; c < 4; c++) { 3416bf215546Sopenharmony_ci rgba[c][j] = tx[c]; 3417bf215546Sopenharmony_ci } 3418bf215546Sopenharmony_ci } 3419bf215546Sopenharmony_ci break; 3420bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 3421bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 3422bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 3423bf215546Sopenharmony_ci const int x = CLAMP(v_i[j] + offset[0], 0, width - 1); 3424bf215546Sopenharmony_ci const int y = CLAMP(v_j[j] + offset[1], 0, height - 1); 3425bf215546Sopenharmony_ci tx = get_texel_3d_no_border(sp_sview, addr, x, y, 3426bf215546Sopenharmony_ci sp_sview->base.u.tex.first_layer); 3427bf215546Sopenharmony_ci for (c = 0; c < 4; c++) { 3428bf215546Sopenharmony_ci rgba[c][j] = tx[c]; 3429bf215546Sopenharmony_ci } 3430bf215546Sopenharmony_ci } 3431bf215546Sopenharmony_ci break; 3432bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 3433bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 3434bf215546Sopenharmony_ci const int x = CLAMP(v_i[j] + offset[0], 0, width - 1); 3435bf215546Sopenharmony_ci const int y = CLAMP(v_j[j] + offset[1], 0, height - 1); 3436bf215546Sopenharmony_ci const int layer = CLAMP(v_k[j], sp_sview->base.u.tex.first_layer, 3437bf215546Sopenharmony_ci sp_sview->base.u.tex.last_layer); 3438bf215546Sopenharmony_ci tx = get_texel_3d_no_border(sp_sview, addr, x, y, layer); 3439bf215546Sopenharmony_ci for (c = 0; c < 4; c++) { 3440bf215546Sopenharmony_ci rgba[c][j] = tx[c]; 3441bf215546Sopenharmony_ci } 3442bf215546Sopenharmony_ci } 3443bf215546Sopenharmony_ci break; 3444bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 3445bf215546Sopenharmony_ci for (j = 0; j < TGSI_QUAD_SIZE; j++) { 3446bf215546Sopenharmony_ci int x = CLAMP(v_i[j] + offset[0], 0, width - 1); 3447bf215546Sopenharmony_ci int y = CLAMP(v_j[j] + offset[1], 0, height - 1); 3448bf215546Sopenharmony_ci int z = CLAMP(v_k[j] + offset[2], 0, depth - 1); 3449bf215546Sopenharmony_ci tx = get_texel_3d_no_border(sp_sview, addr, x, y, z); 3450bf215546Sopenharmony_ci for (c = 0; c < 4; c++) { 3451bf215546Sopenharmony_ci rgba[c][j] = tx[c]; 3452bf215546Sopenharmony_ci } 3453bf215546Sopenharmony_ci } 3454bf215546Sopenharmony_ci break; 3455bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: /* TXF can't work on CUBE according to spec */ 3456bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 3457bf215546Sopenharmony_ci default: 3458bf215546Sopenharmony_ci assert(!"Unknown or CUBE texture type in TXF processing\n"); 3459bf215546Sopenharmony_ci break; 3460bf215546Sopenharmony_ci } 3461bf215546Sopenharmony_ci 3462bf215546Sopenharmony_ci if (sp_sview->need_swizzle) { 3463bf215546Sopenharmony_ci float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]; 3464bf215546Sopenharmony_ci memcpy(rgba_temp, rgba, sizeof(rgba_temp)); 3465bf215546Sopenharmony_ci do_swizzling(&sp_sview->base, rgba_temp, rgba); 3466bf215546Sopenharmony_ci } 3467bf215546Sopenharmony_ci} 3468bf215546Sopenharmony_ci 3469bf215546Sopenharmony_ci 3470bf215546Sopenharmony_civoid * 3471bf215546Sopenharmony_cisoftpipe_create_sampler_state(struct pipe_context *pipe, 3472bf215546Sopenharmony_ci const struct pipe_sampler_state *sampler) 3473bf215546Sopenharmony_ci{ 3474bf215546Sopenharmony_ci struct sp_sampler *samp = CALLOC_STRUCT(sp_sampler); 3475bf215546Sopenharmony_ci 3476bf215546Sopenharmony_ci samp->base = *sampler; 3477bf215546Sopenharmony_ci 3478bf215546Sopenharmony_ci /* Note that (for instance) linear_texcoord_s and 3479bf215546Sopenharmony_ci * nearest_texcoord_s may be active at the same time, if the 3480bf215546Sopenharmony_ci * sampler min_img_filter differs from its mag_img_filter. 3481bf215546Sopenharmony_ci */ 3482bf215546Sopenharmony_ci if (sampler->normalized_coords) { 3483bf215546Sopenharmony_ci samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s ); 3484bf215546Sopenharmony_ci samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t ); 3485bf215546Sopenharmony_ci samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r ); 3486bf215546Sopenharmony_ci 3487bf215546Sopenharmony_ci samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s ); 3488bf215546Sopenharmony_ci samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t ); 3489bf215546Sopenharmony_ci samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r ); 3490bf215546Sopenharmony_ci } 3491bf215546Sopenharmony_ci else { 3492bf215546Sopenharmony_ci samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s ); 3493bf215546Sopenharmony_ci samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t ); 3494bf215546Sopenharmony_ci samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r ); 3495bf215546Sopenharmony_ci 3496bf215546Sopenharmony_ci samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s ); 3497bf215546Sopenharmony_ci samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t ); 3498bf215546Sopenharmony_ci samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r ); 3499bf215546Sopenharmony_ci } 3500bf215546Sopenharmony_ci 3501bf215546Sopenharmony_ci samp->min_img_filter = sampler->min_img_filter; 3502bf215546Sopenharmony_ci 3503bf215546Sopenharmony_ci switch (sampler->min_mip_filter) { 3504bf215546Sopenharmony_ci case PIPE_TEX_MIPFILTER_NONE: 3505bf215546Sopenharmony_ci if (sampler->min_img_filter == sampler->mag_img_filter) 3506bf215546Sopenharmony_ci samp->filter_funcs = &funcs_none_no_filter_select; 3507bf215546Sopenharmony_ci else 3508bf215546Sopenharmony_ci samp->filter_funcs = &funcs_none; 3509bf215546Sopenharmony_ci break; 3510bf215546Sopenharmony_ci 3511bf215546Sopenharmony_ci case PIPE_TEX_MIPFILTER_NEAREST: 3512bf215546Sopenharmony_ci samp->filter_funcs = &funcs_nearest; 3513bf215546Sopenharmony_ci break; 3514bf215546Sopenharmony_ci 3515bf215546Sopenharmony_ci case PIPE_TEX_MIPFILTER_LINEAR: 3516bf215546Sopenharmony_ci if (sampler->min_img_filter == sampler->mag_img_filter && 3517bf215546Sopenharmony_ci sampler->normalized_coords && 3518bf215546Sopenharmony_ci sampler->wrap_s == PIPE_TEX_WRAP_REPEAT && 3519bf215546Sopenharmony_ci sampler->wrap_t == PIPE_TEX_WRAP_REPEAT && 3520bf215546Sopenharmony_ci sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR && 3521bf215546Sopenharmony_ci sampler->max_anisotropy <= 1) { 3522bf215546Sopenharmony_ci samp->min_mag_equal_repeat_linear = TRUE; 3523bf215546Sopenharmony_ci } 3524bf215546Sopenharmony_ci samp->filter_funcs = &funcs_linear; 3525bf215546Sopenharmony_ci 3526bf215546Sopenharmony_ci /* Anisotropic filtering extension. */ 3527bf215546Sopenharmony_ci if (sampler->max_anisotropy > 1) { 3528bf215546Sopenharmony_ci samp->filter_funcs = &funcs_linear_aniso; 3529bf215546Sopenharmony_ci 3530bf215546Sopenharmony_ci /* Override min_img_filter: 3531bf215546Sopenharmony_ci * min_img_filter needs to be set to NEAREST since we need to access 3532bf215546Sopenharmony_ci * each texture pixel as it is and weight it later; using linear 3533bf215546Sopenharmony_ci * filters will have incorrect results. 3534bf215546Sopenharmony_ci * By setting the filter to NEAREST here, we can avoid calling the 3535bf215546Sopenharmony_ci * generic img_filter_2d_nearest in the anisotropic filter function, 3536bf215546Sopenharmony_ci * making it possible to use one of the accelerated implementations 3537bf215546Sopenharmony_ci */ 3538bf215546Sopenharmony_ci samp->min_img_filter = PIPE_TEX_FILTER_NEAREST; 3539bf215546Sopenharmony_ci 3540bf215546Sopenharmony_ci /* on first access create the lookup table containing the filter weights. */ 3541bf215546Sopenharmony_ci if (!weightLut) { 3542bf215546Sopenharmony_ci create_filter_table(); 3543bf215546Sopenharmony_ci } 3544bf215546Sopenharmony_ci } 3545bf215546Sopenharmony_ci break; 3546bf215546Sopenharmony_ci } 3547bf215546Sopenharmony_ci if (samp->min_img_filter == sampler->mag_img_filter) { 3548bf215546Sopenharmony_ci samp->min_mag_equal = TRUE; 3549bf215546Sopenharmony_ci } 3550bf215546Sopenharmony_ci 3551bf215546Sopenharmony_ci return (void *)samp; 3552bf215546Sopenharmony_ci} 3553bf215546Sopenharmony_ci 3554bf215546Sopenharmony_ci 3555bf215546Sopenharmony_cicompute_lambda_func 3556bf215546Sopenharmony_cisoftpipe_get_lambda_func(const struct pipe_sampler_view *view, 3557bf215546Sopenharmony_ci enum pipe_shader_type shader) 3558bf215546Sopenharmony_ci{ 3559bf215546Sopenharmony_ci if (shader != PIPE_SHADER_FRAGMENT) 3560bf215546Sopenharmony_ci return compute_lambda_vert; 3561bf215546Sopenharmony_ci 3562bf215546Sopenharmony_ci switch (view->target) { 3563bf215546Sopenharmony_ci case PIPE_BUFFER: 3564bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 3565bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 3566bf215546Sopenharmony_ci return compute_lambda_1d; 3567bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 3568bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 3569bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 3570bf215546Sopenharmony_ci return compute_lambda_2d; 3571bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 3572bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 3573bf215546Sopenharmony_ci return compute_lambda_cube; 3574bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 3575bf215546Sopenharmony_ci return compute_lambda_3d; 3576bf215546Sopenharmony_ci default: 3577bf215546Sopenharmony_ci assert(0); 3578bf215546Sopenharmony_ci return compute_lambda_1d; 3579bf215546Sopenharmony_ci } 3580bf215546Sopenharmony_ci} 3581bf215546Sopenharmony_ci 3582bf215546Sopenharmony_ci 3583bf215546Sopenharmony_cistruct pipe_sampler_view * 3584bf215546Sopenharmony_cisoftpipe_create_sampler_view(struct pipe_context *pipe, 3585bf215546Sopenharmony_ci struct pipe_resource *resource, 3586bf215546Sopenharmony_ci const struct pipe_sampler_view *templ) 3587bf215546Sopenharmony_ci{ 3588bf215546Sopenharmony_ci struct sp_sampler_view *sview = CALLOC_STRUCT(sp_sampler_view); 3589bf215546Sopenharmony_ci const struct softpipe_resource *spr = (struct softpipe_resource *)resource; 3590bf215546Sopenharmony_ci 3591bf215546Sopenharmony_ci if (sview) { 3592bf215546Sopenharmony_ci struct pipe_sampler_view *view = &sview->base; 3593bf215546Sopenharmony_ci *view = *templ; 3594bf215546Sopenharmony_ci view->reference.count = 1; 3595bf215546Sopenharmony_ci view->texture = NULL; 3596bf215546Sopenharmony_ci pipe_resource_reference(&view->texture, resource); 3597bf215546Sopenharmony_ci view->context = pipe; 3598bf215546Sopenharmony_ci 3599bf215546Sopenharmony_ci#ifdef DEBUG 3600bf215546Sopenharmony_ci /* 3601bf215546Sopenharmony_ci * This is possibly too lenient, but the primary reason is just 3602bf215546Sopenharmony_ci * to catch gallium frontends which forget to initialize this, so 3603bf215546Sopenharmony_ci * it only catches clearly impossible view targets. 3604bf215546Sopenharmony_ci */ 3605bf215546Sopenharmony_ci if (view->target != resource->target) { 3606bf215546Sopenharmony_ci if (view->target == PIPE_TEXTURE_1D) 3607bf215546Sopenharmony_ci assert(resource->target == PIPE_TEXTURE_1D_ARRAY); 3608bf215546Sopenharmony_ci else if (view->target == PIPE_TEXTURE_1D_ARRAY) 3609bf215546Sopenharmony_ci assert(resource->target == PIPE_TEXTURE_1D); 3610bf215546Sopenharmony_ci else if (view->target == PIPE_TEXTURE_2D) 3611bf215546Sopenharmony_ci assert(resource->target == PIPE_TEXTURE_2D_ARRAY || 3612bf215546Sopenharmony_ci resource->target == PIPE_TEXTURE_CUBE || 3613bf215546Sopenharmony_ci resource->target == PIPE_TEXTURE_CUBE_ARRAY); 3614bf215546Sopenharmony_ci else if (view->target == PIPE_TEXTURE_2D_ARRAY) 3615bf215546Sopenharmony_ci assert(resource->target == PIPE_TEXTURE_2D || 3616bf215546Sopenharmony_ci resource->target == PIPE_TEXTURE_CUBE || 3617bf215546Sopenharmony_ci resource->target == PIPE_TEXTURE_CUBE_ARRAY); 3618bf215546Sopenharmony_ci else if (view->target == PIPE_TEXTURE_CUBE) 3619bf215546Sopenharmony_ci assert(resource->target == PIPE_TEXTURE_CUBE_ARRAY || 3620bf215546Sopenharmony_ci resource->target == PIPE_TEXTURE_2D_ARRAY); 3621bf215546Sopenharmony_ci else if (view->target == PIPE_TEXTURE_CUBE_ARRAY) 3622bf215546Sopenharmony_ci assert(resource->target == PIPE_TEXTURE_CUBE || 3623bf215546Sopenharmony_ci resource->target == PIPE_TEXTURE_2D_ARRAY); 3624bf215546Sopenharmony_ci else 3625bf215546Sopenharmony_ci assert(0); 3626bf215546Sopenharmony_ci } 3627bf215546Sopenharmony_ci#endif 3628bf215546Sopenharmony_ci 3629bf215546Sopenharmony_ci if (any_swizzle(view)) { 3630bf215546Sopenharmony_ci sview->need_swizzle = TRUE; 3631bf215546Sopenharmony_ci } 3632bf215546Sopenharmony_ci 3633bf215546Sopenharmony_ci sview->need_cube_convert = (view->target == PIPE_TEXTURE_CUBE || 3634bf215546Sopenharmony_ci view->target == PIPE_TEXTURE_CUBE_ARRAY); 3635bf215546Sopenharmony_ci sview->pot2d = spr->pot && 3636bf215546Sopenharmony_ci (view->target == PIPE_TEXTURE_2D || 3637bf215546Sopenharmony_ci view->target == PIPE_TEXTURE_RECT); 3638bf215546Sopenharmony_ci 3639bf215546Sopenharmony_ci sview->xpot = util_logbase2( resource->width0 ); 3640bf215546Sopenharmony_ci sview->ypot = util_logbase2( resource->height0 ); 3641bf215546Sopenharmony_ci 3642bf215546Sopenharmony_ci sview->oneval = util_format_is_pure_integer(view->format) ? uif(1) : 1.0f; 3643bf215546Sopenharmony_ci } 3644bf215546Sopenharmony_ci 3645bf215546Sopenharmony_ci return (struct pipe_sampler_view *) sview; 3646bf215546Sopenharmony_ci} 3647bf215546Sopenharmony_ci 3648bf215546Sopenharmony_ci 3649bf215546Sopenharmony_cistatic inline const struct sp_tgsi_sampler * 3650bf215546Sopenharmony_cisp_tgsi_sampler_cast_c(const struct tgsi_sampler *sampler) 3651bf215546Sopenharmony_ci{ 3652bf215546Sopenharmony_ci return (const struct sp_tgsi_sampler *)sampler; 3653bf215546Sopenharmony_ci} 3654bf215546Sopenharmony_ci 3655bf215546Sopenharmony_ci 3656bf215546Sopenharmony_cistatic void 3657bf215546Sopenharmony_cisp_tgsi_get_dims(struct tgsi_sampler *tgsi_sampler, 3658bf215546Sopenharmony_ci const unsigned sview_index, 3659bf215546Sopenharmony_ci int level, int dims[4]) 3660bf215546Sopenharmony_ci{ 3661bf215546Sopenharmony_ci const struct sp_tgsi_sampler *sp_samp = 3662bf215546Sopenharmony_ci sp_tgsi_sampler_cast_c(tgsi_sampler); 3663bf215546Sopenharmony_ci 3664bf215546Sopenharmony_ci assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS); 3665bf215546Sopenharmony_ci /* always have a view here but texture is NULL if no sampler view was set. */ 3666bf215546Sopenharmony_ci if (!sp_samp->sp_sview[sview_index].base.texture) { 3667bf215546Sopenharmony_ci dims[0] = dims[1] = dims[2] = dims[3] = 0; 3668bf215546Sopenharmony_ci return; 3669bf215546Sopenharmony_ci } 3670bf215546Sopenharmony_ci sp_get_dims(&sp_samp->sp_sview[sview_index], level, dims); 3671bf215546Sopenharmony_ci} 3672bf215546Sopenharmony_ci 3673bf215546Sopenharmony_ci 3674bf215546Sopenharmony_cistatic void prepare_compare_values(enum pipe_texture_target target, 3675bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 3676bf215546Sopenharmony_ci const float c0[TGSI_QUAD_SIZE], 3677bf215546Sopenharmony_ci const float c1[TGSI_QUAD_SIZE], 3678bf215546Sopenharmony_ci float pc[TGSI_QUAD_SIZE]) 3679bf215546Sopenharmony_ci{ 3680bf215546Sopenharmony_ci if (target == PIPE_TEXTURE_2D_ARRAY || 3681bf215546Sopenharmony_ci target == PIPE_TEXTURE_CUBE) { 3682bf215546Sopenharmony_ci pc[0] = c0[0]; 3683bf215546Sopenharmony_ci pc[1] = c0[1]; 3684bf215546Sopenharmony_ci pc[2] = c0[2]; 3685bf215546Sopenharmony_ci pc[3] = c0[3]; 3686bf215546Sopenharmony_ci } else if (target == PIPE_TEXTURE_CUBE_ARRAY) { 3687bf215546Sopenharmony_ci pc[0] = c1[0]; 3688bf215546Sopenharmony_ci pc[1] = c1[1]; 3689bf215546Sopenharmony_ci pc[2] = c1[2]; 3690bf215546Sopenharmony_ci pc[3] = c1[3]; 3691bf215546Sopenharmony_ci } else { 3692bf215546Sopenharmony_ci pc[0] = p[0]; 3693bf215546Sopenharmony_ci pc[1] = p[1]; 3694bf215546Sopenharmony_ci pc[2] = p[2]; 3695bf215546Sopenharmony_ci pc[3] = p[3]; 3696bf215546Sopenharmony_ci } 3697bf215546Sopenharmony_ci} 3698bf215546Sopenharmony_ci 3699bf215546Sopenharmony_cistatic void 3700bf215546Sopenharmony_cisp_tgsi_get_samples(struct tgsi_sampler *tgsi_sampler, 3701bf215546Sopenharmony_ci const unsigned sview_index, 3702bf215546Sopenharmony_ci const unsigned sampler_index, 3703bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 3704bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 3705bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 3706bf215546Sopenharmony_ci const float c0[TGSI_QUAD_SIZE], 3707bf215546Sopenharmony_ci const float lod_in[TGSI_QUAD_SIZE], 3708bf215546Sopenharmony_ci float derivs[3][2][TGSI_QUAD_SIZE], 3709bf215546Sopenharmony_ci const int8_t offset[3], 3710bf215546Sopenharmony_ci enum tgsi_sampler_control control, 3711bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 3712bf215546Sopenharmony_ci{ 3713bf215546Sopenharmony_ci const struct sp_tgsi_sampler *sp_tgsi_samp = 3714bf215546Sopenharmony_ci sp_tgsi_sampler_cast_c(tgsi_sampler); 3715bf215546Sopenharmony_ci struct sp_sampler_view sp_sview; 3716bf215546Sopenharmony_ci const struct sp_sampler *sp_samp; 3717bf215546Sopenharmony_ci struct filter_args filt_args; 3718bf215546Sopenharmony_ci float compare_values[TGSI_QUAD_SIZE]; 3719bf215546Sopenharmony_ci float lod[TGSI_QUAD_SIZE]; 3720bf215546Sopenharmony_ci int c; 3721bf215546Sopenharmony_ci 3722bf215546Sopenharmony_ci assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS); 3723bf215546Sopenharmony_ci assert(sampler_index < PIPE_MAX_SAMPLERS); 3724bf215546Sopenharmony_ci assert(sp_tgsi_samp->sp_sampler[sampler_index]); 3725bf215546Sopenharmony_ci 3726bf215546Sopenharmony_ci memcpy(&sp_sview, &sp_tgsi_samp->sp_sview[sview_index], 3727bf215546Sopenharmony_ci sizeof(struct sp_sampler_view)); 3728bf215546Sopenharmony_ci sp_samp = sp_tgsi_samp->sp_sampler[sampler_index]; 3729bf215546Sopenharmony_ci 3730bf215546Sopenharmony_ci if (util_format_is_unorm(sp_sview.base.format)) { 3731bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 3732bf215546Sopenharmony_ci sp_sview.border_color.f[c] = CLAMP(sp_samp->base.border_color.f[c], 3733bf215546Sopenharmony_ci 0.0f, 1.0f); 3734bf215546Sopenharmony_ci } else if (util_format_is_snorm(sp_sview.base.format)) { 3735bf215546Sopenharmony_ci for (c = 0; c < TGSI_NUM_CHANNELS; c++) 3736bf215546Sopenharmony_ci sp_sview.border_color.f[c] = CLAMP(sp_samp->base.border_color.f[c], 3737bf215546Sopenharmony_ci -1.0f, 1.0f); 3738bf215546Sopenharmony_ci } else { 3739bf215546Sopenharmony_ci memcpy(sp_sview.border_color.f, sp_samp->base.border_color.f, 3740bf215546Sopenharmony_ci TGSI_NUM_CHANNELS * sizeof(float)); 3741bf215546Sopenharmony_ci } 3742bf215546Sopenharmony_ci 3743bf215546Sopenharmony_ci /* always have a view here but texture is NULL if no sampler view was set. */ 3744bf215546Sopenharmony_ci if (!sp_sview.base.texture) { 3745bf215546Sopenharmony_ci int i, j; 3746bf215546Sopenharmony_ci for (j = 0; j < TGSI_NUM_CHANNELS; j++) { 3747bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) { 3748bf215546Sopenharmony_ci rgba[j][i] = 0.0f; 3749bf215546Sopenharmony_ci } 3750bf215546Sopenharmony_ci } 3751bf215546Sopenharmony_ci return; 3752bf215546Sopenharmony_ci } 3753bf215546Sopenharmony_ci 3754bf215546Sopenharmony_ci if (sp_samp->base.compare_mode != PIPE_TEX_COMPARE_NONE) 3755bf215546Sopenharmony_ci prepare_compare_values(sp_sview.base.target, p, c0, lod_in, compare_values); 3756bf215546Sopenharmony_ci 3757bf215546Sopenharmony_ci filt_args.control = control; 3758bf215546Sopenharmony_ci filt_args.offset = offset; 3759bf215546Sopenharmony_ci int gather_comp = get_gather_component(lod_in); 3760bf215546Sopenharmony_ci 3761bf215546Sopenharmony_ci compute_lambda_lod(&sp_sview, sp_samp, s, t, p, derivs, lod_in, control, lod); 3762bf215546Sopenharmony_ci 3763bf215546Sopenharmony_ci if (sp_sview.need_cube_convert) { 3764bf215546Sopenharmony_ci float cs[TGSI_QUAD_SIZE]; 3765bf215546Sopenharmony_ci float ct[TGSI_QUAD_SIZE]; 3766bf215546Sopenharmony_ci float cp[TGSI_QUAD_SIZE]; 3767bf215546Sopenharmony_ci uint faces[TGSI_QUAD_SIZE]; 3768bf215546Sopenharmony_ci 3769bf215546Sopenharmony_ci convert_cube(&sp_sview, sp_samp, s, t, p, c0, cs, ct, cp, faces); 3770bf215546Sopenharmony_ci 3771bf215546Sopenharmony_ci filt_args.faces = faces; 3772bf215546Sopenharmony_ci sample_mip(&sp_sview, sp_samp, cs, ct, cp, compare_values, gather_comp, lod, &filt_args, rgba); 3773bf215546Sopenharmony_ci } else { 3774bf215546Sopenharmony_ci static const uint zero_faces[TGSI_QUAD_SIZE] = {0, 0, 0, 0}; 3775bf215546Sopenharmony_ci 3776bf215546Sopenharmony_ci filt_args.faces = zero_faces; 3777bf215546Sopenharmony_ci sample_mip(&sp_sview, sp_samp, s, t, p, compare_values, gather_comp, lod, &filt_args, rgba); 3778bf215546Sopenharmony_ci } 3779bf215546Sopenharmony_ci} 3780bf215546Sopenharmony_ci 3781bf215546Sopenharmony_cistatic void 3782bf215546Sopenharmony_cisp_tgsi_query_lod(const struct tgsi_sampler *tgsi_sampler, 3783bf215546Sopenharmony_ci const unsigned sview_index, 3784bf215546Sopenharmony_ci const unsigned sampler_index, 3785bf215546Sopenharmony_ci const float s[TGSI_QUAD_SIZE], 3786bf215546Sopenharmony_ci const float t[TGSI_QUAD_SIZE], 3787bf215546Sopenharmony_ci const float p[TGSI_QUAD_SIZE], 3788bf215546Sopenharmony_ci const float c0[TGSI_QUAD_SIZE], 3789bf215546Sopenharmony_ci const enum tgsi_sampler_control control, 3790bf215546Sopenharmony_ci float mipmap[TGSI_QUAD_SIZE], 3791bf215546Sopenharmony_ci float lod[TGSI_QUAD_SIZE]) 3792bf215546Sopenharmony_ci{ 3793bf215546Sopenharmony_ci static const float lod_in[TGSI_QUAD_SIZE] = { 0.0, 0.0, 0.0, 0.0 }; 3794bf215546Sopenharmony_ci static const float dummy_grad[3][2][TGSI_QUAD_SIZE]; 3795bf215546Sopenharmony_ci 3796bf215546Sopenharmony_ci const struct sp_tgsi_sampler *sp_tgsi_samp = 3797bf215546Sopenharmony_ci sp_tgsi_sampler_cast_c(tgsi_sampler); 3798bf215546Sopenharmony_ci const struct sp_sampler_view *sp_sview; 3799bf215546Sopenharmony_ci const struct sp_sampler *sp_samp; 3800bf215546Sopenharmony_ci const struct sp_filter_funcs *funcs; 3801bf215546Sopenharmony_ci int i; 3802bf215546Sopenharmony_ci 3803bf215546Sopenharmony_ci assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS); 3804bf215546Sopenharmony_ci assert(sampler_index < PIPE_MAX_SAMPLERS); 3805bf215546Sopenharmony_ci assert(sp_tgsi_samp->sp_sampler[sampler_index]); 3806bf215546Sopenharmony_ci 3807bf215546Sopenharmony_ci sp_sview = &sp_tgsi_samp->sp_sview[sview_index]; 3808bf215546Sopenharmony_ci sp_samp = sp_tgsi_samp->sp_sampler[sampler_index]; 3809bf215546Sopenharmony_ci /* always have a view here but texture is NULL if no sampler view was 3810bf215546Sopenharmony_ci * set. */ 3811bf215546Sopenharmony_ci if (!sp_sview->base.texture) { 3812bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) { 3813bf215546Sopenharmony_ci mipmap[i] = 0.0f; 3814bf215546Sopenharmony_ci lod[i] = 0.0f; 3815bf215546Sopenharmony_ci } 3816bf215546Sopenharmony_ci return; 3817bf215546Sopenharmony_ci } 3818bf215546Sopenharmony_ci compute_lambda_lod_unclamped(sp_sview, sp_samp, 3819bf215546Sopenharmony_ci s, t, p, dummy_grad, lod_in, control, lod); 3820bf215546Sopenharmony_ci 3821bf215546Sopenharmony_ci get_filters(sp_sview, sp_samp, control, &funcs, NULL, NULL); 3822bf215546Sopenharmony_ci funcs->relative_level(sp_sview, sp_samp, lod, mipmap); 3823bf215546Sopenharmony_ci} 3824bf215546Sopenharmony_ci 3825bf215546Sopenharmony_cistatic void 3826bf215546Sopenharmony_cisp_tgsi_get_texel(struct tgsi_sampler *tgsi_sampler, 3827bf215546Sopenharmony_ci const unsigned sview_index, 3828bf215546Sopenharmony_ci const int i[TGSI_QUAD_SIZE], 3829bf215546Sopenharmony_ci const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE], 3830bf215546Sopenharmony_ci const int lod[TGSI_QUAD_SIZE], const int8_t offset[3], 3831bf215546Sopenharmony_ci float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 3832bf215546Sopenharmony_ci{ 3833bf215546Sopenharmony_ci const struct sp_tgsi_sampler *sp_samp = 3834bf215546Sopenharmony_ci sp_tgsi_sampler_cast_c(tgsi_sampler); 3835bf215546Sopenharmony_ci 3836bf215546Sopenharmony_ci assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS); 3837bf215546Sopenharmony_ci /* always have a view here but texture is NULL if no sampler view was set. */ 3838bf215546Sopenharmony_ci if (!sp_samp->sp_sview[sview_index].base.texture) { 3839bf215546Sopenharmony_ci int i, j; 3840bf215546Sopenharmony_ci for (j = 0; j < TGSI_NUM_CHANNELS; j++) { 3841bf215546Sopenharmony_ci for (i = 0; i < TGSI_QUAD_SIZE; i++) { 3842bf215546Sopenharmony_ci rgba[j][i] = 0.0f; 3843bf215546Sopenharmony_ci } 3844bf215546Sopenharmony_ci } 3845bf215546Sopenharmony_ci return; 3846bf215546Sopenharmony_ci } 3847bf215546Sopenharmony_ci sp_get_texels(&sp_samp->sp_sview[sview_index], i, j, k, lod, offset, rgba); 3848bf215546Sopenharmony_ci} 3849bf215546Sopenharmony_ci 3850bf215546Sopenharmony_ci 3851bf215546Sopenharmony_cistruct sp_tgsi_sampler * 3852bf215546Sopenharmony_cisp_create_tgsi_sampler(void) 3853bf215546Sopenharmony_ci{ 3854bf215546Sopenharmony_ci struct sp_tgsi_sampler *samp = CALLOC_STRUCT(sp_tgsi_sampler); 3855bf215546Sopenharmony_ci if (!samp) 3856bf215546Sopenharmony_ci return NULL; 3857bf215546Sopenharmony_ci 3858bf215546Sopenharmony_ci samp->base.get_dims = sp_tgsi_get_dims; 3859bf215546Sopenharmony_ci samp->base.get_samples = sp_tgsi_get_samples; 3860bf215546Sopenharmony_ci samp->base.get_texel = sp_tgsi_get_texel; 3861bf215546Sopenharmony_ci samp->base.query_lod = sp_tgsi_query_lod; 3862bf215546Sopenharmony_ci 3863bf215546Sopenharmony_ci return samp; 3864bf215546Sopenharmony_ci} 3865