sp_tex_sample.c revision 3d53d38d5e35386de4793162b9dd32e171927059
10dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul/**************************************************************************
20dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul *
30dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
40dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * All Rights Reserved.
50dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul *
60dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * Permission is hereby granted, free of charge, to any person obtaining a
70dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * copy of this software and associated documentation files (the
80dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * "Software"), to deal in the Software without restriction, including
90dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * without limitation the rights to use, copy, modify, merge, publish,
100dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * distribute, sub license, and/or sell copies of the Software, and to
110dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * permit persons to whom the Software is furnished to do so, subject to
120dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * the following conditions:
130dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul *
140dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * The above copyright notice and this permission notice (including the
150dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * next paragraph) shall be included in all copies or substantial portions
160dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * of the Software.
170dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul *
180dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
190dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
200dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
210dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
220dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
230dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
240dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
250dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul *
260dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul **************************************************************************/
270dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
280dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul/**
290dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * Texture sampling
300dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul *
310dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * Authors:
320dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul *   Brian Paul
330dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul */
340dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
3508f33a025100dea2d951e6d628891fe294b18082Brian Paul#include "sp_context.h"
36b91de8a6e7d74d38698b6dad9f34040e484e69afBrian Paul#include "sp_headers.h"
370dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul#include "sp_surface.h"
380dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul#include "sp_tex_sample.h"
3970eb7996f265f3634dabda078f13d1be3533cc65Brian Paul#include "sp_tile_cache.h"
400dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul#include "pipe/p_context.h"
410dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul#include "pipe/p_defines.h"
427de874ec2c7b9e3aff7f81b7e30045b45381fbadMichal Krol#include "pipe/p_util.h"
436acd63a4980951727939c0dd545a0324965b3834José Fonseca#include "tgsi/exec/tgsi_exec.h"
440dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
450dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
4608f33a025100dea2d951e6d628891fe294b18082Brian Paul/*
4708f33a025100dea2d951e6d628891fe294b18082Brian Paul * Note, the FRAC macro has to work perfectly.  Otherwise you'll sometimes
4808f33a025100dea2d951e6d628891fe294b18082Brian Paul * see 1-pixel bands of improperly weighted linear-filtered textures.
4908f33a025100dea2d951e6d628891fe294b18082Brian Paul * The tests/texwrap.c demo is a good test.
5008f33a025100dea2d951e6d628891fe294b18082Brian Paul * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
5108f33a025100dea2d951e6d628891fe294b18082Brian Paul * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
5208f33a025100dea2d951e6d628891fe294b18082Brian Paul */
5370af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell#define FRAC(f)  ((f) - ifloor(f))
5408f33a025100dea2d951e6d628891fe294b18082Brian Paul
5508f33a025100dea2d951e6d628891fe294b18082Brian Paul
5608f33a025100dea2d951e6d628891fe294b18082Brian Paul/**
5708f33a025100dea2d951e6d628891fe294b18082Brian Paul * Linear interpolation macro
5808f33a025100dea2d951e6d628891fe294b18082Brian Paul */
590dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
600dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
610dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
620dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul/**
630dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * Do 2D/biliner interpolation of float values.
640dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * v00, v10, v01 and v11 are typically four texture samples in a square/box.
650dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * a and b are the horizontal and vertical interpolants.
660dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * It's important that this function is inlined when compiled with
670dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * optimization!  If we find that's not true on some systems, convert
680dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul * to a macro.
690dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul */
70b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paulstatic INLINE float
71b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paullerp_2d(float a, float b,
72b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul        float v00, float v10, float v01, float v11)
730dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul{
74b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   const float temp0 = LERP(a, v00, v10);
75b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   const float temp1 = LERP(a, v01, v11);
760dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   return LERP(b, temp0, temp1);
770dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul}
780dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
790dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
800dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul/**
81906768316d9521a32d9a7eebc9edaf76c06a98a7Brian Paul * If A is a signed integer, A % B doesn't give the right value for A < 0
82906768316d9521a32d9a7eebc9edaf76c06a98a7Brian Paul * (in terms of texture repeat).  Just casting to unsigned fixes that.
830dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul */
84906768316d9521a32d9a7eebc9edaf76c06a98a7Brian Paul#define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B))
8508f33a025100dea2d951e6d628891fe294b18082Brian Paul
8608f33a025100dea2d951e6d628891fe294b18082Brian Paul
8708f33a025100dea2d951e6d628891fe294b18082Brian Paul/**
8808f33a025100dea2d951e6d628891fe294b18082Brian Paul * Apply texture coord wrapping mode and return integer texture index.
8908f33a025100dea2d951e6d628891fe294b18082Brian Paul * \param wrapMode  PIPE_TEX_WRAP_x
9008f33a025100dea2d951e6d628891fe294b18082Brian Paul * \param s  the texcoord
9108f33a025100dea2d951e6d628891fe294b18082Brian Paul * \param size  the texture image size
9208f33a025100dea2d951e6d628891fe294b18082Brian Paul * \return  integer texture index
9308f33a025100dea2d951e6d628891fe294b18082Brian Paul */
9470af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwellstatic INLINE int
9570af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwellnearest_texcoord(unsigned wrapMode, float s, unsigned size)
960dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul{
9770af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell   int i;
980dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   switch (wrapMode) {
990dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   case PIPE_TEX_WRAP_REPEAT:
10008f33a025100dea2d951e6d628891fe294b18082Brian Paul      /* s limited to [0,1) */
10108f33a025100dea2d951e6d628891fe294b18082Brian Paul      /* i limited to [0,size-1] */
10270af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell      i = ifloor(s * size);
103906768316d9521a32d9a7eebc9edaf76c06a98a7Brian Paul      i = REMAINDER(i, size);
10408f33a025100dea2d951e6d628891fe294b18082Brian Paul      return i;
1050dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   case PIPE_TEX_WRAP_CLAMP:
10608f33a025100dea2d951e6d628891fe294b18082Brian Paul      /* s limited to [0,1] */
10708f33a025100dea2d951e6d628891fe294b18082Brian Paul      /* i limited to [0,size-1] */
10808f33a025100dea2d951e6d628891fe294b18082Brian Paul      if (s <= 0.0F)
10908f33a025100dea2d951e6d628891fe294b18082Brian Paul         i = 0;
11008f33a025100dea2d951e6d628891fe294b18082Brian Paul      else if (s >= 1.0F)
11108f33a025100dea2d951e6d628891fe294b18082Brian Paul         i = size - 1;
11208f33a025100dea2d951e6d628891fe294b18082Brian Paul      else
11370af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell         i = ifloor(s * size);
11408f33a025100dea2d951e6d628891fe294b18082Brian Paul      return i;
11508f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
11608f33a025100dea2d951e6d628891fe294b18082Brian Paul      {
11708f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* s limited to [min,max] */
11808f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* i limited to [0, size-1] */
119b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float min = 1.0F / (2.0F * size);
120b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float max = 1.0F - min;
12108f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (s < min)
12208f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = 0;
12308f33a025100dea2d951e6d628891fe294b18082Brian Paul         else if (s > max)
12408f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = size - 1;
12508f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
12670af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell            i = ifloor(s * size);
12708f33a025100dea2d951e6d628891fe294b18082Brian Paul      }
12808f33a025100dea2d951e6d628891fe294b18082Brian Paul      return i;
12908f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
13008f33a025100dea2d951e6d628891fe294b18082Brian Paul      {
13108f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* s limited to [min,max] */
13208f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* i limited to [-1, size] */
133b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float min = -1.0F / (2.0F * size);
134b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float max = 1.0F - min;
13508f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (s <= min)
13608f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = -1;
13708f33a025100dea2d951e6d628891fe294b18082Brian Paul         else if (s >= max)
13808f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = size;
13908f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
14070af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell            i = ifloor(s * size);
14108f33a025100dea2d951e6d628891fe294b18082Brian Paul      }
14208f33a025100dea2d951e6d628891fe294b18082Brian Paul      return i;
14308f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_MIRROR_REPEAT:
14408f33a025100dea2d951e6d628891fe294b18082Brian Paul      {
145b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float min = 1.0F / (2.0F * size);
146b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float max = 1.0F - min;
14770af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell         const int flr = ifloor(s);
148b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         float u;
14908f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (flr & 1)
150b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul            u = 1.0F - (s - (float) flr);
15108f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
152b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul            u = s - (float) flr;
15308f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (u < min)
15408f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = 0;
15508f33a025100dea2d951e6d628891fe294b18082Brian Paul         else if (u > max)
15608f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = size - 1;
15708f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
15870af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell            i = ifloor(u * size);
15908f33a025100dea2d951e6d628891fe294b18082Brian Paul      }
16008f33a025100dea2d951e6d628891fe294b18082Brian Paul      return i;
16108f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_MIRROR_CLAMP:
16208f33a025100dea2d951e6d628891fe294b18082Brian Paul      {
16308f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* s limited to [0,1] */
16408f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* i limited to [0,size-1] */
165b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float u = FABSF(s);
16608f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (u <= 0.0F)
16708f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = 0;
16808f33a025100dea2d951e6d628891fe294b18082Brian Paul         else if (u >= 1.0F)
16908f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = size - 1;
17008f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
17170af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell            i = ifloor(u * size);
17208f33a025100dea2d951e6d628891fe294b18082Brian Paul      }
17308f33a025100dea2d951e6d628891fe294b18082Brian Paul      return i;
17408f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
17508f33a025100dea2d951e6d628891fe294b18082Brian Paul      {
17608f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* s limited to [min,max] */
17708f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* i limited to [0, size-1] */
178b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float min = 1.0F / (2.0F * size);
179b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float max = 1.0F - min;
180b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float u = FABSF(s);
18108f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (u < min)
18208f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = 0;
18308f33a025100dea2d951e6d628891fe294b18082Brian Paul         else if (u > max)
18408f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = size - 1;
18508f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
18670af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell            i = ifloor(u * size);
18708f33a025100dea2d951e6d628891fe294b18082Brian Paul      }
18808f33a025100dea2d951e6d628891fe294b18082Brian Paul      return i;
18908f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
19008f33a025100dea2d951e6d628891fe294b18082Brian Paul      {
19108f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* s limited to [min,max] */
19208f33a025100dea2d951e6d628891fe294b18082Brian Paul         /* i limited to [0, size-1] */
193b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float min = -1.0F / (2.0F * size);
194b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float max = 1.0F - min;
195b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float u = FABSF(s);
19608f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (u < min)
19708f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = -1;
19808f33a025100dea2d951e6d628891fe294b18082Brian Paul         else if (u > max)
19908f33a025100dea2d951e6d628891fe294b18082Brian Paul            i = size;
20008f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
20170af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell            i = ifloor(u * size);
20208f33a025100dea2d951e6d628891fe294b18082Brian Paul      }
20308f33a025100dea2d951e6d628891fe294b18082Brian Paul      return i;
2040dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   default:
2050dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul      assert(0);
20608f33a025100dea2d951e6d628891fe294b18082Brian Paul      return 0;
2070dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   }
2080dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul}
2090dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
21008f33a025100dea2d951e6d628891fe294b18082Brian Paul
21108f33a025100dea2d951e6d628891fe294b18082Brian Paul/**
21208f33a025100dea2d951e6d628891fe294b18082Brian Paul * Used to compute texel locations for linear sampling.
21308f33a025100dea2d951e6d628891fe294b18082Brian Paul * \param wrapMode  PIPE_TEX_WRAP_x
21408f33a025100dea2d951e6d628891fe294b18082Brian Paul * \param s  the texcoord
21508f33a025100dea2d951e6d628891fe294b18082Brian Paul * \param size  the texture image size
21608f33a025100dea2d951e6d628891fe294b18082Brian Paul * \param i0  returns first texture index
21708f33a025100dea2d951e6d628891fe294b18082Brian Paul * \param i1  returns second texture index (usually *i0 + 1)
21808f33a025100dea2d951e6d628891fe294b18082Brian Paul * \param a  returns blend factor/weight between texture indexes
21908f33a025100dea2d951e6d628891fe294b18082Brian Paul */
2200dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paulstatic INLINE void
22170af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwelllinear_texcoord(unsigned wrapMode, float s, unsigned size,
22270af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell                int *i0, int *i1, float *a)
2230dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul{
224b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   float u;
2250dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   switch (wrapMode) {
2260dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   case PIPE_TEX_WRAP_REPEAT:
22708f33a025100dea2d951e6d628891fe294b18082Brian Paul      u = s * size - 0.5F;
228906768316d9521a32d9a7eebc9edaf76c06a98a7Brian Paul      *i0 = REMAINDER(ifloor(u), size);
229906768316d9521a32d9a7eebc9edaf76c06a98a7Brian Paul      *i1 = REMAINDER(*i0 + 1, size);
2300dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul      break;
2310dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   case PIPE_TEX_WRAP_CLAMP:
23208f33a025100dea2d951e6d628891fe294b18082Brian Paul      if (s <= 0.0F)
23308f33a025100dea2d951e6d628891fe294b18082Brian Paul         u = 0.0F;
23408f33a025100dea2d951e6d628891fe294b18082Brian Paul      else if (s >= 1.0F)
235b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         u = (float) size;
23608f33a025100dea2d951e6d628891fe294b18082Brian Paul      else
23708f33a025100dea2d951e6d628891fe294b18082Brian Paul         u = s * size;
23808f33a025100dea2d951e6d628891fe294b18082Brian Paul      u -= 0.5F;
23970af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell      *i0 = ifloor(u);
24008f33a025100dea2d951e6d628891fe294b18082Brian Paul      *i1 = *i0 + 1;
24108f33a025100dea2d951e6d628891fe294b18082Brian Paul      break;
24208f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
24308f33a025100dea2d951e6d628891fe294b18082Brian Paul      if (s <= 0.0F)
24408f33a025100dea2d951e6d628891fe294b18082Brian Paul         u = 0.0F;
24508f33a025100dea2d951e6d628891fe294b18082Brian Paul      else if (s >= 1.0F)
246b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         u = (float) size;
24708f33a025100dea2d951e6d628891fe294b18082Brian Paul      else
24808f33a025100dea2d951e6d628891fe294b18082Brian Paul         u = s * size;
24908f33a025100dea2d951e6d628891fe294b18082Brian Paul      u -= 0.5F;
25070af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell      *i0 = ifloor(u);
25108f33a025100dea2d951e6d628891fe294b18082Brian Paul      *i1 = *i0 + 1;
25208f33a025100dea2d951e6d628891fe294b18082Brian Paul      if (*i0 < 0)
25308f33a025100dea2d951e6d628891fe294b18082Brian Paul         *i0 = 0;
25470af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell      if (*i1 >= (int) size)
25508f33a025100dea2d951e6d628891fe294b18082Brian Paul         *i1 = size - 1;
25608f33a025100dea2d951e6d628891fe294b18082Brian Paul      break;
25708f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
25808f33a025100dea2d951e6d628891fe294b18082Brian Paul      {
259b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float min = -1.0F / (2.0F * size);
260b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float max = 1.0F - min;
26108f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (s <= min)
26208f33a025100dea2d951e6d628891fe294b18082Brian Paul            u = min * size;
26308f33a025100dea2d951e6d628891fe294b18082Brian Paul         else if (s >= max)
26408f33a025100dea2d951e6d628891fe294b18082Brian Paul            u = max * size;
26508f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
26608f33a025100dea2d951e6d628891fe294b18082Brian Paul            u = s * size;
26708f33a025100dea2d951e6d628891fe294b18082Brian Paul         u -= 0.5F;
26870af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell         *i0 = ifloor(u);
26908f33a025100dea2d951e6d628891fe294b18082Brian Paul         *i1 = *i0 + 1;
27008f33a025100dea2d951e6d628891fe294b18082Brian Paul      }
27108f33a025100dea2d951e6d628891fe294b18082Brian Paul      break;
27208f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_MIRROR_REPEAT:
27308f33a025100dea2d951e6d628891fe294b18082Brian Paul      {
27470af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell         const int flr = ifloor(s);
27508f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (flr & 1)
276b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul            u = 1.0F - (s - (float) flr);
27708f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
278b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul            u = s - (float) flr;
27908f33a025100dea2d951e6d628891fe294b18082Brian Paul         u = (u * size) - 0.5F;
28070af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell         *i0 = ifloor(u);
28108f33a025100dea2d951e6d628891fe294b18082Brian Paul         *i1 = *i0 + 1;
28208f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (*i0 < 0)
28308f33a025100dea2d951e6d628891fe294b18082Brian Paul            *i0 = 0;
28470af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell         if (*i1 >= (int) size)
28508f33a025100dea2d951e6d628891fe294b18082Brian Paul            *i1 = size - 1;
28608f33a025100dea2d951e6d628891fe294b18082Brian Paul      }
28708f33a025100dea2d951e6d628891fe294b18082Brian Paul      break;
28808f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_MIRROR_CLAMP:
28908f33a025100dea2d951e6d628891fe294b18082Brian Paul      u = FABSF(s);
29008f33a025100dea2d951e6d628891fe294b18082Brian Paul      if (u >= 1.0F)
291b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         u = (float) size;
29208f33a025100dea2d951e6d628891fe294b18082Brian Paul      else
29308f33a025100dea2d951e6d628891fe294b18082Brian Paul         u *= size;
29408f33a025100dea2d951e6d628891fe294b18082Brian Paul      u -= 0.5F;
29570af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell      *i0 = ifloor(u);
29608f33a025100dea2d951e6d628891fe294b18082Brian Paul      *i1 = *i0 + 1;
29708f33a025100dea2d951e6d628891fe294b18082Brian Paul      break;
29808f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
29908f33a025100dea2d951e6d628891fe294b18082Brian Paul      u = FABSF(s);
30008f33a025100dea2d951e6d628891fe294b18082Brian Paul      if (u >= 1.0F)
301b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         u = (float) size;
30208f33a025100dea2d951e6d628891fe294b18082Brian Paul      else
30308f33a025100dea2d951e6d628891fe294b18082Brian Paul         u *= size;
30408f33a025100dea2d951e6d628891fe294b18082Brian Paul      u -= 0.5F;
30570af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell      *i0 = ifloor(u);
30608f33a025100dea2d951e6d628891fe294b18082Brian Paul      *i1 = *i0 + 1;
30708f33a025100dea2d951e6d628891fe294b18082Brian Paul      if (*i0 < 0)
30808f33a025100dea2d951e6d628891fe294b18082Brian Paul         *i0 = 0;
30970af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell      if (*i1 >= (int) size)
31008f33a025100dea2d951e6d628891fe294b18082Brian Paul         *i1 = size - 1;
31108f33a025100dea2d951e6d628891fe294b18082Brian Paul      break;
31208f33a025100dea2d951e6d628891fe294b18082Brian Paul   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
31308f33a025100dea2d951e6d628891fe294b18082Brian Paul      {
314b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float min = -1.0F / (2.0F * size);
315b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         const float max = 1.0F - min;
31608f33a025100dea2d951e6d628891fe294b18082Brian Paul         u = FABSF(s);
31708f33a025100dea2d951e6d628891fe294b18082Brian Paul         if (u <= min)
31808f33a025100dea2d951e6d628891fe294b18082Brian Paul            u = min * size;
31908f33a025100dea2d951e6d628891fe294b18082Brian Paul         else if (u >= max)
32008f33a025100dea2d951e6d628891fe294b18082Brian Paul            u = max * size;
32108f33a025100dea2d951e6d628891fe294b18082Brian Paul         else
32208f33a025100dea2d951e6d628891fe294b18082Brian Paul            u *= size;
32308f33a025100dea2d951e6d628891fe294b18082Brian Paul         u -= 0.5F;
32470af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell         *i0 = ifloor(u);
32508f33a025100dea2d951e6d628891fe294b18082Brian Paul         *i1 = *i0 + 1;
32608f33a025100dea2d951e6d628891fe294b18082Brian Paul      }
3270dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul      break;
3280dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   default:
3290dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul      assert(0);
3300dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   }
33108f33a025100dea2d951e6d628891fe294b18082Brian Paul   *a = FRAC(u);
3320dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul}
3330dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
3340dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul
335b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul/**
336b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul * For RECT textures / unnormalized texcoords
337b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul * Only a subset of wrap modes supported.
338b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul */
339b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paulstatic INLINE int
340b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paulnearest_texcoord_unnorm(unsigned wrapMode, float s, unsigned size)
341b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul{
342b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   int i;
343b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   switch (wrapMode) {
344b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   case PIPE_TEX_WRAP_CLAMP:
345b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      i = ifloor(s);
34669a7c9739bc0f11e66e11ab410d813fa69fe5fc9Michal Krol      return CLAMP(i, 0, (int) size-1);
347b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
348b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      /* fall-through */
349b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
3504ec46e4869b60b60c7ddf43168604713b5c4c359Brian Paul      return ifloor( CLAMP(s, 0.5F, (float) size - 0.5F) );
351b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   default:
352b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      assert(0);
353b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      return 0;
354b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   }
355b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul}
356b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
357b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
358b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul/**
359b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul * For RECT textures / unnormalized texcoords.
360b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul * Only a subset of wrap modes supported.
361b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul */
362b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paulstatic INLINE void
363b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paullinear_texcoord_unnorm(unsigned wrapMode, float s, unsigned size,
364b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul                       int *i0, int *i1, float *a)
365b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul{
366b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   switch (wrapMode) {
367b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   case PIPE_TEX_WRAP_CLAMP:
368b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      /* Not exactly what the spec says, but it matches NVIDIA output */
36969a7c9739bc0f11e66e11ab410d813fa69fe5fc9Michal Krol      s = CLAMP(s - 0.5F, 0.0f, (float) size - 1.0f);
370b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      *i0 = ifloor(s);
371b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      *i1 = *i0 + 1;
372b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      break;
373b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
374b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      /* fall-through */
375b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
3764ec46e4869b60b60c7ddf43168604713b5c4c359Brian Paul      s = CLAMP(s, 0.5F, (float) size - 0.5F);
377b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      s -= 0.5F;
378b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      *i0 = ifloor(s);
379b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      *i1 = *i0 + 1;
38069a7c9739bc0f11e66e11ab410d813fa69fe5fc9Michal Krol      if (*i1 > (int) size - 1)
381b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         *i1 = size - 1;
382b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      break;
383b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   default:
384b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      assert(0);
385b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   }
386b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   *a = FRAC(s);
387b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul}
388b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
389b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
39070af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwellstatic unsigned
391a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paulchoose_cube_face(float rx, float ry, float rz, float *newS, float *newT)
39234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul{
39334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   /*
39434a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      major axis
39534a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      direction     target                             sc     tc    ma
39634a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      ----------    -------------------------------    ---    ---   ---
39734a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul       +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
39834a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul       -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
39934a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul       +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
40034a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul       -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
40134a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul       +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
40234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul       -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
40334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   */
404b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   const float arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz);
40570af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell   unsigned face;
406b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   float sc, tc, ma;
40734a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
40834a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   if (arx > ary && arx > arz) {
40934a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      if (rx >= 0.0F) {
41034a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         face = PIPE_TEX_FACE_POS_X;
41134a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         sc = -rz;
41234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         tc = -ry;
41334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         ma = arx;
41434a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      }
41534a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      else {
41634a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         face = PIPE_TEX_FACE_NEG_X;
41734a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         sc = rz;
41834a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         tc = -ry;
41934a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         ma = arx;
42034a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      }
42134a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   }
42234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   else if (ary > arx && ary > arz) {
42334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      if (ry >= 0.0F) {
42434a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         face = PIPE_TEX_FACE_POS_Y;
42534a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         sc = rx;
42634a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         tc = rz;
42734a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         ma = ary;
42834a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      }
42934a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      else {
43034a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         face = PIPE_TEX_FACE_NEG_Y;
43134a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         sc = rx;
43234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         tc = -rz;
43334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         ma = ary;
43434a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      }
43534a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   }
43634a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   else {
43734a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      if (rz > 0.0F) {
43834a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         face = PIPE_TEX_FACE_POS_Z;
43934a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         sc = rx;
44034a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         tc = -ry;
44134a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         ma = arz;
44234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      }
44334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      else {
44434a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         face = PIPE_TEX_FACE_NEG_Z;
44534a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         sc = -rx;
44634a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         tc = -ry;
44734a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul         ma = arz;
44834a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      }
44934a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   }
45034a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
451a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul   *newS = ( sc / ma + 1.0F ) * 0.5F;
452a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul   *newT = ( tc / ma + 1.0F ) * 0.5F;
45334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
45434a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   return face;
45534a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul}
45634a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
45734a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
458b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul/**
459b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul * Examine the quad's texture coordinates to compute the partial
460b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul * derivatives w.r.t X and Y, then compute lambda (level of detail).
461b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul *
462b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul * This is only done for fragment shaders, not vertex shaders.
463b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul */
464b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paulstatic float
465b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paulcompute_lambda(struct tgsi_sampler *sampler,
466b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul               const float s[QUAD_SIZE],
467b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul               const float t[QUAD_SIZE],
468f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul               const float p[QUAD_SIZE],
469f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul               float lodbias)
470b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul{
471b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   float rho, lambda;
472b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul
473b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   assert(sampler->state->normalized_coords);
474b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
475b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   assert(s);
476b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   {
477b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT];
478b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      float dsdy = s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT];
479b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      dsdx = FABSF(dsdx);
480b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      dsdy = FABSF(dsdy);
481b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      rho = MAX2(dsdx, dsdy) * sampler->texture->width[0];
482b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   }
483b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   if (t) {
484b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT];
485b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      float dtdy = t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT];
486b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      float max;
487b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      dtdx = FABSF(dtdx);
488b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      dtdy = FABSF(dtdy);
489b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      max = MAX2(dtdx, dtdy) * sampler->texture->height[0];
490b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      rho = MAX2(rho, max);
491b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   }
492b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   if (p) {
493b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      float dpdx = p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT];
494b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      float dpdy = p[QUAD_TOP_LEFT]     - p[QUAD_BOTTOM_LEFT];
495b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      float max;
496b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      dpdx = FABSF(dpdx);
497b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      dpdy = FABSF(dpdy);
498b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      max = MAX2(dpdx, dpdy) * sampler->texture->depth[0];
499b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      rho = MAX2(rho, max);
500b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   }
501b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul
502b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   lambda = LOG2(rho);
503f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul   lambda += lodbias + sampler->state->lod_bias;
504b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod);
505b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul
506b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   return lambda;
507b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul}
508b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul
509b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul
510f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul/**
511c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul * Do several things here:
512c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul * 1. Compute lambda from the texcoords, if needed
513c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul * 2. Determine if we're minifying or magnifying
514c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul * 3. If minifying, choose mipmap levels
515c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul * 4. Return image filter to use within mipmap images
516f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul */
517f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paulstatic void
518c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paulchoose_mipmap_levels(struct tgsi_sampler *sampler,
519c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul                     const float s[QUAD_SIZE],
520c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul                     const float t[QUAD_SIZE],
521c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul                     const float p[QUAD_SIZE],
522c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul                     float lodbias,
523c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul                     unsigned *level0, unsigned *level1, float *levelBlend,
524c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul                     unsigned *imgFilter)
52509a1b912605ff48c8782dcc5aae55ac77e27037bBrian Paul{
526c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul   if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
527c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul      /* no mipmap selection needed */
5280c6bbd41bd6dc1041eaca7c907d3768d107c1afaBrian Paul      *level0 = *level1 = CLAMP((int) sampler->state->min_lod,
5290c6bbd41bd6dc1041eaca7c907d3768d107c1afaBrian Paul                                0, (int) sampler->texture->last_level);
53008c9534107fcaf06f9b801551524ed5dc724db13Brian Paul
53108c9534107fcaf06f9b801551524ed5dc724db13Brian Paul      if (sampler->state->min_img_filter != sampler->state->mag_img_filter) {
53208c9534107fcaf06f9b801551524ed5dc724db13Brian Paul         /* non-mipmapped texture, but still need to determine if doing
53308c9534107fcaf06f9b801551524ed5dc724db13Brian Paul          * minification or magnification.
53408c9534107fcaf06f9b801551524ed5dc724db13Brian Paul          */
53508c9534107fcaf06f9b801551524ed5dc724db13Brian Paul         float lambda = compute_lambda(sampler, s, t, p, lodbias);
5363b2a291888d8e62787de03f8529806fb562bd186Brian Paul         if (lambda <= 0.0) {
53708c9534107fcaf06f9b801551524ed5dc724db13Brian Paul            *imgFilter = sampler->state->mag_img_filter;
53808c9534107fcaf06f9b801551524ed5dc724db13Brian Paul         }
53908c9534107fcaf06f9b801551524ed5dc724db13Brian Paul         else {
54008c9534107fcaf06f9b801551524ed5dc724db13Brian Paul            *imgFilter = sampler->state->min_img_filter;
54108c9534107fcaf06f9b801551524ed5dc724db13Brian Paul         }
54208c9534107fcaf06f9b801551524ed5dc724db13Brian Paul      }
5433b2a291888d8e62787de03f8529806fb562bd186Brian Paul      else {
5443b2a291888d8e62787de03f8529806fb562bd186Brian Paul         *imgFilter = sampler->state->mag_img_filter;
5453b2a291888d8e62787de03f8529806fb562bd186Brian Paul      }
546c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul   }
547c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul   else {
548c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul      float lambda;
549c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul
550c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul      if (1)
551c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         /* fragment shader */
552c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         lambda = compute_lambda(sampler, s, t, p, lodbias);
553c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul      else
554c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         /* vertex shader */
555c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         lambda = lodbias; /* not really a bias, but absolute LOD */
556c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul
5573b2a291888d8e62787de03f8529806fb562bd186Brian Paul      if (lambda <= 0.0) { /* XXX threshold depends on the filter */
558c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         /* magnifying */
559c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         *imgFilter = sampler->state->mag_img_filter;
5604da1cdf78fa3b954840650fa46cf72da5daf149fBrian Paul         *level0 = *level1 = 0;
561f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul      }
562c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul      else {
563c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         /* minifying */
564c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         *imgFilter = sampler->state->min_img_filter;
565c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul
566c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         /* choose mipmap level(s) and compute the blend factor between them */
567c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
568c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul            /* Nearest mipmap level */
569c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul            const int lvl = (int) (lambda + 0.5);
570c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul            *level0 =
5714da1cdf78fa3b954840650fa46cf72da5daf149fBrian Paul            *level1 = CLAMP(lvl, 0, (int) sampler->texture->last_level);
572c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         }
573c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         else {
574c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul            /* Linear interpolation between mipmap levels */
575c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul            const int lvl = (int) lambda;
5764da1cdf78fa3b954840650fa46cf72da5daf149fBrian Paul            *level0 = CLAMP(lvl,     0, (int) sampler->texture->last_level);
5774da1cdf78fa3b954840650fa46cf72da5daf149fBrian Paul            *level1 = CLAMP(lvl + 1, 0, (int) sampler->texture->last_level);
578c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul            *levelBlend = FRAC(lambda);  /* blending weight between levels */
579c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul         }
580f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul      }
58109a1b912605ff48c8782dcc5aae55ac77e27037bBrian Paul   }
58209a1b912605ff48c8782dcc5aae55ac77e27037bBrian Paul}
58309a1b912605ff48c8782dcc5aae55ac77e27037bBrian Paul
58408f33a025100dea2d951e6d628891fe294b18082Brian Paul
585b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul/**
586a13de2464dd034ff117f9314df5757d068cae8e5Brian Paul * Get a texel from a texture, using the texture tile cache.
587a13de2464dd034ff117f9314df5757d068cae8e5Brian Paul *
588b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul * \param face  the cube face in 0..5
589b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul * \param level  the mipmap level
590b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul * \param x  the x coord of texel within 2D image
591b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul * \param y  the y coord of texel within 2D image
59270eb7996f265f3634dabda078f13d1be3533cc65Brian Paul * \param z  which slice of a 3D texture
593b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul * \param rgba  the quad to put the texel/color into
594b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul * \param j  which element of the rgba quad to write to
59570eb7996f265f3634dabda078f13d1be3533cc65Brian Paul *
59670eb7996f265f3634dabda078f13d1be3533cc65Brian Paul * XXX maybe move this into sp_tile_cache.c and merge with the
59770eb7996f265f3634dabda078f13d1be3533cc65Brian Paul * sp_get_cached_tile_tex() function.  Also, get 4 texels instead of 1...
598b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul */
599b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paulstatic void
600b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paulget_texel(struct tgsi_sampler *sampler,
60170eb7996f265f3634dabda078f13d1be3533cc65Brian Paul          unsigned face, unsigned level, int x, int y, int z,
602a13de2464dd034ff117f9314df5757d068cae8e5Brian Paul          float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j)
603b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul{
60470eb7996f265f3634dabda078f13d1be3533cc65Brian Paul   const int tx = x % TILE_SIZE;
60570eb7996f265f3634dabda078f13d1be3533cc65Brian Paul   const int ty = y % TILE_SIZE;
60670eb7996f265f3634dabda078f13d1be3533cc65Brian Paul   const struct softpipe_cached_tile *tile
60770eb7996f265f3634dabda078f13d1be3533cc65Brian Paul      = sp_get_cached_tile_tex(sampler->pipe, sampler->cache,
60870eb7996f265f3634dabda078f13d1be3533cc65Brian Paul                               x, y, z, face, level);
60970eb7996f265f3634dabda078f13d1be3533cc65Brian Paul   rgba[0][j] = tile->data.color[ty][tx][0];
61070eb7996f265f3634dabda078f13d1be3533cc65Brian Paul   rgba[1][j] = tile->data.color[ty][tx][1];
61170eb7996f265f3634dabda078f13d1be3533cc65Brian Paul   rgba[2][j] = tile->data.color[ty][tx][2];
61270eb7996f265f3634dabda078f13d1be3533cc65Brian Paul   rgba[3][j] = tile->data.color[ty][tx][3];
613b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul}
614b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul
615b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul
6163d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul/**
6173d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
6183d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul * When we sampled the depth texture, the depth value was put into all
6193d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul * RGBA channels.  We look at the red channel here.
6203d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul */
6213d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paulstatic INLINE void
6223d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paulshadow_compare(uint compare_func,
6233d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul               float rgba[NUM_CHANNELS][QUAD_SIZE],
6243d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul               const float p[QUAD_SIZE],
6253d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul               uint j)
6263d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul{
6273d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   int k;
6283d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   switch (compare_func) {
6293d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   case PIPE_FUNC_LESS:
6303d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      k = p[j] < rgba[0][j];
6313d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      break;
6323d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   case PIPE_FUNC_LEQUAL:
6333d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      k = p[j] <= rgba[0][j];
6343d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      break;
6353d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   case PIPE_FUNC_GREATER:
6363d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      k = p[j] > rgba[0][j];
6373d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      break;
6383d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   case PIPE_FUNC_GEQUAL:
6393d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      k = p[j] >= rgba[0][j];
6403d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      break;
6413d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   case PIPE_FUNC_EQUAL:
6423d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      k = p[j] == rgba[0][j];
6433d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      break;
6443d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   case PIPE_FUNC_NOTEQUAL:
6453d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      k = p[j] != rgba[0][j];
6463d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      break;
6473d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   case PIPE_FUNC_ALWAYS:
6483d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      k = 1;
6493d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      break;
6503d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   case PIPE_FUNC_NEVER:
6513d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      k = 0;
6523d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      break;
6533d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   default:
654f9b1d47d652778012fd35552ffc51717ac0b6f79Keith Whitwell      k = 0;
6553d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul      assert(0);
656f9b1d47d652778012fd35552ffc51717ac0b6f79Keith Whitwell      break;
6573d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   }
6583d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul
6593d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   rgba[0][j] = rgba[1][j] = rgba[2][j] = (float) k;
6603d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul}
6613d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul
662b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul
663b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul/**
664a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul * Common code for sampling 1D/2D/cube textures.
665a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul * Could probably extend for 3D...
6660dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul */
667e12810d92ffb3547680b227bf88937c03018112bBrian Paulstatic void
668a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paulsp_get_samples_2d_common(struct tgsi_sampler *sampler,
669a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                         const float s[QUAD_SIZE],
670a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                         const float t[QUAD_SIZE],
671a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                         const float p[QUAD_SIZE],
672a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                         float lodbias,
673a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                         float rgba[NUM_CHANNELS][QUAD_SIZE],
674a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                         const unsigned faces[4])
6750dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul{
6763d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   const uint compare_func = sampler->state->compare_func;
677f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul   unsigned level0, level1, j, imgFilter;
678f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul   int width, height;
679c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul   float levelBlend;
680a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul
681c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul   choose_mipmap_levels(sampler, s, t, p, lodbias,
682c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul                        &level0, &level1, &levelBlend, &imgFilter);
68309a1b912605ff48c8782dcc5aae55ac77e27037bBrian Paul
684b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   assert(sampler->state->normalized_coords);
685b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
686b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   width = sampler->texture->width[level0];
687b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   height = sampler->texture->height[level0];
68809a1b912605ff48c8782dcc5aae55ac77e27037bBrian Paul
689b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   assert(width > 0);
690612cfb749c3526eeb446bbc631bf24716522f373Brian Paul
691b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   switch (imgFilter) {
6920dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   case PIPE_TEX_FILTER_NEAREST:
693b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      for (j = 0; j < QUAD_SIZE; j++) {
694b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         int x = nearest_texcoord(sampler->state->wrap_s, s[j], width);
695b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         int y = nearest_texcoord(sampler->state->wrap_t, t[j], height);
696df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, faces[j], level0, x, y, 0, rgba, j);
6973d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
6983d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul            shadow_compare(compare_func, rgba, p, j);
6993d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul         }
700f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul
701f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul         if (level0 != level1) {
702f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            /* get texels from second mipmap level and blend */
703f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            float rgba2[4][4];
704f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            unsigned c;
705f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            x = x / 2;
706f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            y = y / 2;
707df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, faces[j], level1, x, y, 0, rgba2, j);
7083d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul            if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
7093d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul               shadow_compare(compare_func, rgba2, p, j);
7103d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul            }
7113d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul
712f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            for (c = 0; c < NUM_CHANNELS; c++) {
71317c2f56dc3f2f58ba89d8e305e7d9b423e3cae16Brian Paul               rgba[c][j] = LERP(levelBlend, rgba[c][j], rgba2[c][j]);
714f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            }
715f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul         }
7160dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul      }
7170dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul      break;
7180dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   case PIPE_TEX_FILTER_LINEAR:
71998ae83d5cc73b61826823c915b5c59746c2e85c7Keith Whitwell   case PIPE_TEX_FILTER_ANISO:
720b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul      for (j = 0; j < QUAD_SIZE; j++) {
721b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         float tx[4][4], a, b;
722b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         int x0, y0, x1, y1, c;
723b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         linear_texcoord(sampler->state->wrap_s, s[j], width,  &x0, &x1, &a);
724b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         linear_texcoord(sampler->state->wrap_t, t[j], height, &y0, &y1, &b);
725df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, faces[j], level0, x0, y0, 0, tx, 0);
726df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, faces[j], level0, x1, y0, 0, tx, 1);
727df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, faces[j], level0, x0, y1, 0, tx, 2);
728df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, faces[j], level0, x1, y1, 0, tx, 3);
7293d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
7303d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul            shadow_compare(compare_func, tx, p, 0);
7313d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul            shadow_compare(compare_func, tx, p, 1);
7323d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul            shadow_compare(compare_func, tx, p, 2);
7333d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul            shadow_compare(compare_func, tx, p, 3);
7343d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul         }
7353d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul
736b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         for (c = 0; c < 4; c++) {
737b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul            rgba[c][j] = lerp_2d(a, b, tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
738b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul         }
739f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul
740f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul         if (level0 != level1) {
741f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            /* get texels from second mipmap level and blend */
742f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            float rgba2[4][4];
743f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            x0 = x0 / 2;
744f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            y0 = y0 / 2;
745f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            x1 = x1 / 2;
746f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            y1 = y1 / 2;
747df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, faces[j], level1, x0, y0, 0, tx, 0);
748df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, faces[j], level1, x1, y0, 0, tx, 1);
749df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, faces[j], level1, x0, y1, 0, tx, 2);
750df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, faces[j], level1, x1, y1, 0, tx, 3);
7513d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul            if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){
7523d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul               shadow_compare(compare_func, tx, p, 0);
7533d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul               shadow_compare(compare_func, tx, p, 1);
7543d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul               shadow_compare(compare_func, tx, p, 2);
7553d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul               shadow_compare(compare_func, tx, p, 3);
7563d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul            }
7573d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul
758f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            for (c = 0; c < 4; c++) {
759f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul               rgba2[c][j] = lerp_2d(a, b,
760f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul                                     tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
761f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            }
762f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul
763f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            for (c = 0; c < NUM_CHANNELS; c++) {
764c7722edcfdf36e0d0bfdc51013ecb199fc7fa9f6Brian Paul               rgba[c][j] = LERP(levelBlend, rgba[c][j], rgba2[c][j]);
765f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul            }
766f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul         }
76709a1b912605ff48c8782dcc5aae55ac77e27037bBrian Paul      }
76809a1b912605ff48c8782dcc5aae55ac77e27037bBrian Paul      break;
7690dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   default:
7700dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul      assert(0);
7710dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul   }
7720dc4eea64f56cc93e5359372b08b99a2d600273cBrian Paul}
77334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
77434a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
77534a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paulstatic void
776a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paulsp_get_samples_1d(struct tgsi_sampler *sampler,
777a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  const float s[QUAD_SIZE],
778a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  const float t[QUAD_SIZE],
779a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  const float p[QUAD_SIZE],
780a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  float lodbias,
781a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  float rgba[NUM_CHANNELS][QUAD_SIZE])
782a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul{
783a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul   static const unsigned faces[4] = {0, 0, 0, 0};
784d16b4bc32a731cb6ae320e8c187af3bc751d4138Brian Paul   static const float tzero[4] = {0, 0, 0, 0};
785d16b4bc32a731cb6ae320e8c187af3bc751d4138Brian Paul   sp_get_samples_2d_common(sampler, s, tzero, NULL, lodbias, rgba, faces);
786a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul}
787a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul
788a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul
789a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paulstatic void
790a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paulsp_get_samples_2d(struct tgsi_sampler *sampler,
791a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  const float s[QUAD_SIZE],
792a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  const float t[QUAD_SIZE],
793a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  const float p[QUAD_SIZE],
794a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  float lodbias,
795a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul                  float rgba[NUM_CHANNELS][QUAD_SIZE])
796a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul{
797a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul   static const unsigned faces[4] = {0, 0, 0, 0};
7983d8c05f7320151898dd224c1daaf3118e1f7ea34Brian Paul   sp_get_samples_2d_common(sampler, s, t, p, lodbias, rgba, faces);
799a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul}
800a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul
801a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul
802a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paulstatic void
803b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paulsp_get_samples_3d(struct tgsi_sampler *sampler,
804b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul                  const float s[QUAD_SIZE],
805b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul                  const float t[QUAD_SIZE],
806b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul                  const float p[QUAD_SIZE],
807f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul                  float lodbias,
808b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul                  float rgba[NUM_CHANNELS][QUAD_SIZE])
80934a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul{
81034a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   /* get/map pipe_surfaces corresponding to 3D tex slices */
8113d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   unsigned level0, level1, j, imgFilter;
8123d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   int width, height, depth;
8133d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   float levelBlend;
8143d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   const uint face = 0;
8153d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul
8163d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   choose_mipmap_levels(sampler, s, t, p, lodbias,
8173d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul                        &level0, &level1, &levelBlend, &imgFilter);
8183d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul
819b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   assert(sampler->state->normalized_coords);
820b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
821b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   width = sampler->texture->width[level0];
822b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   height = sampler->texture->height[level0];
823b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   depth = sampler->texture->depth[level0];
8243d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul
8253d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   assert(width > 0);
8263d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   assert(height > 0);
8273d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   assert(depth > 0);
8283d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul
8293d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   switch (imgFilter) {
8303d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   case PIPE_TEX_FILTER_NEAREST:
8313d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul      for (j = 0; j < QUAD_SIZE; j++) {
8323d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         int x = nearest_texcoord(sampler->state->wrap_s, s[j], width);
8333d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         int y = nearest_texcoord(sampler->state->wrap_t, t[j], height);
8343d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         int z = nearest_texcoord(sampler->state->wrap_r, p[j], depth);
835df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, face, level0, x, y, z, rgba, j);
8363d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul
8373d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         if (level0 != level1) {
8383d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            /* get texels from second mipmap level and blend */
8393d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            float rgba2[4][4];
8403d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            unsigned c;
8413d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            x /= 2;
8423d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            y /= 2;
8433d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            z /= 2;
844df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, face, level1, x, y, z, rgba2, j);
8453d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            for (c = 0; c < NUM_CHANNELS; c++) {
8463d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul               rgba[c][j] = LERP(levelBlend, rgba2[c][j], rgba[c][j]);
8473d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            }
8483d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         }
8493d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul      }
8503d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul      break;
8513d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   case PIPE_TEX_FILTER_LINEAR:
85298ae83d5cc73b61826823c915b5c59746c2e85c7Keith Whitwell   case PIPE_TEX_FILTER_ANISO:
8533d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul      for (j = 0; j < QUAD_SIZE; j++) {
854df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         float texel0[4][4], texel1[4][4];
855df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         float xw, yw, zw; /* interpolation weights */
8563d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         int x0, x1, y0, y1, z0, z1, c;
8573d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         linear_texcoord(sampler->state->wrap_s, s[j], width,  &x0, &x1, &xw);
8583d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         linear_texcoord(sampler->state->wrap_t, t[j], height, &y0, &y1, &yw);
8593d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         linear_texcoord(sampler->state->wrap_r, p[j], depth,  &z0, &z1, &zw);
860df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, face, level0, x0, y0, z0, texel0, 0);
861df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, face, level0, x1, y0, z0, texel0, 1);
862df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, face, level0, x0, y1, z0, texel0, 2);
863df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, face, level0, x1, y1, z0, texel0, 3);
864df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, face, level0, x0, y0, z1, texel1, 0);
865df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, face, level0, x1, y0, z1, texel1, 1);
866df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, face, level0, x0, y1, z1, texel1, 2);
867df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul         get_texel(sampler, face, level0, x1, y1, z1, texel1, 3);
8683d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul
8693d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         /* 3D lerp */
8703d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         for (c = 0; c < 4; c++) {
8713d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            float ctemp0[4][4], ctemp1[4][4];
8723d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            ctemp0[c][j] = lerp_2d(xw, yw,
8733d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul                                   texel0[c][0], texel0[c][1],
8743d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul                                   texel0[c][2], texel0[c][3]);
8753d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            ctemp1[c][j] = lerp_2d(xw, yw,
8763d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul                                   texel1[c][0], texel1[c][1],
8773d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul                                   texel1[c][2], texel1[c][3]);
8783d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            rgba[c][j] = LERP(zw, ctemp0[c][j], ctemp1[c][j]);
8793d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         }
8803d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul
8813d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         if (level0 != level1) {
8823d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            /* get texels from second mipmap level and blend */
8833d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            float rgba2[4][4];
8843d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            x0 /= 2;
8853d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            y0 /= 2;
8863d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            z0 /= 2;
8873d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            x1 /= 2;
8883d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            y1 /= 2;
8893d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            z1 /= 2;
890df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, face, level1, x0, y0, z0, texel0, 0);
891df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, face, level1, x1, y0, z0, texel0, 1);
892df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, face, level1, x0, y1, z0, texel0, 2);
893df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, face, level1, x1, y1, z0, texel0, 3);
894df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, face, level1, x0, y0, z1, texel1, 0);
895df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, face, level1, x1, y0, z1, texel1, 1);
896df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, face, level1, x0, y1, z1, texel1, 2);
897df4410a59784482fcbd48f82788dd0a9f5a62c15Brian Paul            get_texel(sampler, face, level1, x1, y1, z1, texel1, 3);
8983d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul
8993d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            /* 3D lerp */
9003d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            for (c = 0; c < 4; c++) {
9013d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul               float ctemp0[4][4], ctemp1[4][4];
9023d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul               ctemp0[c][j] = lerp_2d(xw, yw,
9033d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul                                      texel0[c][0], texel0[c][1],
9043d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul                                      texel0[c][2], texel0[c][3]);
9053d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul               ctemp1[c][j] = lerp_2d(xw, yw,
9063d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul                                      texel1[c][0], texel1[c][1],
9073d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul                                      texel1[c][2], texel1[c][3]);
9083d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul               rgba2[c][j] = LERP(zw, ctemp0[c][j], ctemp1[c][j]);
9093d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            }
9103d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul
9113d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            /* blend mipmap levels */
9123d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            for (c = 0; c < NUM_CHANNELS; c++) {
9133d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul               rgba[c][j] = LERP(levelBlend, rgba[c][j], rgba2[c][j]);
9143d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul            }
9153d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul         }
9163d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul      }
9173d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul      break;
9183d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   default:
9193d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul      assert(0);
9203d6f9d904f07b7676cc971eb3faf9dd8e7c58e50Brian Paul   }
92134a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul}
92234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
92334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
92434a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paulstatic void
925b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paulsp_get_samples_cube(struct tgsi_sampler *sampler,
926b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul                    const float s[QUAD_SIZE],
927b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul                    const float t[QUAD_SIZE],
928b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul                    const float p[QUAD_SIZE],
929f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul                    float lodbias,
930b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul                    float rgba[NUM_CHANNELS][QUAD_SIZE])
93134a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul{
932a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul   unsigned faces[QUAD_SIZE], j;
933a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul   float ssss[4], tttt[4];
934b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   for (j = 0; j < QUAD_SIZE; j++) {
935a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul      faces[j] = choose_cube_face(s[j], t[j], p[j], ssss + j, tttt + j);
936b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul   }
937a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul   sp_get_samples_2d_common(sampler, ssss, tttt, NULL, lodbias, rgba, faces);
93834a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul}
93934a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
94034a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
941b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paulstatic void
942b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paulsp_get_samples_rect(struct tgsi_sampler *sampler,
943b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul                    const float s[QUAD_SIZE],
944b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul                    const float t[QUAD_SIZE],
945b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul                    const float p[QUAD_SIZE],
946b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul                    float lodbias,
947b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul                    float rgba[NUM_CHANNELS][QUAD_SIZE])
948b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul{
949b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   //sp_get_samples_2d_common(sampler, s, t, p, lodbias, rgba, faces);
950b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   static const uint face = 0;
951b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   const uint compare_func = sampler->state->compare_func;
952b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   unsigned level0, level1, j, imgFilter;
953b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   int width, height;
954b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   float levelBlend;
955b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
956b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   choose_mipmap_levels(sampler, s, t, p, lodbias,
957b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul                        &level0, &level1, &levelBlend, &imgFilter);
958b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
959b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   /* texture RECTS cannot be mipmapped */
960b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   assert(level0 == level1);
961b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
962b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   width = sampler->texture->width[level0];
963b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   height = sampler->texture->height[level0];
964b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
965b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   assert(width > 0);
966b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
967b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   switch (imgFilter) {
968b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   case PIPE_TEX_FILTER_NEAREST:
969b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      for (j = 0; j < QUAD_SIZE; j++) {
970b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         int x = nearest_texcoord_unnorm(sampler->state->wrap_s, s[j], width);
971b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         int y = nearest_texcoord_unnorm(sampler->state->wrap_t, t[j], height);
972b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         get_texel(sampler, face, level0, x, y, 0, rgba, j);
973b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
974b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul            shadow_compare(compare_func, rgba, p, j);
975b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         }
976b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      }
977b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      break;
978b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   case PIPE_TEX_FILTER_LINEAR:
97998ae83d5cc73b61826823c915b5c59746c2e85c7Keith Whitwell   case PIPE_TEX_FILTER_ANISO:
980b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      for (j = 0; j < QUAD_SIZE; j++) {
981b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         float tx[4][4], a, b;
982b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         int x0, y0, x1, y1, c;
983b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         linear_texcoord_unnorm(sampler->state->wrap_s, s[j], width,  &x0, &x1, &a);
984b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         linear_texcoord_unnorm(sampler->state->wrap_t, t[j], height, &y0, &y1, &b);
985b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         get_texel(sampler, face, level0, x0, y0, 0, tx, 0);
986b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         get_texel(sampler, face, level0, x1, y0, 0, tx, 1);
987b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         get_texel(sampler, face, level0, x0, y1, 0, tx, 2);
988b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         get_texel(sampler, face, level0, x1, y1, 0, tx, 3);
989b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
990b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul            shadow_compare(compare_func, tx, p, 0);
991b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul            shadow_compare(compare_func, tx, p, 1);
992b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul            shadow_compare(compare_func, tx, p, 2);
993b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul            shadow_compare(compare_func, tx, p, 3);
994b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         }
995b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
996b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         for (c = 0; c < 4; c++) {
997b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul            rgba[c][j] = lerp_2d(a, b, tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
998b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         }
999b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      }
1000b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      break;
1001b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   default:
1002b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      assert(0);
1003b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul   }
1004b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul}
1005b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
1006b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
1007b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
1008b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul
1009a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul/**
1010a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul * Called via tgsi_sampler::get_samples()
1011a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul * Use the sampler's state setting to get a filtered RGBA value
1012753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * from the sampler's texture.
1013a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul *
1014a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul * XXX we can implement many versions of this function, each
1015a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul * tightly coded for a specific combination of sampler state
1016a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul * (nearest + repeat), (bilinear mipmap + clamp), etc.
1017a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul *
1018a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul * The update_samplers() function in st_atom_sampler.c could create
1019a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul * a new tgsi_sampler object for each state combo it finds....
1020a34b8594b7b2d00404bb639621ec1ce918ba0786Brian Paul */
102134a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paulvoid
1022b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paulsp_get_samples(struct tgsi_sampler *sampler,
1023b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul               const float s[QUAD_SIZE],
1024b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul               const float t[QUAD_SIZE],
1025b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul               const float p[QUAD_SIZE],
1026f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul               float lodbias,
1027b4480285ed5098f1c862690ee105dd46f5e6cd1eBrian Paul               float rgba[NUM_CHANNELS][QUAD_SIZE])
102834a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul{
10294f23468bd0d14b8ed687a641003d587b91ad39a7Brian Paul   if (!sampler->texture)
10304f23468bd0d14b8ed687a641003d587b91ad39a7Brian Paul      return;
10314f23468bd0d14b8ed687a641003d587b91ad39a7Brian Paul
103234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   switch (sampler->texture->target) {
103370af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell   case PIPE_TEXTURE_1D:
1034b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      assert(sampler->state->normalized_coords);
1035f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul      sp_get_samples_1d(sampler, s, t, p, lodbias, rgba);
103634a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      break;
103770af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell   case PIPE_TEXTURE_2D:
1038b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      if (sampler->state->normalized_coords)
1039b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         sp_get_samples_2d(sampler, s, t, p, lodbias, rgba);
1040b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      else
1041b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul         sp_get_samples_rect(sampler, s, t, p, lodbias, rgba);
104234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      break;
104370af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell   case PIPE_TEXTURE_3D:
1044b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      assert(sampler->state->normalized_coords);
1045f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul      sp_get_samples_3d(sampler, s, t, p, lodbias, rgba);
104634a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      break;
104770af238b494ed1b6da4841c2065c33ee0f0f37c9Keith Whitwell   case PIPE_TEXTURE_CUBE:
1048b1c8fa5b6002296d9abe21c06d5cb81a3f70828aBrian Paul      assert(sampler->state->normalized_coords);
1049f9e331a574cc4eba60e0de5a29a4aed4bb40520cBrian Paul      sp_get_samples_cube(sampler, s, t, p, lodbias, rgba);
105034a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      break;
105134a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   default:
105234a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul      assert(0);
105334a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul   }
10543d53d38d5e35386de4793162b9dd32e171927059Brian Paul
10553d53d38d5e35386de4793162b9dd32e171927059Brian Paul#if 0 /* DEBUG */
10563d53d38d5e35386de4793162b9dd32e171927059Brian Paul   {
10573d53d38d5e35386de4793162b9dd32e171927059Brian Paul      int i;
10583d53d38d5e35386de4793162b9dd32e171927059Brian Paul      printf("Sampled at %f, %f, %f:\n", s[0], t[0], p[0]);
10593d53d38d5e35386de4793162b9dd32e171927059Brian Paul      for (i = 0; i < 4; i++) {
10603d53d38d5e35386de4793162b9dd32e171927059Brian Paul         printf("Frag %d: %f %f %f %f\n", i,
10613d53d38d5e35386de4793162b9dd32e171927059Brian Paul                rgba[0][i],
10623d53d38d5e35386de4793162b9dd32e171927059Brian Paul                rgba[1][i],
10633d53d38d5e35386de4793162b9dd32e171927059Brian Paul                rgba[2][i],
10643d53d38d5e35386de4793162b9dd32e171927059Brian Paul                rgba[3][i]);
10653d53d38d5e35386de4793162b9dd32e171927059Brian Paul      }
10663d53d38d5e35386de4793162b9dd32e171927059Brian Paul   }
10673d53d38d5e35386de4793162b9dd32e171927059Brian Paul#endif
106834a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul}
106934a48abd5ff82ce9748fc29191e35a0985d47c5fBrian Paul
1070