s_texfilter.c revision 26b8dfc8cadf0f1a8604fc77b226cc7de005f9ca
12cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/*
22cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Mesa 3-D graphics library
3249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian * Version:  7.3
42cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *
5249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
62cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *
72cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Permission is hereby granted, free of charge, to any person obtaining a
82cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * copy of this software and associated documentation files (the "Software"),
92cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * to deal in the Software without restriction, including without limitation
102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense,
112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * and/or sell copies of the Software, and to permit persons to whom the
122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Software is furnished to do so, subject to the following conditions:
132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *
142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * The above copyright notice and this permission notice shall be included
152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * in all copies or substantial portions of the Software.
162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *
172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/glheader.h"
27bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/context.h"
28bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/colormac.h"
29bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/imports.h"
302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#include "s_context.h"
322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#include "s_texfilter.h"
332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
35249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian/*
36249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian * Note, the FRAC macro has to work perfectly.  Otherwise you'll sometimes
37249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian * see 1-pixel bands of improperly weighted linear-filtered textures.
38249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian * The tests/texwrap.c demo is a good test.
39249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
40249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
41249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian */
42249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian#define FRAC(f)  ((f) - IFLOOR(f))
43249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian
44249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian
452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
47bd32640f77c72e79fb5dda0e5fd077e564b33b02Brian Paul * Linear interpolation macro
482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Do 2D/biliner interpolation of float values.
542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * v00, v10, v01 and v11 are typically four texture samples in a square/box.
552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * a and b are the horizontal and vertical interpolants.
562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * It's important that this function is inlined when compiled with
572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * optimization!  If we find that's not true on some systems, convert
582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * to a macro.
592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
609520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat
612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paullerp_2d(GLfloat a, GLfloat b,
622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat temp0 = LERP(a, v00, v10);
652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat temp1 = LERP(a, v01, v11);
662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   return LERP(b, temp0, temp1);
672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Do 3D/trilinear interpolation of float values.
722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * \sa lerp_2d
732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
749520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat
752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paullerp_3d(GLfloat a, GLfloat b, GLfloat c,
762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul        GLfloat v000, GLfloat v100, GLfloat v010, GLfloat v110,
772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul        GLfloat v001, GLfloat v101, GLfloat v011, GLfloat v111)
782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat temp00 = LERP(a, v000, v100);
802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat temp10 = LERP(a, v010, v110);
812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat temp01 = LERP(a, v001, v101);
822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat temp11 = LERP(a, v011, v111);
832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat temp0 = LERP(b, temp00, temp10);
842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat temp1 = LERP(b, temp01, temp11);
852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   return LERP(c, temp0, temp1);
862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Do linear interpolation of colors.
912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
929520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
93de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paullerp_rgba(GLfloat result[4], GLfloat t, const GLfloat a[4], const GLfloat b[4])
942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   result[0] = LERP(t, a[0], b[0]);
962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   result[1] = LERP(t, a[1], b[1]);
972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   result[2] = LERP(t, a[2], b[2]);
982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   result[3] = LERP(t, a[3], b[3]);
992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
1002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
1032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Do bilinear interpolation of colors.
1042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
1059520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
106de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paullerp_rgba_2d(GLfloat result[4], GLfloat a, GLfloat b,
107de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul             const GLfloat t00[4], const GLfloat t10[4],
108de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul             const GLfloat t01[4], const GLfloat t11[4])
1092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
1102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   result[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]);
1112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   result[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]);
1122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   result[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]);
1132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   result[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]);
1142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
1152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
1180f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul * Do trilinear interpolation of colors.
1190f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul */
1209520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
121de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paullerp_rgba_3d(GLfloat result[4], GLfloat a, GLfloat b, GLfloat c,
122de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul             const GLfloat t000[4], const GLfloat t100[4],
123de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul             const GLfloat t010[4], const GLfloat t110[4],
124de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul             const GLfloat t001[4], const GLfloat t101[4],
125de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul             const GLfloat t011[4], const GLfloat t111[4])
1260f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul{
1270f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   GLuint k;
1280f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   /* compiler should unroll these short loops */
1290f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   for (k = 0; k < 4; k++) {
1300f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul      result[k] = lerp_3d(a, b, c, t000[k], t100[k], t010[k], t110[k],
1310f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul                                   t001[k], t101[k], t011[k], t111[k]);
1320f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
1330f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul}
1340f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul
1350f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul
1360f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul/**
1375ba62cd4139e95c752453a1591eb3e47b6b18238Brian Paul * Used for GL_REPEAT wrap mode.  Using A % B doesn't produce the
1385ba62cd4139e95c752453a1591eb3e47b6b18238Brian Paul * right results for A<0.  Casting to A to be unsigned only works if B
1395ba62cd4139e95c752453a1591eb3e47b6b18238Brian Paul * is a power of two.  Adding a bias to A (which is a multiple of B)
1405ba62cd4139e95c752453a1591eb3e47b6b18238Brian Paul * avoids the problems with A < 0 (for reasonable A) without using a
1415ba62cd4139e95c752453a1591eb3e47b6b18238Brian Paul * conditional.
1422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
143ed7f4b42307bff4633689d6781cd3643f10041e5Brian Paul#define REMAINDER(A, B) (((A) + (B) * 1024) % (B))
1442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
1472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Used to compute texel locations for linear sampling.
1482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Input:
1492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
150249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian *    s = texcoord in [0,1]
151249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian *    size = width (or height or depth) of texture
1522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Output:
153249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian *    i0, i1 = returns two nearest texel indexes
154249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian *    weight = returns blend factor between texels
1552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
1569520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
157249e1e4d30759cd3c55cef0dba75f531cc7c6269Brianlinear_texel_locations(GLenum wrapMode,
158249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian                       const struct gl_texture_image *img,
159249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian                       GLint size, GLfloat s,
160249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian                       GLint *i0, GLint *i1, GLfloat *weight)
161249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian{
162eaf376ba354db11f7729452060570b48a029c9a0Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
163249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   GLfloat u;
164249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   switch (wrapMode) {
165249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_REPEAT:
166249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      u = s * size - 0.5F;
167eaf376ba354db11f7729452060570b48a029c9a0Brian Paul      if (swImg->_IsPowerOfTwo) {
168249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i0 = IFLOOR(u) & (size - 1);
169249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i1 = (*i0 + 1) & (size - 1);
170249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
171249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else {
172249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i0 = REMAINDER(IFLOOR(u), size);
173249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i1 = REMAINDER(*i0 + 1, size);
174249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
175249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      break;
176249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_CLAMP_TO_EDGE:
177249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      if (s <= 0.0F)
178249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = 0.0F;
179249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else if (s >= 1.0F)
180249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = (GLfloat) size;
181249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else
182249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = s * size;
183249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      u -= 0.5F;
184249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      *i0 = IFLOOR(u);
185249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      *i1 = *i0 + 1;
186249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      if (*i0 < 0)
187249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i0 = 0;
188249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      if (*i1 >= (GLint) size)
189249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i1 = size - 1;
190249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      break;
191249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_CLAMP_TO_BORDER:
192249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      {
193249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat min = -1.0F / (2.0F * size);
194249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat max = 1.0F - min;
195249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (s <= min)
196249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u = min * size;
197249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else if (s >= max)
198249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u = max * size;
199249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
200249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u = s * size;
201249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u -= 0.5F;
202249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i0 = IFLOOR(u);
203249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i1 = *i0 + 1;
204249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
205249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      break;
206249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_MIRRORED_REPEAT:
207249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      {
208249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLint flr = IFLOOR(s);
209249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (flr & 1)
210249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u = 1.0F - (s - (GLfloat) flr);
211249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
212249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u = s - (GLfloat) flr;
213249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = (u * size) - 0.5F;
214249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i0 = IFLOOR(u);
215249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i1 = *i0 + 1;
216249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (*i0 < 0)
217249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            *i0 = 0;
218249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (*i1 >= (GLint) size)
219249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            *i1 = size - 1;
220249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
221249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      break;
222249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_MIRROR_CLAMP_EXT:
223249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      u = FABSF(s);
224249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      if (u >= 1.0F)
225249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = (GLfloat) size;
226249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else
227249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u *= size;
228249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      u -= 0.5F;
229249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      *i0 = IFLOOR(u);
230249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      *i1 = *i0 + 1;
231249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      break;
232249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_MIRROR_CLAMP_TO_EDGE_EXT:
233249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      u = FABSF(s);
234249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      if (u >= 1.0F)
235249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = (GLfloat) size;
236249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else
237249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u *= size;
238249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      u -= 0.5F;
239249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      *i0 = IFLOOR(u);
240249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      *i1 = *i0 + 1;
241249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      if (*i0 < 0)
242249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i0 = 0;
243249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      if (*i1 >= (GLint) size)
244249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i1 = size - 1;
245249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      break;
246249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_MIRROR_CLAMP_TO_BORDER_EXT:
247249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      {
248249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat min = -1.0F / (2.0F * size);
249249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat max = 1.0F - min;
250249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = FABSF(s);
251249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (u <= min)
252249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u = min * size;
253249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else if (u >= max)
254249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u = max * size;
255249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
256249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u *= size;
257249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u -= 0.5F;
258249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i0 = IFLOOR(u);
259249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         *i1 = *i0 + 1;
260249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
261249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      break;
262249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_CLAMP:
263249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      if (s <= 0.0F)
264249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = 0.0F;
265249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else if (s >= 1.0F)
266249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = (GLfloat) size;
267249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else
268249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         u = s * size;
269249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      u -= 0.5F;
270249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      *i0 = IFLOOR(u);
271249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      *i1 = *i0 + 1;
272249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      break;
273249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   default:
274249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      _mesa_problem(NULL, "Bad wrap mode");
275249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      u = 0.0F;
276249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   }
277249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   *weight = FRAC(u);
2782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
2792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
2802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
2812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
2822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Used to compute texel location for nearest sampling.
2832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
2849520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLint
285249e1e4d30759cd3c55cef0dba75f531cc7c6269Briannearest_texel_location(GLenum wrapMode,
286249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian                       const struct gl_texture_image *img,
287249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian                       GLint size, GLfloat s)
288249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian{
289eaf376ba354db11f7729452060570b48a029c9a0Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
290249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   GLint i;
291249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian
292249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   switch (wrapMode) {
293249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_REPEAT:
294249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      /* s limited to [0,1) */
295249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      /* i limited to [0,size-1] */
296249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      i = IFLOOR(s * size);
297eaf376ba354db11f7729452060570b48a029c9a0Brian Paul      if (swImg->_IsPowerOfTwo)
298249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         i &= (size - 1);
299249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else
300249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         i = REMAINDER(i, size);
301249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      return i;
302249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_CLAMP_TO_EDGE:
303249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      {
304249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* s limited to [min,max] */
305249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* i limited to [0, size-1] */
306249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat min = 1.0F / (2.0F * size);
307249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat max = 1.0F - min;
308249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (s < min)
309249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = 0;
310249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else if (s > max)
311249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = size - 1;
312249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
313249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = IFLOOR(s * size);
314249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
315249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      return i;
316249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_CLAMP_TO_BORDER:
317249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      {
318249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* s limited to [min,max] */
319249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* i limited to [-1, size] */
320249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat min = -1.0F / (2.0F * size);
321249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat max = 1.0F - min;
322249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (s <= min)
323249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = -1;
324249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else if (s >= max)
325249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = size;
326249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
327249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = IFLOOR(s * size);
328249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
329249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      return i;
330249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_MIRRORED_REPEAT:
331249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      {
332249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat min = 1.0F / (2.0F * size);
333249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat max = 1.0F - min;
334249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLint flr = IFLOOR(s);
335249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         GLfloat u;
336249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (flr & 1)
337249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u = 1.0F - (s - (GLfloat) flr);
338249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
339249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            u = s - (GLfloat) flr;
340249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (u < min)
341249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = 0;
342249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else if (u > max)
343249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = size - 1;
344249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
345249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = IFLOOR(u * size);
346249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
347249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      return i;
348249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_MIRROR_CLAMP_EXT:
349249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      {
350249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* s limited to [0,1] */
351249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* i limited to [0,size-1] */
352249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat u = FABSF(s);
353249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (u <= 0.0F)
354249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = 0;
355249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else if (u >= 1.0F)
356249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = size - 1;
357249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
358249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = IFLOOR(u * size);
359249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
360249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      return i;
361249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_MIRROR_CLAMP_TO_EDGE_EXT:
362249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      {
363249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* s limited to [min,max] */
364249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* i limited to [0, size-1] */
365249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat min = 1.0F / (2.0F * size);
366249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat max = 1.0F - min;
367249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat u = FABSF(s);
368249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (u < min)
369249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = 0;
370249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else if (u > max)
371249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = size - 1;
372249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
373249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = IFLOOR(u * size);
374249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
375249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      return i;
376249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_MIRROR_CLAMP_TO_BORDER_EXT:
377249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      {
378249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* s limited to [min,max] */
379249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         /* i limited to [0, size-1] */
380249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat min = -1.0F / (2.0F * size);
381249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat max = 1.0F - min;
382249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         const GLfloat u = FABSF(s);
383249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         if (u < min)
384249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = -1;
385249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else if (u > max)
386249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = size;
387249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         else
388249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian            i = IFLOOR(u * size);
389249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      }
390249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      return i;
391249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   case GL_CLAMP:
392249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      /* s limited to [0,1] */
393249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      /* i limited to [0,size-1] */
394249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      if (s <= 0.0F)
395249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         i = 0;
396249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else if (s >= 1.0F)
397249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         i = size - 1;
398249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      else
399249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian         i = IFLOOR(s * size);
400249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      return i;
401249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   default:
402249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      _mesa_problem(NULL, "Bad wrap mode");
403249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian      return 0;
404249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   }
4052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
4062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
4072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
4082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/* Power of two image sizes only */
4099520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
410249e1e4d30759cd3c55cef0dba75f531cc7c6269Brianlinear_repeat_texel_location(GLuint size, GLfloat s,
411249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian                             GLint *i0, GLint *i1, GLfloat *weight)
412249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian{
413249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   GLfloat u = s * size - 0.5F;
414249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   *i0 = IFLOOR(u) & (size - 1);
415249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   *i1 = (*i0 + 1) & (size - 1);
416249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   *weight = FRAC(u);
4172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
4182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
4192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
420792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul/**
421a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
422a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul */
4239520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLint
424a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paulclamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max)
425a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul{
426a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   switch (wrapMode) {
427a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_CLAMP:
428a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return IFLOOR( CLAMP(coord, 0.0F, max - 1) );
429a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_CLAMP_TO_EDGE:
430a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) );
431a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_CLAMP_TO_BORDER:
432a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) );
433a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   default:
434a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_nearest");
435a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return 0;
436a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   }
437a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul}
438a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
439a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
440a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul/**
441a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul * As above, but GL_LINEAR filtering.
442a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul */
4439520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
444a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paulclamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max,
445a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                        GLint *i0out, GLint *i1out, GLfloat *weight)
446a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul{
447a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   GLfloat fcol;
448a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   GLint i0, i1;
449a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   switch (wrapMode) {
450a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_CLAMP:
451a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      /* Not exactly what the spec says, but it matches NVIDIA output */
452880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul      fcol = CLAMP(coord - 0.5F, 0.0F, max - 1);
453a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      i0 = IFLOOR(fcol);
454a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      i1 = i0 + 1;
455a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
456a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_CLAMP_TO_EDGE:
457a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      fcol = CLAMP(coord, 0.5F, max - 0.5F);
458a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      fcol -= 0.5F;
459a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      i0 = IFLOOR(fcol);
460a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      i1 = i0 + 1;
461a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      if (i1 > max - 1)
462a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul         i1 = max - 1;
463a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
464a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_CLAMP_TO_BORDER:
465a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      fcol = CLAMP(coord, -0.5F, max + 0.5F);
466a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      fcol -= 0.5F;
467a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      i0 = IFLOOR(fcol);
468a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      i1 = i0 + 1;
469dcf571aff9de1a4298c4d2c4148d84cdc4daf02eBrian Paul      break;
470a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   default:
471a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_linear");
472a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      i0 = i1 = 0;
473a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      fcol = 0.0F;
474a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   }
475a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   *i0out = i0;
476a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   *i1out = i1;
477a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   *weight = FRAC(fcol);
478a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul}
479a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
480a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
481a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul/**
48258ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul * Compute slice/image to use for 1D or 2D array texture.
48358ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul */
4849520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLint
48558ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paultex_array_slice(GLfloat coord, GLsizei size)
48658ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul{
487bdbb5f8170f48713b741ad68c26464231a01ca7aBrian Paul   GLint slice = IFLOOR(coord + 0.5f);
48858ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul   slice = CLAMP(slice, 0, size - 1);
48958ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul   return slice;
49058ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul}
49158ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul
49258ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul
49358ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul/**
494a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul * Compute nearest integer texcoords for given texobj and coordinate.
4952b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul * NOTE: only used for depth texture sampling.
496a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul */
4979520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
498a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paulnearest_texcoord(const struct gl_texture_object *texObj,
4992b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul                 GLuint level,
500a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                 const GLfloat texcoord[4],
501a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                 GLint *i, GLint *j, GLint *k)
502a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul{
5032b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul   const struct gl_texture_image *img = texObj->Image[0][level];
504a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   const GLint width = img->Width;
505a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   const GLint height = img->Height;
506a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   const GLint depth = img->Depth;
507a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
508a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   switch (texObj->Target) {
509a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_RECTANGLE_ARB:
510ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      *i = clamp_rect_coord_nearest(texObj->Sampler.WrapS, texcoord[0], width);
511ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      *j = clamp_rect_coord_nearest(texObj->Sampler.WrapT, texcoord[1], height);
512a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *k = 0;
513a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
514a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_1D:
515ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
516a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *j = 0;
517a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *k = 0;
518a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
519a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_2D:
520ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
521ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      *j = nearest_texel_location(texObj->Sampler.WrapT, img, height, texcoord[1]);
522a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *k = 0;
523a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
524a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_1D_ARRAY_EXT:
525ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
52658ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul      *j = tex_array_slice(texcoord[1], height);
527a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *k = 0;
528a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
529a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_2D_ARRAY_EXT:
530ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      *i = nearest_texel_location(texObj->Sampler.WrapS, img, width, texcoord[0]);
531ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      *j = nearest_texel_location(texObj->Sampler.WrapT, img, height, texcoord[1]);
53258ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul      *k = tex_array_slice(texcoord[2], depth);
533a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
534a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   default:
535a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *i = *j = *k = 0;
536a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   }
537a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul}
538a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
539a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
540a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul/**
541a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul * Compute linear integer texcoords for given texobj and coordinate.
5422b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul * NOTE: only used for depth texture sampling.
543a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul */
5449520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
545a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paullinear_texcoord(const struct gl_texture_object *texObj,
5462b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul                GLuint level,
547a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                const GLfloat texcoord[4],
548a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                GLint *i0, GLint *i1, GLint *j0, GLint *j1, GLint *slice,
549a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                GLfloat *wi, GLfloat *wj)
550a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul{
5512b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul   const struct gl_texture_image *img = texObj->Image[0][level];
552a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   const GLint width = img->Width;
553a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   const GLint height = img->Height;
554a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   const GLint depth = img->Depth;
555a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
556a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   switch (texObj->Target) {
557a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_RECTANGLE_ARB:
558ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      clamp_rect_coord_linear(texObj->Sampler.WrapS, texcoord[0],
559a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                              width, i0, i1, wi);
560ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      clamp_rect_coord_linear(texObj->Sampler.WrapT, texcoord[1],
561a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                              height, j0, j1, wj);
562a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *slice = 0;
563a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
564a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
565a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_1D:
566a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_2D:
567ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      linear_texel_locations(texObj->Sampler.WrapS, img, width,
568a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                             texcoord[0], i0, i1, wi);
569ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      linear_texel_locations(texObj->Sampler.WrapT, img, height,
570a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                             texcoord[1], j0, j1, wj);
571a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *slice = 0;
572a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
573a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
574a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_1D_ARRAY_EXT:
575ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      linear_texel_locations(texObj->Sampler.WrapS, img, width,
576a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                             texcoord[0], i0, i1, wi);
57758ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul      *j0 = tex_array_slice(texcoord[1], height);
578a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *j1 = *j0;
579a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *slice = 0;
580a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
581a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
582a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_TEXTURE_2D_ARRAY_EXT:
583ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      linear_texel_locations(texObj->Sampler.WrapS, img, width,
584a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                             texcoord[0], i0, i1, wi);
585ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      linear_texel_locations(texObj->Sampler.WrapT, img, height,
586a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                             texcoord[1], j0, j1, wj);
58758ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul      *slice = tex_array_slice(texcoord[2], depth);
588a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      break;
589a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
590a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   default:
591a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      *slice = 0;
592a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   }
593a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul}
594a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
595a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
596a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
597a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul/**
598792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul * For linear interpolation between mipmap levels N and N+1, this function
599792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul * computes N.
6002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
6019520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLint
602792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paullinear_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda)
603792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul{
604792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   if (lambda < 0.0F)
605792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      return tObj->BaseLevel;
606792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   else if (lambda > tObj->_MaxLambda)
607792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      return (GLint) (tObj->BaseLevel + tObj->_MaxLambda);
608792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   else
609792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      return (GLint) (tObj->BaseLevel + lambda);
6102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
6112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
6122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
613792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul/**
614792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul * Compute the nearest mipmap level to take texels from.
6152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
6169520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLint
617792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paulnearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda)
618792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul{
619792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   GLfloat l;
620792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   GLint level;
621792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   if (lambda <= 0.5F)
622792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      l = 0.0F;
623792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   else if (lambda > tObj->_MaxLambda + 0.4999F)
624792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      l = tObj->_MaxLambda + 0.4999F;
625792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   else
626792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      l = lambda;
627792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   level = (GLint) (tObj->BaseLevel + l + 0.5F);
628792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   if (level > tObj->_MaxLevel)
629792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      level = tObj->_MaxLevel;
630792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   return level;
6312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
6322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
6332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
6342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
6352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/*
6362cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Bitflags for texture border color sampling.
6372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
6382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#define I0BIT   1
6392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#define I1BIT   2
6402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#define J0BIT   4
6412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#define J1BIT   8
6422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#define K0BIT  16
6432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#define K1BIT  32
6442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
6452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
6462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
6476e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
6482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * The lambda[] array values are always monotonic.  Either the whole span
6492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * will be minified, magnified, or split between the two.  This function
6502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * determines the subranges in [0, n-1] that are to be minified or magnified.
6512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
6529520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
653aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paulcompute_min_mag_ranges(const struct gl_texture_object *tObj,
654aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul                       GLuint n, const GLfloat lambda[],
655aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul                       GLuint *minStart, GLuint *minEnd,
656aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul                       GLuint *magStart, GLuint *magEnd)
6572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
658aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   GLfloat minMagThresh;
659aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul
660aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   /* we shouldn't be here if minfilter == magfilter */
661ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.MinFilter != tObj->Sampler.MagFilter);
662aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul
663aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   /* This bit comes from the OpenGL spec: */
664ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   if (tObj->Sampler.MagFilter == GL_LINEAR
665ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul       && (tObj->Sampler.MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
666ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul           tObj->Sampler.MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
667aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul      minMagThresh = 0.5F;
668aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   }
669aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   else {
670aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul      minMagThresh = 0.0F;
671aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   }
672792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul
6732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#if 0
674792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul   /* DEBUG CODE: Verify that lambda[] is monotonic.
6752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul    * We can't really use this because the inaccuracy in the LOG2 function
6762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul    * causes this test to fail, yet the resulting texturing is correct.
6772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul    */
6782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (n > 1) {
6792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLuint i;
6802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      printf("lambda delta = %g\n", lambda[0] - lambda[n-1]);
6812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (lambda[0] >= lambda[n-1]) { /* decreasing */
6822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = 0; i < n - 1; i++) {
6832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10));
6842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
6852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
6862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else { /* increasing */
6872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = 0; i < n - 1; i++) {
6882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10));
6892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
6902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
6912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
6922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#endif /* DEBUG */
6932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
694876b41bc03c9a92263b824378fc2191f85e0a403Brian Paul   if (lambda[0] <= minMagThresh && (n <= 1 || lambda[n-1] <= minMagThresh)) {
6952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* magnification for whole span */
6962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      *magStart = 0;
6972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      *magEnd = n;
6982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      *minStart = *minEnd = 0;
6992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
700876b41bc03c9a92263b824378fc2191f85e0a403Brian Paul   else if (lambda[0] > minMagThresh && (n <=1 || lambda[n-1] > minMagThresh)) {
7012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* minification for whole span */
7022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      *minStart = 0;
7032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      *minEnd = n;
7042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      *magStart = *magEnd = 0;
7052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
7062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
7072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* a mix of minification and magnification */
7082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLuint i;
7092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (lambda[0] > minMagThresh) {
7102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         /* start with minification */
7112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = 1; i < n; i++) {
7122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            if (lambda[i] <= minMagThresh)
7132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul               break;
7142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
7152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         *minStart = 0;
7162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         *minEnd = i;
7172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         *magStart = i;
7182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         *magEnd = n;
7192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
7202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
7212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         /* start with magnification */
7222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = 1; i < n; i++) {
7232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            if (lambda[i] > minMagThresh)
7242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul               break;
7252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
7262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         *magStart = 0;
7272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         *magEnd = i;
7282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         *minStart = i;
7292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         *minEnd = n;
7302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
7312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
7322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
7332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#if 0
7342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   /* Verify the min/mag Start/End values
7352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul    * We don't use this either (see above)
7362cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul    */
7372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   {
7382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLint i;
7392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      for (i = 0; i < n; i++) {
7402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         if (lambda[i] > minMagThresh) {
7412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            /* minification */
7422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            ASSERT(i >= *minStart);
7432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            ASSERT(i < *minEnd);
7442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
7452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
7462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            /* magnification */
7472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            ASSERT(i >= *magStart);
7482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            ASSERT(i < *magEnd);
7492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
7502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
7512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
7522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul#endif
7532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
7542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
7552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
756b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul/**
757b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul * When we sample the border color, it must be interpreted according to
758b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul * the base texture format.  Ex: if the texture base format it GL_ALPHA,
759b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul * we return (0,0,0,BorderAlpha).
760b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul */
7619520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
762b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paulget_border_color(const struct gl_texture_object *tObj,
763b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul                 const struct gl_texture_image *img,
764b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul                 GLfloat rgba[4])
765b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul{
7661f7c914ad0beea8a29c1a171c7cd1a12f2efe0faBrian Paul   switch (img->_BaseFormat) {
767b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul   case GL_RGB:
768ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      rgba[0] = tObj->Sampler.BorderColor.f[0];
769ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      rgba[1] = tObj->Sampler.BorderColor.f[1];
770ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      rgba[2] = tObj->Sampler.BorderColor.f[2];
771b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      rgba[3] = 1.0F;
772b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      break;
773b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul   case GL_ALPHA:
774b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      rgba[0] = rgba[1] = rgba[2] = 0.0;
775ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      rgba[3] = tObj->Sampler.BorderColor.f[3];
776b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      break;
777b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul   case GL_LUMINANCE:
778ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      rgba[0] = rgba[1] = rgba[2] = tObj->Sampler.BorderColor.f[0];
779b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      rgba[3] = 1.0;
780b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      break;
781b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul   case GL_LUMINANCE_ALPHA:
782ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      rgba[0] = rgba[1] = rgba[2] = tObj->Sampler.BorderColor.f[0];
783ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      rgba[3] = tObj->Sampler.BorderColor.f[3];
784b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      break;
785b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul   case GL_INTENSITY:
786ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      rgba[0] = rgba[1] = rgba[2] = rgba[3] = tObj->Sampler.BorderColor.f[0];
787b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      break;
788b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul   default:
789ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      COPY_4V(rgba, tObj->Sampler.BorderColor.f);
790b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul   }
791b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul}
792b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul
793b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul
7942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
7952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/*                    1-D Texture Sampling Functions                  */
7962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
7972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
7986e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
7992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Return the texture sample for coordinate (s) using GL_NEAREST filter.
8002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
8019520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
802f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_nearest(struct gl_context *ctx,
8032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const struct gl_texture_object *tObj,
8042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const struct gl_texture_image *img,
805de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                  const GLfloat texcoord[4], GLfloat rgba[4])
8062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
807a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
8082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint width = img->Width2;  /* without border, power of two */
8092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLint i;
810ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
8112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   /* skip over the border, if any */
8122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   i += img->Border;
8132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (i < 0 || i >= (GLint) img->Width) {
8142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* Need this test for GL_CLAMP_TO_BORDER mode */
815b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, rgba);
8162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
8172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
818a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i, 0, 0, rgba);
8192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
8202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
8212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8236e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
8242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Return the texture sample for coordinate (s) using GL_LINEAR filter.
8252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
8269520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
827f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_linear(struct gl_context *ctx,
8282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                 const struct gl_texture_object *tObj,
8292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                 const struct gl_texture_image *img,
830de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                 const GLfloat texcoord[4], GLfloat rgba[4])
8312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
832a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
8332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint width = img->Width2;
8342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLint i0, i1;
8350f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   GLbitfield useBorderColor = 0x0;
8360f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   GLfloat a;
837de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul   GLfloat t0[4], t1[4];  /* texels */
8382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
839ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a);
8402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (img->Border) {
8422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      i0 += img->Border;
8432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      i1 += img->Border;
8442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
8452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
8462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
8472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
8482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
8492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8500f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   /* fetch texel colors */
8510f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & I0BIT) {
852b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t0);
8532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
8540f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
855a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i0, 0, 0, t0);
8560f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
8570f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & I1BIT) {
858b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t1);
8590f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
8600f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
861a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i1, 0, 0, t1);
8620f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
8630f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul
8640f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   lerp_rgba(rgba, a, t0, t1);
8652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
8662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
869f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_nearest_mipmap_nearest(struct gl_context *ctx,
8702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 const struct gl_texture_object *tObj,
8712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 GLuint n, const GLfloat texcoord[][4],
872de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                 const GLfloat lambda[], GLfloat rgba[][4])
8732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
8742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
8752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
8762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
877792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = nearest_mipmap_level(tObj, lambda[i]);
8782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_1d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
8792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
8802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
8812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
884f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_linear_mipmap_nearest(struct gl_context *ctx,
8852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                const struct gl_texture_object *tObj,
8862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                GLuint n, const GLfloat texcoord[][4],
887de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                const GLfloat lambda[], GLfloat rgba[][4])
8882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
8892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
8902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
8912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
892792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = nearest_mipmap_level(tObj, lambda[i]);
8932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_1d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
8942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
8952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
8962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
8982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
899f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_nearest_mipmap_linear(struct gl_context *ctx,
9002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                const struct gl_texture_object *tObj,
9012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                GLuint n, const GLfloat texcoord[][4],
902de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                const GLfloat lambda[], GLfloat rgba[][4])
9032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
9042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
9052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
9062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
907792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = linear_mipmap_level(tObj, lambda[i]);
9082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (level >= tObj->_MaxLevel) {
9092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
9102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                           texcoord[i], rgba[i]);
9112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
9122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
913de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];
9142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         const GLfloat f = FRAC(lambda[i]);
9152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
9162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
9172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         lerp_rgba(rgba[i], f, t0, t1);
9182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
9192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
9202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
9212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
924f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_linear_mipmap_linear(struct gl_context *ctx,
9252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                               const struct gl_texture_object *tObj,
9262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                               GLuint n, const GLfloat texcoord[][4],
927de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                               const GLfloat lambda[], GLfloat rgba[][4])
9282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
9292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
9302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
9312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
932792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = linear_mipmap_level(tObj, lambda[i]);
9332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (level >= tObj->_MaxLevel) {
9342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
9352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                          texcoord[i], rgba[i]);
9362cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
9372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
938de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];
9392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         const GLfloat f = FRAC(lambda[i]);
9402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
9412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
9422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         lerp_rgba(rgba[i], f, t0, t1);
9432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
9442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
9452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
9462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9486e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 1D texture, nearest filtering for both min/magnification */
9492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
950f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_nearest_1d( struct gl_context *ctx,
9512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                   const struct gl_texture_object *tObj, GLuint n,
9522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                   const GLfloat texcoords[][4], const GLfloat lambda[],
953de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                   GLfloat rgba[][4] )
9542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
9552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
9562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
9572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
9586e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   for (i = 0; i < n; i++) {
9592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
9602cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
9612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
9622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9646e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 1D texture, linear filtering for both min/magnification */
9652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
966f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_linear_1d( struct gl_context *ctx,
9672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const struct gl_texture_object *tObj, GLuint n,
9682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const GLfloat texcoords[][4], const GLfloat lambda[],
969de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                  GLfloat rgba[][4] )
9702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
9712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
9722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
9732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
9746e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   for (i = 0; i < n; i++) {
9752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
9762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
9772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
9782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9806e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 1D texture, using lambda to choose between min/magnification */
9812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
982f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_lambda_1d( struct gl_context *ctx,
9832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const struct gl_texture_object *tObj, GLuint n,
9842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const GLfloat texcoords[][4],
985de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                  const GLfloat lambda[], GLfloat rgba[][4] )
9862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
9872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint minStart, minEnd;  /* texels with minification */
9882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint magStart, magEnd;  /* texels with magnification */
9892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
9902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
992aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   compute_min_mag_ranges(tObj, n, lambda,
993aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul                          &minStart, &minEnd, &magStart, &magEnd);
9942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
9952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (minStart < minEnd) {
9962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* do the minified texels */
9972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const GLuint m = minEnd - minStart;
998ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MinFilter) {
9992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST:
10002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = minStart; i < minEnd; i++)
10012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
10022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                              texcoords[i], rgba[i]);
10032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
10042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR:
10052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = minStart; i < minEnd; i++)
10062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
10072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                             texcoords[i], rgba[i]);
10082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
10092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST_MIPMAP_NEAREST:
10102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
10112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                          lambda + minStart, rgba + minStart);
10122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
10132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR_MIPMAP_NEAREST:
10142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
10152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                         lambda + minStart, rgba + minStart);
10162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
10172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST_MIPMAP_LINEAR:
10182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
10192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                         lambda + minStart, rgba + minStart);
10202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
10212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR_MIPMAP_LINEAR:
10222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
10232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                        lambda + minStart, rgba + minStart);
10242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
10252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      default:
10262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         _mesa_problem(ctx, "Bad min filter in sample_1d_texture");
10272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         return;
10282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
10292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
10302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
10312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (magStart < magEnd) {
10322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* do the magnified texels */
1033ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MagFilter) {
10342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST:
10352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = magStart; i < magEnd; i++)
10362cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
10372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                              texcoords[i], rgba[i]);
10382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
10392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR:
10402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = magStart; i < magEnd; i++)
10412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
10422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                             texcoords[i], rgba[i]);
10432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
10442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      default:
10452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         _mesa_problem(ctx, "Bad mag filter in sample_1d_texture");
10462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         return;
10472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
10482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
10492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
10502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
10512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
10522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
10532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/*                    2-D Texture Sampling Functions                  */
10542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
10552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
10562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
10576e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
10582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
10592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
10609520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
1061f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_nearest(struct gl_context *ctx,
10622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const struct gl_texture_object *tObj,
10632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const struct gl_texture_image *img,
10642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const GLfloat texcoord[4],
1065de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                  GLfloat rgba[])
10662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
1067a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
10682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint width = img->Width2;    /* without border, power of two */
10692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint height = img->Height2;  /* without border, power of two */
10702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLint i, j;
10712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) ctx;
10722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1073ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
1074ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]);
10752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
10762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   /* skip over the border, if any */
10772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   i += img->Border;
10782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   j += img->Border;
10792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
10802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
10812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* Need this test for GL_CLAMP_TO_BORDER mode */
1082b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, rgba);
10832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
10842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
1085a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i, j, 0, rgba);
10862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
10872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
10882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
10892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
10902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
10912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
10922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
10932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
10949520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
1095f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_linear(struct gl_context *ctx,
10962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                 const struct gl_texture_object *tObj,
10972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                 const struct gl_texture_image *img,
10982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                 const GLfloat texcoord[4],
1099de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                 GLfloat rgba[])
11002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
1101a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
11022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint width = img->Width2;
11032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint height = img->Height2;
11042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLint i0, j0, i1, j1;
11050f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   GLbitfield useBorderColor = 0x0;
11060f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   GLfloat a, b;
1107de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul   GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
11082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1109ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0],  &i0, &i1, &a);
1110ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b);
11112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
11122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (img->Border) {
11132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      i0 += img->Border;
11142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      i1 += img->Border;
11152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      j0 += img->Border;
11162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      j1 += img->Border;
11172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
11182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
11192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
11202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
11212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
11222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
11232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
11242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
11250f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   /* fetch four texel colors */
11260f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I0BIT | J0BIT)) {
1127b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t00);
11280f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
11290f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
1130a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i0, j0, 0, t00);
11310f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
11320f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I1BIT | J0BIT)) {
1133b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t10);
11340f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
11350f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
1136a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i1, j0, 0, t10);
11370f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
11380f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I0BIT | J1BIT)) {
1139b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t01);
11400f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
11410f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
1142a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i0, j1, 0, t01);
11430f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
11440f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I1BIT | J1BIT)) {
1145b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t11);
11460f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
11470f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
1148a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i1, j1, 0, t11);
11492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
11500f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul
11510f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11);
11522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
11532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
11542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
11556e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
11562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT.
11572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * We don't have to worry about the texture border.
11582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
11599520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
1160f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_linear_repeat(struct gl_context *ctx,
11612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                        const struct gl_texture_object *tObj,
11622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                        const struct gl_texture_image *img,
11632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                        const GLfloat texcoord[4],
1164de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                        GLfloat rgba[])
11652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
1166a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
11672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint width = img->Width2;
11682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint height = img->Height2;
11692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLint i0, j0, i1, j1;
1170249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   GLfloat wi, wj;
1171de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul   GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
11720f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul
11739ebe3b6d369c946e41b5f6a684a4ac4e3509b67cBrian Paul   (void) ctx;
11749ebe3b6d369c946e41b5f6a684a4ac4e3509b67cBrian Paul
1175ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapS == GL_REPEAT);
1176ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapT == GL_REPEAT);
11772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(img->Border == 0);
1178eaf376ba354db11f7729452060570b48a029c9a0Brian Paul   ASSERT(swImg->_IsPowerOfTwo);
11792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1180249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   linear_repeat_texel_location(width,  texcoord[0], &i0, &i1, &wi);
1181249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   linear_repeat_texel_location(height, texcoord[1], &j0, &j1, &wj);
11822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1183a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   swImg->FetchTexelf(swImg, i0, j0, 0, t00);
1184a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   swImg->FetchTexelf(swImg, i1, j0, 0, t10);
1185a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   swImg->FetchTexelf(swImg, i0, j1, 0, t01);
1186a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   swImg->FetchTexelf(swImg, i1, j1, 0, t11);
11872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1188249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian   lerp_rgba_2d(rgba, wi, wj, t00, t10, t01, t11);
11892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
11902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
11912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
11922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1193f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_nearest_mipmap_nearest(struct gl_context *ctx,
11942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 const struct gl_texture_object *tObj,
11952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 GLuint n, const GLfloat texcoord[][4],
1196de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                 const GLfloat lambda[], GLfloat rgba[][4])
11972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
11982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
11992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
1200792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = nearest_mipmap_level(tObj, lambda[i]);
12012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_2d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
12022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
12032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
12042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
12052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
12062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1207f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_linear_mipmap_nearest(struct gl_context *ctx,
12082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                const struct gl_texture_object *tObj,
12092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                GLuint n, const GLfloat texcoord[][4],
1210de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                const GLfloat lambda[], GLfloat rgba[][4])
12112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
12122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
12132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
12142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
1215792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = nearest_mipmap_level(tObj, lambda[i]);
12162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_2d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
12172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
12182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
12192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
12202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
12212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1222f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_nearest_mipmap_linear(struct gl_context *ctx,
12232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                const struct gl_texture_object *tObj,
12242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                GLuint n, const GLfloat texcoord[][4],
1225de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                const GLfloat lambda[], GLfloat rgba[][4])
12262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
12272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
12282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
12292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
1230792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = linear_mipmap_level(tObj, lambda[i]);
12312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (level >= tObj->_MaxLevel) {
12322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
12332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                           texcoord[i], rgba[i]);
12342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
12352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
1236de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
12372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         const GLfloat f = FRAC(lambda[i]);
12382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
12392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
12402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         lerp_rgba(rgba[i], f, t0, t1);
12412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
12422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
12432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
12442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
12452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
12462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1247f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_linear_mipmap_linear( struct gl_context *ctx,
12482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                const struct gl_texture_object *tObj,
12492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                GLuint n, const GLfloat texcoord[][4],
1250de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                const GLfloat lambda[], GLfloat rgba[][4] )
12512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
12522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
12532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
12542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
1255792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = linear_mipmap_level(tObj, lambda[i]);
12562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (level >= tObj->_MaxLevel) {
12572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
12582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                          texcoord[i], rgba[i]);
12592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
12602cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
1261de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
12622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         const GLfloat f = FRAC(lambda[i]);
12632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
12642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
12652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         lerp_rgba(rgba[i], f, t0, t1);
12662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
12672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
12682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
12692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
12702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
12712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1272f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_linear_mipmap_linear_repeat(struct gl_context *ctx,
12736e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                      const struct gl_texture_object *tObj,
12746e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                      GLuint n, const GLfloat texcoord[][4],
1275de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                      const GLfloat lambda[], GLfloat rgba[][4])
12762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
12772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
12782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
1279ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapS == GL_REPEAT);
1280ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapT == GL_REPEAT);
12812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
1282792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = linear_mipmap_level(tObj, lambda[i]);
12832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (level >= tObj->_MaxLevel) {
12842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
12852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 texcoord[i], rgba[i]);
12862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
12872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
1288de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
12892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         const GLfloat f = FRAC(lambda[i]);
12906e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level  ],
12916e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                 texcoord[i], t0);
12926e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level+1],
12936e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                 texcoord[i], t1);
12942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         lerp_rgba(rgba[i], f, t0, t1);
12952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
12962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
12972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
12982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
12992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
13006e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 2D texture, nearest filtering for both min/magnification */
13012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1302f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_nearest_2d(struct gl_context *ctx,
13036e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                  const struct gl_texture_object *tObj, GLuint n,
13046e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                  const GLfloat texcoords[][4],
1305de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                  const GLfloat lambda[], GLfloat rgba[][4])
13062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
13072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
13082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
13092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
13106e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   for (i = 0; i < n; i++) {
13112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
13122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
13132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
13142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
13152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
13166e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 2D texture, linear filtering for both min/magnification */
13172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1318f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_linear_2d(struct gl_context *ctx,
13196e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                 const struct gl_texture_object *tObj, GLuint n,
13206e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                 const GLfloat texcoords[][4],
1321de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                 const GLfloat lambda[], GLfloat rgba[][4])
13222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
13232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
13242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
1325eaf376ba354db11f7729452060570b48a029c9a0Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(image);
13262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
1327ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   if (tObj->Sampler.WrapS == GL_REPEAT &&
1328ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul       tObj->Sampler.WrapT == GL_REPEAT &&
1329eaf376ba354db11f7729452060570b48a029c9a0Brian Paul       swImg->_IsPowerOfTwo &&
1330c14d969a69d7b9a060c6701d3f18c51eabc56635Brian       image->Border == 0) {
13316e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian      for (i = 0; i < n; i++) {
13322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear_repeat(ctx, tObj, image, texcoords[i], rgba[i]);
13332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
13342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
13352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
13366e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian      for (i = 0; i < n; i++) {
13372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
13382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
13392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
13402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
13412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
13422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
13436e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
13442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Optimized 2-D texture sampling:
13452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    S and T wrap mode == GL_REPEAT
13462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    GL_NEAREST min/mag filter
13472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    No border,
13482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    RowStride == Width,
13492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    Format = GL_RGB
13502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
13512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1352f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergopt_sample_rgb_2d(struct gl_context *ctx,
13536e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                  const struct gl_texture_object *tObj,
13546e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                  GLuint n, const GLfloat texcoords[][4],
13556d63dec41f5399dbe5561175c1652d2ac5ffd4bbBrian Paul                  const GLfloat lambda[], GLfloat rgba[][4])
13562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
13572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
1358eaf376ba354db11f7729452060570b48a029c9a0Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
13592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat width = (GLfloat) img->Width;
13602cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat height = (GLfloat) img->Height;
13612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint colMask = img->Width - 1;
13622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint rowMask = img->Height - 1;
13632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint shift = img->WidthLog2;
13642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint k;
13652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) ctx;
13662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
1367ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapS==GL_REPEAT);
1368ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapT==GL_REPEAT);
13692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(img->Border==0);
13703fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul   ASSERT(img->TexFormat == MESA_FORMAT_RGB888);
1371eaf376ba354db11f7729452060570b48a029c9a0Brian Paul   ASSERT(swImg->_IsPowerOfTwo);
137226b8dfc8cadf0f1a8604fc77b226cc7de005f9caBrian Paul   (void) swImg;
13732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
13742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (k=0; k<n; k++) {
13752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLint i = IFLOOR(texcoords[k][0] * width) & colMask;
13762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLint j = IFLOOR(texcoords[k][1] * height) & rowMask;
13772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLint pos = (j << shift) | i;
13783fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul      GLubyte *texel = ((GLubyte *) img->Data) + 3*pos;
13798c36ca707ca8879d6f888de7733ffb6b04ddc48aBrian Paul      rgba[k][RCOMP] = UBYTE_TO_FLOAT(texel[2]);
13803fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul      rgba[k][GCOMP] = UBYTE_TO_FLOAT(texel[1]);
13818c36ca707ca8879d6f888de7733ffb6b04ddc48aBrian Paul      rgba[k][BCOMP] = UBYTE_TO_FLOAT(texel[0]);
13826a0255122a7d7c0aa09bceacda90a5cea67d5ee2Brian Paul      rgba[k][ACOMP] = 1.0F;
13832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
13842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
13852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
13862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
13876e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
13882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Optimized 2-D texture sampling:
13892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    S and T wrap mode == GL_REPEAT
13902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    GL_NEAREST min/mag filter
13912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    No border
13922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    RowStride == Width,
13932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul *    Format = GL_RGBA
13942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
13952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1396f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergopt_sample_rgba_2d(struct gl_context *ctx,
13976e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                   const struct gl_texture_object *tObj,
13986e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                   GLuint n, const GLfloat texcoords[][4],
13996d63dec41f5399dbe5561175c1652d2ac5ffd4bbBrian Paul                   const GLfloat lambda[], GLfloat rgba[][4])
14002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
14012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
1402eaf376ba354db11f7729452060570b48a029c9a0Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
14032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat width = (GLfloat) img->Width;
14042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat height = (GLfloat) img->Height;
14052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint colMask = img->Width - 1;
14062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint rowMask = img->Height - 1;
14072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint shift = img->WidthLog2;
14082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
14092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) ctx;
14102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
1411ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapS==GL_REPEAT);
1412ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapT==GL_REPEAT);
14132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(img->Border==0);
14143fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul   ASSERT(img->TexFormat == MESA_FORMAT_RGBA8888);
1415eaf376ba354db11f7729452060570b48a029c9a0Brian Paul   ASSERT(swImg->_IsPowerOfTwo);
141626b8dfc8cadf0f1a8604fc77b226cc7de005f9caBrian Paul   (void) swImg;
14172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
14182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
14192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const GLint col = IFLOOR(texcoords[i][0] * width) & colMask;
14202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask;
14212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const GLint pos = (row << shift) | col;
14221e7517f059b1f3601502a199b05453eabfe56cdbBrian Paul      const GLuint texel = *((GLuint *) img->Data + pos);
14231e7517f059b1f3601502a199b05453eabfe56cdbBrian Paul      rgba[i][RCOMP] = UBYTE_TO_FLOAT( (texel >> 24)        );
14241e7517f059b1f3601502a199b05453eabfe56cdbBrian Paul      rgba[i][GCOMP] = UBYTE_TO_FLOAT( (texel >> 16) & 0xff );
14251e7517f059b1f3601502a199b05453eabfe56cdbBrian Paul      rgba[i][BCOMP] = UBYTE_TO_FLOAT( (texel >>  8) & 0xff );
14261e7517f059b1f3601502a199b05453eabfe56cdbBrian Paul      rgba[i][ACOMP] = UBYTE_TO_FLOAT( (texel      ) & 0xff );
14272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
14282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
14292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
14302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
14316e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 2D texture, using lambda to choose between min/magnification */
14322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1433f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_lambda_2d(struct gl_context *ctx,
14346e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                 const struct gl_texture_object *tObj,
14356e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                 GLuint n, const GLfloat texcoords[][4],
1436de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                 const GLfloat lambda[], GLfloat rgba[][4])
14372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
14382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel];
1439eaf376ba354db11f7729452060570b48a029c9a0Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(tImg);
14402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint minStart, minEnd;  /* texels with minification */
14412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint magStart, magEnd;  /* texels with magnification */
14422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1443ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   const GLboolean repeatNoBorderPOT = (tObj->Sampler.WrapS == GL_REPEAT)
1444ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      && (tObj->Sampler.WrapT == GL_REPEAT)
14452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      && (tImg->Border == 0 && (tImg->Width == tImg->RowStride))
1446eaf376ba354db11f7729452060570b48a029c9a0Brian Paul      && swImg->_IsPowerOfTwo;
14472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
14482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
1449aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   compute_min_mag_ranges(tObj, n, lambda,
1450aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul                          &minStart, &minEnd, &magStart, &magEnd);
14512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
14522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (minStart < minEnd) {
14532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* do the minified texels */
14542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const GLuint m = minEnd - minStart;
1455ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MinFilter) {
14562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST:
14572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         if (repeatNoBorderPOT) {
14581f7c914ad0beea8a29c1a171c7cd1a12f2efe0faBrian Paul            switch (tImg->TexFormat) {
14593fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul            case MESA_FORMAT_RGB888:
1460aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul               opt_sample_rgb_2d(ctx, tObj, m, texcoords + minStart,
14612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 NULL, rgba + minStart);
14622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul               break;
14633fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul            case MESA_FORMAT_RGBA8888:
1464aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul	       opt_sample_rgba_2d(ctx, tObj, m, texcoords + minStart,
14652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                  NULL, rgba + minStart);
14662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul               break;
14672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            default:
1468aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul               sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
14692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 NULL, rgba + minStart );
14702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            }
14712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
14722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
1473aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul            sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
14742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                              NULL, rgba + minStart);
14752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
14762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
14772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR:
1478aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul	 sample_linear_2d(ctx, tObj, m, texcoords + minStart,
14792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul			  NULL, rgba + minStart);
14802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
14812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST_MIPMAP_NEAREST:
14822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_nearest_mipmap_nearest(ctx, tObj, m,
14832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                          texcoords + minStart,
14842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                          lambda + minStart, rgba + minStart);
14852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
14862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR_MIPMAP_NEAREST:
14872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
14882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                         lambda + minStart, rgba + minStart);
14892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
14902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST_MIPMAP_LINEAR:
14912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
14922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                         lambda + minStart, rgba + minStart);
14932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
14942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR_MIPMAP_LINEAR:
14952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         if (repeatNoBorderPOT)
14962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m,
14972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  texcoords + minStart, lambda + minStart, rgba + minStart);
14982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else
14992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
15002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                        lambda + minStart, rgba + minStart);
15012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
15022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      default:
15032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         _mesa_problem(ctx, "Bad min filter in sample_2d_texture");
15042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         return;
15052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
15062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
15072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
15082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (magStart < magEnd) {
15092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* do the magnified texels */
15102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const GLuint m = magEnd - magStart;
15112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1512ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MagFilter) {
15132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST:
15142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         if (repeatNoBorderPOT) {
15151f7c914ad0beea8a29c1a171c7cd1a12f2efe0faBrian Paul            switch (tImg->TexFormat) {
15163fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul            case MESA_FORMAT_RGB888:
1517aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul               opt_sample_rgb_2d(ctx, tObj, m, texcoords + magStart,
15182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 NULL, rgba + magStart);
15192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul               break;
15203fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul            case MESA_FORMAT_RGBA8888:
1521aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul	       opt_sample_rgba_2d(ctx, tObj, m, texcoords + magStart,
15222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                  NULL, rgba + magStart);
15232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul               break;
15242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            default:
1525aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul               sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
15262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 NULL, rgba + magStart );
15272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            }
15282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
15292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
1530aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul            sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
15312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                              NULL, rgba + magStart);
15322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
15332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
15342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR:
1535aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul	 sample_linear_2d(ctx, tObj, m, texcoords + magStart,
15362cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul			  NULL, rgba + magStart);
15372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
15382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      default:
15392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d");
15402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
15412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
15422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
15432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
15442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
15458a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger/* For anisotropic filtering */
15468a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger#define WEIGHT_LUT_SIZE 1024
15478a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
15488a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengerstatic GLfloat *weightLut = NULL;
15498a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
15508a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger/**
15518a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * Creates the look-up table used to speed-up EWA sampling
15528a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger */
15538a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengerstatic void
15548a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengercreate_filter_table(void)
15558a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger{
15568a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLuint i;
15578a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   if (!weightLut) {
15588a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      weightLut = (GLfloat *) malloc(WEIGHT_LUT_SIZE * sizeof(GLfloat));
15598a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
15608a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      for (i = 0; i < WEIGHT_LUT_SIZE; ++i) {
15618a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         GLfloat alpha = 2;
15628a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         GLfloat r2 = (GLfloat) i / (GLfloat) (WEIGHT_LUT_SIZE - 1);
15638a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         GLfloat weight = (GLfloat) exp(-alpha * r2);
15648a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         weightLut[i] = weight;
15658a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      }
15668a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   }
15678a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger}
15688a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
15698a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
15708a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger/**
15718a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * Elliptical weighted average (EWA) filter for producing high quality
15728a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * anisotropic filtered results.
15738a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * Based on the Higher Quality Elliptical Weighted Avarage Filter
15748a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * published by Paul S. Heckbert in his Master's Thesis
15758a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * "Fundamentals of Texture Mapping and Image Warping" (1989)
15768a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger */
15778a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengerstatic void
15788a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengersample_2d_ewa(struct gl_context *ctx,
15798a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger              const struct gl_texture_object *tObj,
15808a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger              const GLfloat texcoord[4],
15818a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger              const GLfloat dudx, const GLfloat dvdx,
15828a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger              const GLfloat dudy, const GLfloat dvdy, const GLint lod,
15838a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger              GLfloat rgba[])
15848a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger{
15858a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLint level = lod > 0 ? lod : 0;
15868a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat scaling = 1.0 / (1 << level);
15878a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const struct gl_texture_image *img =	tObj->Image[0][level];
15888a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const struct gl_texture_image *mostDetailedImage =
15898a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      tObj->Image[0][tObj->BaseLevel];
1590980f6f1b37ca88529b3e000235156eab93254facBrian Paul   const struct swrast_texture_image *swImg =
1591980f6f1b37ca88529b3e000235156eab93254facBrian Paul      swrast_texture_image_const(mostDetailedImage);
1592980f6f1b37ca88529b3e000235156eab93254facBrian Paul   GLfloat tex_u=-0.5 + texcoord[0] * swImg->WidthScale * scaling;
1593980f6f1b37ca88529b3e000235156eab93254facBrian Paul   GLfloat tex_v=-0.5 + texcoord[1] * swImg->HeightScale * scaling;
15948a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
15958a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat ux = dudx * scaling;
15968a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat vx = dvdx * scaling;
15978a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat uy = dudy * scaling;
15988a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat vy = dvdy * scaling;
15998a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16008a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* compute ellipse coefficients to bound the region:
16018a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    * A*x*x + B*x*y + C*y*y = F.
16028a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    */
16038a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat A = vx*vx+vy*vy+1;
16048a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat B = -2*(ux*vx+uy*vy);
16058a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat C = ux*ux+uy*uy+1;
16068a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat F = A*C-B*B/4.0;
16078a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16088a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* check if it is an ellipse */
16098a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* ASSERT(F > 0.0); */
16108a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16118a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* Compute the ellipse's (u,v) bounding box in texture space */
16128a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat d = -B*B+4.0*C*A;
16138a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat box_u = 2.0 / d * sqrt(d*C*F); /* box_u -> half of bbox with   */
16148a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat box_v = 2.0 / d * sqrt(A*d*F); /* box_v -> half of bbox height */
16158a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16168a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLint u0 = floor(tex_u - box_u);
16178a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLint u1 = ceil (tex_u + box_u);
16188a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLint v0 = floor(tex_v - box_v);
16198a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLint v1 = ceil (tex_v + box_v);
16208a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16218a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
16228a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat newCoord[2];
16238a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat den = 0.0F;
16248a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat ddq;
16258a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat U = u0 - tex_u;
16268a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLint v;
16278a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16288a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* Scale ellipse formula to directly index the Filter Lookup Table.
16298a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    * i.e. scale so that F = WEIGHT_LUT_SIZE-1
16308a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    */
16318a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F;
16328a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   A *= formScale;
16338a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   B *= formScale;
16348a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   C *= formScale;
16358a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* F *= formScale; */ /* no need to scale F as we don't use it below here */
16368a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16378a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
16388a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    * and incrementally update the value of Ax^2+Bxy*Cy^2; when this
16398a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    * value, q, is less than F, we're inside the ellipse
16408a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    */
16418a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   ddq = 2 * A;
16428a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   for (v = v0; v <= v1; ++v) {
16438a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat V = v - tex_v;
16448a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat dq = A * (2 * U + 1) + B * V;
16458a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat q = (C * V + B * U) * V + A * U * U;
16468a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16478a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLint u;
16488a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      for (u = u0; u <= u1; ++u) {
16498a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         /* Note that the ellipse has been pre-scaled so F = WEIGHT_LUT_SIZE - 1 */
16508a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         if (q < WEIGHT_LUT_SIZE) {
16518a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            /* as a LUT is used, q must never be negative;
16528a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger             * should not happen, though
16538a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger             */
16548a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            const GLint qClamped = q >= 0.0F ? q : 0;
16558a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            GLfloat weight = weightLut[qClamped];
16568a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16578a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            newCoord[0] = u / ((GLfloat) img->Width2);
16588a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            newCoord[1] = v / ((GLfloat) img->Height2);
16598a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16608a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            sample_2d_nearest(ctx, tObj, img, newCoord, rgba);
16618a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            num[0] += weight * rgba[0];
16628a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            num[1] += weight * rgba[1];
16638a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            num[2] += weight * rgba[2];
16648a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            num[3] += weight * rgba[3];
16658a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16668a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            den += weight;
16678a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         }
16688a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         q += dq;
16698a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         dq += ddq;
16708a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      }
16718a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   }
16728a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16738a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   if (den <= 0.0F) {
16748a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      /* Reaching this place would mean
16758a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       * that no pixels intersected the ellipse.
16768a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       * This should never happen because
16778a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       * the filter we use always
16788a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       * intersects at least one pixel.
16798a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       */
16808a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16818a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      /*rgba[0]=0;
16828a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      rgba[1]=0;
16838a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      rgba[2]=0;
16848a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      rgba[3]=0;*/
16858a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      /* not enough pixels in resampling, resort to direct interpolation */
16868a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      sample_2d_linear(ctx, tObj, img, texcoord, rgba);
16878a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      return;
16888a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   }
16898a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16908a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   rgba[0] = num[0] / den;
16918a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   rgba[1] = num[1] / den;
16928a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   rgba[2] = num[2] / den;
16938a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   rgba[3] = num[3] / den;
16948a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger}
16958a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16968a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
16978a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger/**
16988a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * Anisotropic filtering using footprint assembly as outlined in the
16998a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * EXT_texture_filter_anisotropic spec:
17008a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * http://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt
17018a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * Faster than EWA but has less quality (more aliasing effects)
17028a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger */
17038a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengerstatic void
17048a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengersample_2d_footprint(struct gl_context *ctx,
17058a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                 const struct gl_texture_object *tObj,
17068a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                 const GLfloat texcoord[4],
17078a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                 const GLfloat dudx, const GLfloat dvdx,
17088a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                 const GLfloat dudy, const GLfloat dvdy, const GLint lod,
17098a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                 GLfloat rgba[])
17108a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger{
17118a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLint level = lod > 0 ? lod : 0;
17128a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat scaling = 1.0F / (1 << level);
17138a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const struct gl_texture_image *img = tObj->Image[0][level];
17148a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17158a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat ux = dudx * scaling;
17168a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat vx = dvdx * scaling;
17178a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat uy = dudy * scaling;
17188a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat vy = dvdy * scaling;
17198a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17208a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat Px2 = ux * ux + vx * vx; /* squared length of dx */
17218a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat Py2 = uy * uy + vy * vy; /* squared length of dy */
17228a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17238a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLint numSamples;
17248a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat ds;
17258a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat dt;
17268a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17278a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
17288a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat newCoord[2];
17298a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLint s;
17308a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17318a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /*  Calculate the per anisotropic sample offsets in s,t space. */
17328a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   if (Px2 > Py2) {
17338a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      numSamples = ceil(SQRTF(Px2));
17348a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      ds = ux / ((GLfloat) img->Width2);
17358a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      dt = vx / ((GLfloat) img->Height2);
17368a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   }
17378a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   else {
17388a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      numSamples = ceil(SQRTF(Py2));
17398a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      ds = uy / ((GLfloat) img->Width2);
17408a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      dt = vy / ((GLfloat) img->Height2);
17418a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   }
17428a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17438a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   for (s = 0; s<numSamples; s++) {
17448a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      newCoord[0] = texcoord[0] + ds * ((GLfloat)(s+1) / (numSamples+1) -0.5);
17458a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      newCoord[1] = texcoord[1] + dt * ((GLfloat)(s+1) / (numSamples+1) -0.5);
17468a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17478a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      sample_2d_linear(ctx, tObj, img, newCoord, rgba);
17488a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      num[0] += rgba[0];
17498a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      num[1] += rgba[1];
17508a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      num[2] += rgba[2];
17518a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      num[3] += rgba[3];
17528a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   }
17538a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17548a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   rgba[0] = num[0] / numSamples;
17558a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   rgba[1] = num[1] / numSamples;
17568a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   rgba[2] = num[2] / numSamples;
17578a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   rgba[3] = num[3] / numSamples;
17588a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger}
17598a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17608a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17618a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger/**
17628a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * Returns the index of the specified texture object in the
17638a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * gl_context texture unit array.
17648a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger */
17659520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLuint
17668a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengertexture_unit_index(const struct gl_context *ctx,
17678a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                   const struct gl_texture_object *tObj)
17688a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger{
17698a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLuint maxUnit
17708a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
17718a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLuint u;
17728a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17738a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* XXX CoordUnits vs. ImageUnits */
17748a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   for (u = 0; u < maxUnit; u++) {
17758a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      if (ctx->Texture.Unit[u]._Current == tObj)
17768a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         break; /* found */
17778a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   }
17788a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   if (u >= maxUnit)
17798a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      u = 0; /* not found, use 1st one; should never happen */
17808a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17818a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   return u;
17828a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger}
17838a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17848a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
17858a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger/**
17868a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * Sample 2D texture using an anisotropic filter.
17878a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * NOTE: the const GLfloat lambda_iso[] parameter does *NOT* contain
17888a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * the lambda float array but a "hidden" SWspan struct which is required
17898a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * by this function but is not available in the texture_sample_func signature.
17908a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * See _swrast_texture_span( struct gl_context *ctx, SWspan *span ) on how
17918a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger * this function is called.
17928a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger */
17938a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengerstatic void
17948a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faengersample_lambda_2d_aniso(struct gl_context *ctx,
17958a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                       const struct gl_texture_object *tObj,
17968a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                       GLuint n, const GLfloat texcoords[][4],
17978a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                       const GLfloat lambda_iso[], GLfloat rgba[][4])
17988a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger{
17998a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel];
1800980f6f1b37ca88529b3e000235156eab93254facBrian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(tImg);
18018a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLfloat maxEccentricity =
18028a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      tObj->Sampler.MaxAnisotropy * tObj->Sampler.MaxAnisotropy;
18038a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18048a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* re-calculate the lambda values so that they are usable with anisotropic
18058a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    * filtering
18068a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    */
18078a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   SWspan *span = (SWspan *)lambda_iso; /* access the "hidden" SWspan struct */
18088a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18098a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* based on interpolate_texcoords(struct gl_context *ctx, SWspan *span)
18108a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    * in swrast/s_span.c
18118a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    */
18128a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18138a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* find the texture unit index by looking up the current texture object
18148a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    * from the context list of available texture objects.
18158a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger    */
18168a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLuint u = texture_unit_index(ctx, tObj);
18178a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLuint attr = FRAG_ATTRIB_TEX0 + u;
18188a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat texW, texH;
18198a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18208a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLfloat dsdx = span->attrStepX[attr][0];
18218a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLfloat dsdy = span->attrStepY[attr][0];
18228a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLfloat dtdx = span->attrStepX[attr][1];
18238a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLfloat dtdy = span->attrStepY[attr][1];
18248a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLfloat dqdx = span->attrStepX[attr][3];
18258a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLfloat dqdy = span->attrStepY[attr][3];
18268a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx;
18278a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx;
18288a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx;
18298a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18308a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* from swrast/s_texcombine.c _swrast_texture_span */
18318a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[u];
18328a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   const GLboolean adjustLOD =
18338a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      (texUnit->LodBias + tObj->Sampler.LodBias != 0.0F)
18348a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      || (tObj->Sampler.MinLod != -1000.0 || tObj->Sampler.MaxLod != 1000.0);
18358a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18368a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   GLuint i;
18378a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18388a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   /* on first access create the lookup table containing the filter weights. */
18398a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   if (!weightLut) {
18408a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      create_filter_table();
18418a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   }
18428a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
1843980f6f1b37ca88529b3e000235156eab93254facBrian Paul   texW = swImg->WidthScale;
1844980f6f1b37ca88529b3e000235156eab93254facBrian Paul   texH = swImg->HeightScale;
18458a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18468a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   for (i = 0; i < n; i++) {
18478a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
18488a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18498a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
18508a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
18518a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
18528a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
18538a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18548a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      /* note: instead of working with Px and Py, we will use the
18558a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       * squared length instead, to avoid sqrt.
18568a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       */
18578a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat Px2 = dudx * dudx + dvdx * dvdx;
18588a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat Py2 = dudy * dudy + dvdy * dvdy;
18598a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18608a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat Pmax2;
18618a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat Pmin2;
18628a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat e;
18638a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      GLfloat lod;
18648a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18658a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      s += dsdx;
18668a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      t += dtdx;
18678a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      q += dqdx;
18688a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18698a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      if (Px2 < Py2) {
18708a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         Pmax2 = Py2;
18718a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         Pmin2 = Px2;
18728a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      }
18738a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      else {
18748a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         Pmax2 = Px2;
18758a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         Pmin2 = Py2;
18768a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      }
18778a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18788a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      /* if the eccentricity of the ellipse is too big, scale up the shorter
18798a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       * of the two vectors to limit the maximum amount of work per pixel
18808a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       */
18818a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      e = Pmax2 / Pmin2;
18828a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      if (e > maxEccentricity) {
18838a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         /* GLfloat s=e / maxEccentricity;
18848a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            minor[0] *= s;
18858a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            minor[1] *= s;
18868a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            Pmin2 *= s; */
18878a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         Pmin2 = Pmax2 / maxEccentricity;
18888a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      }
18898a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18908a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
18918a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       * this since 0.5*log(x) = log(sqrt(x))
18928a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       */
18938a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      lod = 0.5 * LOG2(Pmin2);
18948a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
18958a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      if (adjustLOD) {
18968a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         /* from swrast/s_texcombine.c _swrast_texture_span */
18978a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         if (texUnit->LodBias + tObj->Sampler.LodBias != 0.0F) {
18988a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            /* apply LOD bias, but don't clamp yet */
18998a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            const GLfloat bias =
19008a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger               CLAMP(texUnit->LodBias + tObj->Sampler.LodBias,
19018a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                     -ctx->Const.MaxTextureLodBias,
19028a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                     ctx->Const.MaxTextureLodBias);
19038a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            lod += bias;
19048a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
19058a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            if (tObj->Sampler.MinLod != -1000.0 ||
19068a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                tObj->Sampler.MaxLod != 1000.0) {
19078a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger               /* apply LOD clamping to lambda */
19088a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger               lod = CLAMP(lod, tObj->Sampler.MinLod, tObj->Sampler.MaxLod);
19098a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            }
19108a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         }
19118a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      }
19128a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
19138a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      /* If the ellipse covers the whole image, we can
19148a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       * simply return the average of the whole image.
19158a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger       */
19168a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      if (lod >= tObj->_MaxLevel) {
19178a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
19188a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                          texcoords[i], rgba[i]);
19198a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      }
19208a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      else {
19218a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         /* don't bother interpolating between multiple LODs; it doesn't
19228a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger          * seem to be worth the extra running time.
19238a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger          */
19248a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         sample_2d_ewa(ctx, tObj, texcoords[i],
19258a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                       dudx, dvdx, dudy, dvdy, floor(lod), rgba[i]);
19268a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
19278a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         /* unused: */
19288a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         (void) sample_2d_footprint;
19298a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         /*
19308a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         sample_2d_footprint(ctx, tObj, texcoords[i],
19318a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                             dudx, dvdx, dudy, dvdy, floor(lod), rgba[i]);
19328a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger         */
19338a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger      }
19348a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger   }
19358a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger}
19368a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
19378a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger
19382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
19392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
19402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/*                    3-D Texture Sampling Functions                  */
19412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
19422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
19436e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
19442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
19452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
19469520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
1947f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_3d_nearest(struct gl_context *ctx,
19482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const struct gl_texture_object *tObj,
19492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const struct gl_texture_image *img,
19502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const GLfloat texcoord[4],
1951de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                  GLfloat rgba[4])
19522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
1953a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
19542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint width = img->Width2;     /* without border, power of two */
19552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint height = img->Height2;   /* without border, power of two */
19562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint depth = img->Depth2;     /* without border, power of two */
19572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLint i, j, k;
19582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) ctx;
19592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1960ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
1961ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]);
1962ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   k = nearest_texel_location(tObj->Sampler.WrapR, img, depth, texcoord[2]);
19632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
19642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (i < 0 || i >= (GLint) img->Width ||
19652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul       j < 0 || j >= (GLint) img->Height ||
19662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul       k < 0 || k >= (GLint) img->Depth) {
19672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* Need this test for GL_CLAMP_TO_BORDER mode */
1968b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, rgba);
19692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
19702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
1971a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i, j, k, rgba);
19722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
19732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
19742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
19752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
19766e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
19772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
19782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
19792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
1980f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_3d_linear(struct gl_context *ctx,
19812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                 const struct gl_texture_object *tObj,
19822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                 const struct gl_texture_image *img,
19832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                 const GLfloat texcoord[4],
1984de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                 GLfloat rgba[4])
19852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
1986a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
19872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint width = img->Width2;
19882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint height = img->Height2;
19892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLint depth = img->Depth2;
19902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLint i0, j0, k0, i1, j1, k1;
19910f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   GLbitfield useBorderColor = 0x0;
19920f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   GLfloat a, b, c;
1993de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul   GLfloat t000[4], t010[4], t001[4], t011[4];
1994de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul   GLfloat t100[4], t110[4], t101[4], t111[4];
19952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
1996ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0],  &i0, &i1, &a);
1997ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b);
1998ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   linear_texel_locations(tObj->Sampler.WrapR, img, depth, texcoord[2],  &k0, &k1, &c);
19992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
20002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (img->Border) {
20012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      i0 += img->Border;
20022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      i1 += img->Border;
20032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      j0 += img->Border;
20042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      j1 += img->Border;
20052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      k0 += img->Border;
20062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      k1 += img->Border;
20072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
20082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
20092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* check if sampling texture border color */
20102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
20112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
20122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
20132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
20142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (k0 < 0 || k0 >= depth)   useBorderColor |= K0BIT;
20152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (k1 < 0 || k1 >= depth)   useBorderColor |= K1BIT;
20162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
20172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
20180f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   /* Fetch texels */
20190f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
2020b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t000);
20210f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20220f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
2023a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i0, j0, k0, t000);
20240f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20250f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
2026b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t100);
20270f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20280f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
2029a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i1, j0, k0, t100);
20300f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20310f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
2032b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t010);
20330f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20340f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
2035a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i0, j1, k0, t010);
20360f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20370f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
2038b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t110);
20390f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20400f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
2041a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i1, j1, k0, t110);
20420f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
20440f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
2045b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t001);
20460f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20470f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
2048a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i0, j0, k1, t001);
20490f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20500f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
2051b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t101);
20520f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20530f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
2054a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i1, j0, k1, t101);
20550f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20560f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
2057b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t011);
20580f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20590f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
2060a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i0, j1, k1, t011);
20612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
20620f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
2063b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t111);
20640f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20650f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   else {
2066a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i1, j1, k1, t111);
20670f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   }
20680f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul
20690f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   /* trilinear interpolation of samples */
20700f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul   lerp_rgba_3d(rgba, a, b, c, t000, t100, t010, t110, t001, t101, t011, t111);
20712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
20722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
20732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
20742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2075f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_3d_nearest_mipmap_nearest(struct gl_context *ctx,
20762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 const struct gl_texture_object *tObj,
20772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 GLuint n, const GLfloat texcoord[][4],
2078de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                 const GLfloat lambda[], GLfloat rgba[][4] )
20792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
20802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
20812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
2082792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = nearest_mipmap_level(tObj, lambda[i]);
20832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_3d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
20842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
20852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
20862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
20872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
20882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2089f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_3d_linear_mipmap_nearest(struct gl_context *ctx,
20902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                const struct gl_texture_object *tObj,
20912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                GLuint n, const GLfloat texcoord[][4],
2092de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                const GLfloat lambda[], GLfloat rgba[][4])
20932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
20942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
20952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
20962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
2097792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = nearest_mipmap_level(tObj, lambda[i]);
20982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_3d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
20992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
21002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
21012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2104f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_3d_nearest_mipmap_linear(struct gl_context *ctx,
21052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                const struct gl_texture_object *tObj,
21062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                GLuint n, const GLfloat texcoord[][4],
2107de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                const GLfloat lambda[], GLfloat rgba[][4])
21082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
21092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
21102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
21112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
2112792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = linear_mipmap_level(tObj, lambda[i]);
21132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (level >= tObj->_MaxLevel) {
21142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
21152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                           texcoord[i], rgba[i]);
21162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
21172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
2118de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
21192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         const GLfloat f = FRAC(lambda[i]);
21202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
21212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
21222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         lerp_rgba(rgba[i], f, t0, t1);
21232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
21242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
21252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
21262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2129f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_3d_linear_mipmap_linear(struct gl_context *ctx,
21302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                               const struct gl_texture_object *tObj,
21312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                               GLuint n, const GLfloat texcoord[][4],
2132de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                               const GLfloat lambda[], GLfloat rgba[][4])
21332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
21342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
21352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
21362cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
2137792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = linear_mipmap_level(tObj, lambda[i]);
21382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (level >= tObj->_MaxLevel) {
21392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
21402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                          texcoord[i], rgba[i]);
21412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
21422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
2143de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
21442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         const GLfloat f = FRAC(lambda[i]);
21452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
21462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
21472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         lerp_rgba(rgba[i], f, t0, t1);
21482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
21492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
21502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
21512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21536e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 3D texture, nearest filtering for both min/magnification */
21542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2155f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_nearest_3d(struct gl_context *ctx,
21562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const struct gl_texture_object *tObj, GLuint n,
21572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                  const GLfloat texcoords[][4], const GLfloat lambda[],
2158de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                  GLfloat rgba[][4])
21592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
21602cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
21612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
21622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
21636e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   for (i = 0; i < n; i++) {
21642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
21652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
21662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
21672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21696e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 3D texture, linear filtering for both min/magnification */
21702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2171f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_linear_3d(struct gl_context *ctx,
21726e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                 const struct gl_texture_object *tObj, GLuint n,
21736e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                 const GLfloat texcoords[][4],
2174de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul		 const GLfloat lambda[], GLfloat rgba[][4])
21752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
21762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
21772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
21782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
21796e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   for (i = 0; i < n; i++) {
21802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
21812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
21822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
21832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21856e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 3D texture, using lambda to choose between min/magnification */
21862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2187f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_lambda_3d(struct gl_context *ctx,
21886e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                 const struct gl_texture_object *tObj, GLuint n,
21896e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                 const GLfloat texcoords[][4], const GLfloat lambda[],
2190de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                 GLfloat rgba[][4])
21912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
21922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint minStart, minEnd;  /* texels with minification */
21932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint magStart, magEnd;  /* texels with magnification */
21942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
21952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
21962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
2197aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   compute_min_mag_ranges(tObj, n, lambda,
2198aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul                          &minStart, &minEnd, &magStart, &magEnd);
21992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
22002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (minStart < minEnd) {
22012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* do the minified texels */
22022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLuint m = minEnd - minStart;
2203ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MinFilter) {
22042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST:
22052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = minStart; i < minEnd; i++)
22062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
22072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                              texcoords[i], rgba[i]);
22082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
22092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR:
22102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = minStart; i < minEnd; i++)
22112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
22122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                             texcoords[i], rgba[i]);
22132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
22142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST_MIPMAP_NEAREST:
22152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
22162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                          lambda + minStart, rgba + minStart);
22172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
22182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR_MIPMAP_NEAREST:
22192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
22202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                         lambda + minStart, rgba + minStart);
22212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
22222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST_MIPMAP_LINEAR:
22232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
22242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                         lambda + minStart, rgba + minStart);
22252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
22262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR_MIPMAP_LINEAR:
22272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
22282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                        lambda + minStart, rgba + minStart);
22292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
22302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      default:
22312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         _mesa_problem(ctx, "Bad min filter in sample_3d_texture");
22322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         return;
22332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
22342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
22352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
22362cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (magStart < magEnd) {
22372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* do the magnified texels */
2238ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MagFilter) {
22392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST:
22402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = magStart; i < magEnd; i++)
22412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
22422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                              texcoords[i], rgba[i]);
22432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
22442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR:
22452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         for (i = magStart; i < magEnd; i++)
22462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
22472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                             texcoords[i], rgba[i]);
22482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
22492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      default:
22502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         _mesa_problem(ctx, "Bad mag filter in sample_3d_texture");
22512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         return;
22522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
22532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
22542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
22552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
22562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
22572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
22582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/*                Texture Cube Map Sampling Functions                 */
22592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
22602cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
22612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
22622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Choose one of six sides of a texture cube map given the texture
22632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * coord (rx,ry,rz).  Return pointer to corresponding array of texture
22642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * images.
22652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
22662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic const struct gl_texture_image **
22672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulchoose_cube_face(const struct gl_texture_object *texObj,
22682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                 const GLfloat texcoord[4], GLfloat newCoord[4])
22692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
22702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   /*
22712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      major axis
22722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      direction     target                             sc     tc    ma
22732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      ----------    -------------------------------    ---    ---   ---
22742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul       +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
22752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul       -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
22762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul       +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
22772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul       -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
22782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul       +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
22792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul       -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
22802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   */
22812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat rx = texcoord[0];
22822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat ry = texcoord[1];
22832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat rz = texcoord[2];
22842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz);
22852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint face;
22862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLfloat sc, tc, ma;
22872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
2288d504a7669d7b71229c2d15503a095d71ee1584e6Brian Paul   if (arx >= ary && arx >= arz) {
22892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (rx >= 0.0F) {
22902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         face = FACE_POS_X;
22912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sc = -rz;
22922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         tc = -ry;
22932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         ma = arx;
22942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
22952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
22962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         face = FACE_NEG_X;
22972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sc = rz;
22982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         tc = -ry;
22992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         ma = arx;
23002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
23012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
2302d504a7669d7b71229c2d15503a095d71ee1584e6Brian Paul   else if (ary >= arx && ary >= arz) {
23032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (ry >= 0.0F) {
23042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         face = FACE_POS_Y;
23052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sc = rx;
23062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         tc = rz;
23072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         ma = ary;
23082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
23092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
23102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         face = FACE_NEG_Y;
23112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sc = rx;
23122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         tc = -rz;
23132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         ma = ary;
23142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
23152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
23162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
23172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (rz > 0.0F) {
23182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         face = FACE_POS_Z;
23192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sc = rx;
23202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         tc = -ry;
23212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         ma = arz;
23222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
23232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
23242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         face = FACE_NEG_Z;
23252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sc = -rx;
23262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         tc = -ry;
23272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         ma = arz;
23282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
23292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
23302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
233167d4a5b15cfd8583c19a5776b0ec1564b60239ebKeith Whitwell   {
233267d4a5b15cfd8583c19a5776b0ec1564b60239ebKeith Whitwell      const float ima = 1.0F / ma;
233367d4a5b15cfd8583c19a5776b0ec1564b60239ebKeith Whitwell      newCoord[0] = ( sc * ima + 1.0F ) * 0.5F;
233467d4a5b15cfd8583c19a5776b0ec1564b60239ebKeith Whitwell      newCoord[1] = ( tc * ima + 1.0F ) * 0.5F;
233567d4a5b15cfd8583c19a5776b0ec1564b60239ebKeith Whitwell   }
233667d4a5b15cfd8583c19a5776b0ec1564b60239ebKeith Whitwell
23372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   return (const struct gl_texture_image **) texObj->Image[face];
23382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
23392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
23402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
23412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2342f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_nearest_cube(struct gl_context *ctx,
23432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul		    const struct gl_texture_object *tObj, GLuint n,
23442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                    const GLfloat texcoords[][4], const GLfloat lambda[],
2345de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                    GLfloat rgba[][4])
23462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
23472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
23482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
23492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
23502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const struct gl_texture_image **images;
23512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLfloat newCoord[4];
23522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      images = choose_cube_face(tObj, texcoords[i], newCoord);
23532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
23542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                        newCoord, rgba[i]);
23552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
23562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
23572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
23582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
23592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2360f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_linear_cube(struct gl_context *ctx,
23612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul		   const struct gl_texture_object *tObj, GLuint n,
23622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                   const GLfloat texcoords[][4],
2363de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul		   const GLfloat lambda[], GLfloat rgba[][4])
23642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
23652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
23662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
23672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
23682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const struct gl_texture_image **images;
23692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLfloat newCoord[4];
23702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      images = choose_cube_face(tObj, texcoords[i], newCoord);
23712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
23722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                       newCoord, rgba[i]);
23732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
23742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
23752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
23762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
23772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2378f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_cube_nearest_mipmap_nearest(struct gl_context *ctx,
23792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                   const struct gl_texture_object *tObj,
23802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                   GLuint n, const GLfloat texcoord[][4],
2381de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                   const GLfloat lambda[], GLfloat rgba[][4])
23822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
23832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
23842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
23852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
23862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const struct gl_texture_image **images;
23872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLfloat newCoord[4];
238821177c8764638e1d4b3b29fed64adec62a14e936Brian Paul      GLint level;
23892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      images = choose_cube_face(tObj, texcoord[i], newCoord);
239021177c8764638e1d4b3b29fed64adec62a14e936Brian Paul
239121177c8764638e1d4b3b29fed64adec62a14e936Brian Paul      /* XXX we actually need to recompute lambda here based on the newCoords.
239221177c8764638e1d4b3b29fed64adec62a14e936Brian Paul       * But we would need the texcoords of adjacent fragments to compute that
239321177c8764638e1d4b3b29fed64adec62a14e936Brian Paul       * properly, and we don't have those here.
239421177c8764638e1d4b3b29fed64adec62a14e936Brian Paul       * For now, do an approximation:  subtracting 1 from the chosen mipmap
239521177c8764638e1d4b3b29fed64adec62a14e936Brian Paul       * level seems to work in some test cases.
239621177c8764638e1d4b3b29fed64adec62a14e936Brian Paul       * The same adjustment is done in the next few functions.
239721177c8764638e1d4b3b29fed64adec62a14e936Brian Paul      */
239821177c8764638e1d4b3b29fed64adec62a14e936Brian Paul      level = nearest_mipmap_level(tObj, lambda[i]);
239921177c8764638e1d4b3b29fed64adec62a14e936Brian Paul      level = MAX2(level - 1, 0);
240021177c8764638e1d4b3b29fed64adec62a14e936Brian Paul
24012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]);
24022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
24032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
24042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2407f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_cube_linear_mipmap_nearest(struct gl_context *ctx,
24082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                  const struct gl_texture_object *tObj,
24092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                  GLuint n, const GLfloat texcoord[][4],
2410de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                  const GLfloat lambda[], GLfloat rgba[][4])
24112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
24122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
24132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
24142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
24152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const struct gl_texture_image **images;
24162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLfloat newCoord[4];
2417792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = nearest_mipmap_level(tObj, lambda[i]);
241821177c8764638e1d4b3b29fed64adec62a14e936Brian Paul      level = MAX2(level - 1, 0); /* see comment above */
24192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      images = choose_cube_face(tObj, texcoord[i], newCoord);
24202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]);
24212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
24222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
24232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2426f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_cube_nearest_mipmap_linear(struct gl_context *ctx,
24272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                  const struct gl_texture_object *tObj,
24282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                  GLuint n, const GLfloat texcoord[][4],
2429de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                  const GLfloat lambda[], GLfloat rgba[][4])
24302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
24312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
24322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
24332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
24342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const struct gl_texture_image **images;
24352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLfloat newCoord[4];
2436792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = linear_mipmap_level(tObj, lambda[i]);
243721177c8764638e1d4b3b29fed64adec62a14e936Brian Paul      level = MAX2(level - 1, 0); /* see comment above */
24382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      images = choose_cube_face(tObj, texcoord[i], newCoord);
24392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (level >= tObj->_MaxLevel) {
24402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel],
24412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                           newCoord, rgba[i]);
24422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
24432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
2444de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
24452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         const GLfloat f = FRAC(lambda[i]);
24462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_nearest(ctx, tObj, images[level  ], newCoord, t0);
24472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1);
24482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         lerp_rgba(rgba[i], f, t0, t1);
24492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
24502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
24512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
24522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2455f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_cube_linear_mipmap_linear(struct gl_context *ctx,
24562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 const struct gl_texture_object *tObj,
24572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                 GLuint n, const GLfloat texcoord[][4],
2458de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                 const GLfloat lambda[], GLfloat rgba[][4])
24592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
24602cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
24612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
24622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
24632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const struct gl_texture_image **images;
24642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLfloat newCoord[4];
2465792a1bcbe4c4b4f5f96d6ac017fcb5376900ea75Brian Paul      GLint level = linear_mipmap_level(tObj, lambda[i]);
246621177c8764638e1d4b3b29fed64adec62a14e936Brian Paul      level = MAX2(level - 1, 0); /* see comment above */
24672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      images = choose_cube_face(tObj, texcoord[i], newCoord);
24682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (level >= tObj->_MaxLevel) {
24692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel],
24702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                          newCoord, rgba[i]);
24712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
24722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
2473de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];
24742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         const GLfloat f = FRAC(lambda[i]);
24752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear(ctx, tObj, images[level  ], newCoord, t0);
24762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1);
24772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         lerp_rgba(rgba[i], f, t0, t1);
24782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
24792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
24802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
24812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24836e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample cube texture, using lambda to choose between min/magnification */
24842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2485f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_lambda_cube(struct gl_context *ctx,
24866e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian		   const struct gl_texture_object *tObj, GLuint n,
24876e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian		   const GLfloat texcoords[][4], const GLfloat lambda[],
2488de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul		   GLfloat rgba[][4])
24892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
24902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint minStart, minEnd;  /* texels with minification */
24912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint magStart, magEnd;  /* texels with magnification */
24922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(lambda != NULL);
2494aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   compute_min_mag_ranges(tObj, n, lambda,
2495aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul                          &minStart, &minEnd, &magStart, &magEnd);
24962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
24972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (minStart < minEnd) {
24982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* do the minified texels */
24992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const GLuint m = minEnd - minStart;
2500ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MinFilter) {
25012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST:
2502aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul         sample_nearest_cube(ctx, tObj, m, texcoords + minStart,
25032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                             lambda + minStart, rgba + minStart);
25042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
25052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR:
2506aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul         sample_linear_cube(ctx, tObj, m, texcoords + minStart,
25072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                            lambda + minStart, rgba + minStart);
25082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
25092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST_MIPMAP_NEAREST:
2510aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul         sample_cube_nearest_mipmap_nearest(ctx, tObj, m,
25112cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                            texcoords + minStart,
25122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                           lambda + minStart, rgba + minStart);
25132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
25142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR_MIPMAP_NEAREST:
2515aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul         sample_cube_linear_mipmap_nearest(ctx, tObj, m,
25162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                           texcoords + minStart,
25172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                           lambda + minStart, rgba + minStart);
25182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
25192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST_MIPMAP_LINEAR:
2520aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul         sample_cube_nearest_mipmap_linear(ctx, tObj, m,
25212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                           texcoords + minStart,
25222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                           lambda + minStart, rgba + minStart);
25232cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
25242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR_MIPMAP_LINEAR:
2525aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul         sample_cube_linear_mipmap_linear(ctx, tObj, m,
25262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                          texcoords + minStart,
25272cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                                          lambda + minStart, rgba + minStart);
25282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
25292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      default:
25302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         _mesa_problem(ctx, "Bad min filter in sample_lambda_cube");
25312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
25322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
25332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
25342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (magStart < magEnd) {
25352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* do the magnified texels */
25362cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      const GLuint m = magEnd - magStart;
2537ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MagFilter) {
25382cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_NEAREST:
2539aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul         sample_nearest_cube(ctx, tObj, m, texcoords + magStart,
25402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                             lambda + magStart, rgba + magStart);
25412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
25422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_LINEAR:
2543aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul         sample_linear_cube(ctx, tObj, m, texcoords + magStart,
25442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                            lambda + magStart, rgba + magStart);
25452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         break;
25462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      default:
25472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube");
25482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
25492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
25502cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
25512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
25522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
25532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
25542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/*               Texture Rectangle Sampling Functions                 */
25552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**********************************************************************/
25562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
2557fde15a2bae2f2ca552763705f12d53e4606feabfBrian
25582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2559f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_nearest_rect(struct gl_context *ctx,
25602cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul		    const struct gl_texture_object *tObj, GLuint n,
25612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                    const GLfloat texcoords[][4], const GLfloat lambda[],
2562de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                    GLfloat rgba[][4])
25632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
25642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const struct gl_texture_image *img = tObj->Image[0][0];
2565a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
25666e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   const GLint width = img->Width;
25676e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   const GLint height = img->Height;
25682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
25692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
25702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) ctx;
25712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
25722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
2573ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapS == GL_CLAMP ||
2574ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul          tObj->Sampler.WrapS == GL_CLAMP_TO_EDGE ||
2575ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul          tObj->Sampler.WrapS == GL_CLAMP_TO_BORDER);
2576ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapT == GL_CLAMP ||
2577ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul          tObj->Sampler.WrapT == GL_CLAMP_TO_EDGE ||
2578ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul          tObj->Sampler.WrapT == GL_CLAMP_TO_BORDER);
25792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
25802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
25812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLint row, col;
2582ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      col = clamp_rect_coord_nearest(tObj->Sampler.WrapS, texcoords[i][0], width);
2583ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      row = clamp_rect_coord_nearest(tObj->Sampler.WrapT, texcoords[i][1], height);
25846e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian      if (col < 0 || col >= width || row < 0 || row >= height)
2585b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul         get_border_color(tObj, img, rgba[i]);
25862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else
2587a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul         swImg->FetchTexelf(swImg, col, row, 0, rgba[i]);
25882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
25892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
25902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
25912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
25922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2593f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_linear_rect(struct gl_context *ctx,
25942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul		   const struct gl_texture_object *tObj, GLuint n,
25952cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                   const GLfloat texcoords[][4],
2596de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul		   const GLfloat lambda[], GLfloat rgba[][4])
25972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
25982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   const struct gl_texture_image *img = tObj->Image[0][0];
2599a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
26006e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   const GLint width = img->Width;
26016e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   const GLint height = img->Height;
26022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
26032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) ctx;
26052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
26062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
2607ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapS == GL_CLAMP ||
2608ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul          tObj->Sampler.WrapS == GL_CLAMP_TO_EDGE ||
2609ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul          tObj->Sampler.WrapS == GL_CLAMP_TO_BORDER);
2610ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ASSERT(tObj->Sampler.WrapT == GL_CLAMP ||
2611ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul          tObj->Sampler.WrapT == GL_CLAMP_TO_EDGE ||
2612ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul          tObj->Sampler.WrapT == GL_CLAMP_TO_BORDER);
26132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
26152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLint i0, j0, i1, j1;
2616de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul      GLfloat t00[4], t01[4], t10[4], t11[4];
26172cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLfloat a, b;
26180f540f4b0468f581f63fb0b6347fe66251fa545aBrian Paul      GLbitfield useBorderColor = 0x0;
26192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
2620ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      clamp_rect_coord_linear(tObj->Sampler.WrapS, texcoords[i][0], width,
2621249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian                              &i0, &i1, &a);
2622ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      clamp_rect_coord_linear(tObj->Sampler.WrapT, texcoords[i][1], height,
2623249e1e4d30759cd3c55cef0dba75f531cc7c6269Brian                              &j0, &j1, &b);
26242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* compute integer rows/columns */
26266e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian      if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
26276e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian      if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
26286e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian      if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
26296e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian      if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
26302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      /* get four texel samples */
26322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (useBorderColor & (I0BIT | J0BIT))
2633b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul         get_border_color(tObj, img, t00);
26342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else
2635a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul         swImg->FetchTexelf(swImg, i0, j0, 0, t00);
26362cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (useBorderColor & (I1BIT | J0BIT))
2638b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul         get_border_color(tObj, img, t10);
26392cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else
2640a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul         swImg->FetchTexelf(swImg, i1, j0, 0, t10);
26412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (useBorderColor & (I0BIT | J1BIT))
2643b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul         get_border_color(tObj, img, t01);
26442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else
2645a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul         swImg->FetchTexelf(swImg, i0, j1, 0, t01);
26462cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      if (useBorderColor & (I1BIT | J1BIT))
2648b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul         get_border_color(tObj, img, t11);
26492cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else
2650a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul         swImg->FetchTexelf(swImg, i1, j1, 0, t11);
26512cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26522cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      lerp_rgba_2d(rgba[i], a, b, t00, t10, t01, t11);
26532cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
26542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
26552cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26576e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample Rect texture, using lambda to choose between min/magnification */
26582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
2659f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_lambda_rect(struct gl_context *ctx,
26606e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian		   const struct gl_texture_object *tObj, GLuint n,
26616e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian		   const GLfloat texcoords[][4], const GLfloat lambda[],
2662de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul		   GLfloat rgba[][4])
26632cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
26642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint minStart, minEnd, magStart, magEnd;
26652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   /* We only need lambda to decide between minification and magnification.
26672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul    * There is no mipmapping with rectangular textures.
26682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul    */
2669aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul   compute_min_mag_ranges(tObj, n, lambda,
2670aa8abf8081023c00469b6c88760ed0291033eb6eBrian Paul                          &minStart, &minEnd, &magStart, &magEnd);
26712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (minStart < minEnd) {
2673ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      if (tObj->Sampler.MinFilter == GL_NEAREST) {
26746e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_nearest_rect(ctx, tObj, minEnd - minStart,
26756e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                             texcoords + minStart, NULL, rgba + minStart);
26762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
26772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
26786e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_linear_rect(ctx, tObj, minEnd - minStart,
26796e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                            texcoords + minStart, NULL, rgba + minStart);
26802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
26812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
26822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   if (magStart < magEnd) {
2683ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      if (tObj->Sampler.MagFilter == GL_NEAREST) {
26846e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_nearest_rect(ctx, tObj, magEnd - magStart,
26856e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                             texcoords + magStart, NULL, rgba + magStart);
26862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
26872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      else {
26886e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_linear_rect(ctx, tObj, magEnd - magStart,
26896e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                            texcoords + magStart, NULL, rgba + magStart);
26902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
26912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
26922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
26932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
26942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
2695bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick/**********************************************************************/
2696bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick/*                2D Texture Array Sampling Functions                 */
2697bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick/**********************************************************************/
2698bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
26996e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
2700bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
2701bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick */
2702bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
2703f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_array_nearest(struct gl_context *ctx,
2704bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                        const struct gl_texture_object *tObj,
2705bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                        const struct gl_texture_image *img,
2706bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                        const GLfloat texcoord[4],
2707de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                        GLfloat rgba[4])
2708bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
2709a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
2710bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint width = img->Width2;     /* without border, power of two */
2711bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint height = img->Height2;   /* without border, power of two */
2712bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint depth = img->Depth;
2713bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLint i, j;
2714bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLint array;
2715bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   (void) ctx;
2716bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2717ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
2718ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   j = nearest_texel_location(tObj->Sampler.WrapT, img, height, texcoord[1]);
271958ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul   array = tex_array_slice(texcoord[2], depth);
2720bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2721bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (i < 0 || i >= (GLint) img->Width ||
2722bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick       j < 0 || j >= (GLint) img->Height ||
2723bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick       array < 0 || array >= (GLint) img->Depth) {
2724bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      /* Need this test for GL_CLAMP_TO_BORDER mode */
2725b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, rgba);
2726bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2727bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   else {
2728a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i, j, array, rgba);
2729bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2730bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
2731bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2732bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
27336e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
2734bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
2735bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick */
2736bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
2737f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_array_linear(struct gl_context *ctx,
2738bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const struct gl_texture_object *tObj,
2739bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const struct gl_texture_image *img,
2740bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const GLfloat texcoord[4],
2741de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                       GLfloat rgba[4])
2742bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
2743a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
2744bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint width = img->Width2;
2745bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint height = img->Height2;
2746bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint depth = img->Depth;
2747bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLint i0, j0, i1, j1;
2748bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLint array;
2749bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLbitfield useBorderColor = 0x0;
2750bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLfloat a, b;
2751de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul   GLfloat t00[4], t01[4], t10[4], t11[4];
2752bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2753ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   linear_texel_locations(tObj->Sampler.WrapS, img, width,  texcoord[0], &i0, &i1, &a);
2754ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   linear_texel_locations(tObj->Sampler.WrapT, img, height, texcoord[1], &j0, &j1, &b);
275558ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul   array = tex_array_slice(texcoord[2], depth);
2756bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2757bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (array < 0 || array >= depth) {
2758ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      COPY_4V(rgba, tObj->Sampler.BorderColor.f);
2759bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2760bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   else {
2761bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (img->Border) {
2762bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick	 i0 += img->Border;
2763bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick	 i1 += img->Border;
2764bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick	 j0 += img->Border;
2765bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick	 j1 += img->Border;
2766bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2767bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      else {
2768bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick	 /* check if sampling texture border color */
2769bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick	 if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
2770bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick	 if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
2771bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick	 if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
2772bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick	 if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
2773bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2774bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2775bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      /* Fetch texels */
2776bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (useBorderColor & (I0BIT | J0BIT)) {
2777b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul         get_border_color(tObj, img, t00);
2778bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2779bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      else {
2780a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul	 swImg->FetchTexelf(swImg, i0, j0, array, t00);
2781bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2782bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (useBorderColor & (I1BIT | J0BIT)) {
2783b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul         get_border_color(tObj, img, t10);
2784bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2785bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      else {
2786a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul	 swImg->FetchTexelf(swImg, i1, j0, array, t10);
2787bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2788bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (useBorderColor & (I0BIT | J1BIT)) {
2789b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul         get_border_color(tObj, img, t01);
2790bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2791bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      else {
2792a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul	 swImg->FetchTexelf(swImg, i0, j1, array, t01);
2793bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2794bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (useBorderColor & (I1BIT | J1BIT)) {
2795b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul         get_border_color(tObj, img, t11);
2796bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2797bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      else {
2798a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul	 swImg->FetchTexelf(swImg, i1, j1, array, t11);
2799bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2800bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2801bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      /* trilinear interpolation of samples */
2802bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11);
2803bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2804bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
2805bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2806bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2807bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
2808f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_array_nearest_mipmap_nearest(struct gl_context *ctx,
2809bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                       const struct gl_texture_object *tObj,
2810bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                       GLuint n, const GLfloat texcoord[][4],
2811de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                       const GLfloat lambda[], GLfloat rgba[][4])
2812bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
2813bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
2814bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   for (i = 0; i < n; i++) {
2815bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLint level = nearest_mipmap_level(tObj, lambda[i]);
2816bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
2817bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                              rgba[i]);
2818bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2819bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
2820bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2821bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2822bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
2823f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_array_linear_mipmap_nearest(struct gl_context *ctx,
2824bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                      const struct gl_texture_object *tObj,
2825bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                      GLuint n, const GLfloat texcoord[][4],
2826de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                      const GLfloat lambda[], GLfloat rgba[][4])
2827bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
2828bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
2829bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   ASSERT(lambda != NULL);
2830bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   for (i = 0; i < n; i++) {
2831bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLint level = nearest_mipmap_level(tObj, lambda[i]);
2832bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      sample_2d_array_linear(ctx, tObj, tObj->Image[0][level],
2833bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                             texcoord[i], rgba[i]);
2834bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2835bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
2836bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2837bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2838bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
2839f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_array_nearest_mipmap_linear(struct gl_context *ctx,
2840bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                      const struct gl_texture_object *tObj,
2841bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                      GLuint n, const GLfloat texcoord[][4],
2842de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                      const GLfloat lambda[], GLfloat rgba[][4])
2843bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
2844bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
2845bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   ASSERT(lambda != NULL);
2846bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   for (i = 0; i < n; i++) {
2847bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLint level = linear_mipmap_level(tObj, lambda[i]);
2848bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (level >= tObj->_MaxLevel) {
2849bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
2850bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                 texcoord[i], rgba[i]);
2851bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2852bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      else {
2853de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
2854bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         const GLfloat f = FRAC(lambda[i]);
28556e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level  ],
28566e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                 texcoord[i], t0);
28576e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level+1],
28586e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                 texcoord[i], t1);
2859bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         lerp_rgba(rgba[i], f, t0, t1);
2860bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2861bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2862bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
2863bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2864bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2865bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
2866f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_2d_array_linear_mipmap_linear(struct gl_context *ctx,
28676e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                     const struct gl_texture_object *tObj,
28686e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                     GLuint n, const GLfloat texcoord[][4],
2869de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                     const GLfloat lambda[], GLfloat rgba[][4])
2870bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
2871bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
2872bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   ASSERT(lambda != NULL);
2873bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   for (i = 0; i < n; i++) {
2874bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLint level = linear_mipmap_level(tObj, lambda[i]);
2875bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (level >= tObj->_MaxLevel) {
2876bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
2877bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                          texcoord[i], rgba[i]);
2878bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2879bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      else {
2880de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
2881bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         const GLfloat f = FRAC(lambda[i]);
28826e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_2d_array_linear(ctx, tObj, tObj->Image[0][level  ],
28836e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                texcoord[i], t0);
28846e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_2d_array_linear(ctx, tObj, tObj->Image[0][level+1],
28856e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                texcoord[i], t1);
2886bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         lerp_rgba(rgba[i], f, t0, t1);
2887bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2888bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2889bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
2890bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2891bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
28926e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 2D Array texture, nearest filtering for both min/magnification */
2893bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
2894f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_nearest_2d_array(struct gl_context *ctx,
28956e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                        const struct gl_texture_object *tObj, GLuint n,
28966e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                        const GLfloat texcoords[][4], const GLfloat lambda[],
2897de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                        GLfloat rgba[][4])
2898bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
2899bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
2900bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
2901bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   (void) lambda;
29026e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   for (i = 0; i < n; i++) {
2903bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      sample_2d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
2904bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2905bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
2906bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2907bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2908bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
29096e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 2D Array texture, linear filtering for both min/magnification */
2910bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
2911f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_linear_2d_array(struct gl_context *ctx,
2912bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const struct gl_texture_object *tObj, GLuint n,
2913bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const GLfloat texcoords[][4],
2914de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                       const GLfloat lambda[], GLfloat rgba[][4])
2915bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
2916bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
2917bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
2918bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   (void) lambda;
29196e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   for (i = 0; i < n; i++) {
2920bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      sample_2d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
2921bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2922bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
2923bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2924bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
29256e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 2D Array texture, using lambda to choose between min/magnification */
2926bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
2927f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_lambda_2d_array(struct gl_context *ctx,
2928bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const struct gl_texture_object *tObj, GLuint n,
2929bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const GLfloat texcoords[][4], const GLfloat lambda[],
2930de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                       GLfloat rgba[][4])
2931bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
2932bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint minStart, minEnd;  /* texels with minification */
2933bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint magStart, magEnd;  /* texels with magnification */
2934bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
2935bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2936bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   ASSERT(lambda != NULL);
2937bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   compute_min_mag_ranges(tObj, n, lambda,
2938bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                          &minStart, &minEnd, &magStart, &magEnd);
2939bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2940bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (minStart < minEnd) {
2941bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      /* do the minified texels */
2942bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLuint m = minEnd - minStart;
2943ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MinFilter) {
2944bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_NEAREST:
2945bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         for (i = minStart; i < minEnd; i++)
2946bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
2947bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                    texcoords[i], rgba[i]);
2948bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
2949bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_LINEAR:
2950bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         for (i = minStart; i < minEnd; i++)
2951bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
2952bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                   texcoords[i], rgba[i]);
2953bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
2954bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_NEAREST_MIPMAP_NEAREST:
29556e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_2d_array_nearest_mipmap_nearest(ctx, tObj, m,
29566e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                                texcoords + minStart,
29576e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                                lambda + minStart,
29586e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                                rgba + minStart);
2959bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
2960bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_LINEAR_MIPMAP_NEAREST:
2961bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_2d_array_linear_mipmap_nearest(ctx, tObj, m,
2962bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                               texcoords + minStart,
2963bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                               lambda + minStart,
2964bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                               rgba + minStart);
2965bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
2966bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_NEAREST_MIPMAP_LINEAR:
29676e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian         sample_2d_array_nearest_mipmap_linear(ctx, tObj, m,
29686e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                               texcoords + minStart,
29696e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                               lambda + minStart,
29706e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                               rgba + minStart);
2971bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
2972bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_LINEAR_MIPMAP_LINEAR:
2973bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_2d_array_linear_mipmap_linear(ctx, tObj, m,
2974bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                              texcoords + minStart,
2975bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                              lambda + minStart,
2976bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                              rgba + minStart);
2977bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
2978bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      default:
2979bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         _mesa_problem(ctx, "Bad min filter in sample_2d_array_texture");
2980bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         return;
2981bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
2982bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
2983bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
2984bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (magStart < magEnd) {
2985bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      /* do the magnified texels */
2986ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MagFilter) {
2987bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_NEAREST:
2988bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         for (i = magStart; i < magEnd; i++)
2989bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
2990bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                              texcoords[i], rgba[i]);
2991bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
2992bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_LINEAR:
2993bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         for (i = magStart; i < magEnd; i++)
2994bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
2995bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                   texcoords[i], rgba[i]);
2996bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
2997bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      default:
2998bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         _mesa_problem(ctx, "Bad mag filter in sample_2d_array_texture");
2999bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         return;
3000bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
3001bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3002bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3003bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3004bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3005bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3006bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3007bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick/**********************************************************************/
3008bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick/*                1D Texture Array Sampling Functions                 */
3009bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick/**********************************************************************/
3010bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
30116e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
3012bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
3013bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick */
3014bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
3015f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_array_nearest(struct gl_context *ctx,
3016bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                        const struct gl_texture_object *tObj,
3017bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                        const struct gl_texture_image *img,
3018bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                        const GLfloat texcoord[4],
3019de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                        GLfloat rgba[4])
3020bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
3021a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
3022bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint width = img->Width2;     /* without border, power of two */
3023bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint height = img->Height;
3024bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLint i;
3025bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLint array;
3026bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   (void) ctx;
3027bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3028ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   i = nearest_texel_location(tObj->Sampler.WrapS, img, width, texcoord[0]);
302958ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul   array = tex_array_slice(texcoord[1], height);
3030bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3031bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (i < 0 || i >= (GLint) img->Width ||
3032bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick       array < 0 || array >= (GLint) img->Height) {
3033bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      /* Need this test for GL_CLAMP_TO_BORDER mode */
3034b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, rgba);
3035bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3036bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   else {
3037a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i, array, 0, rgba);
3038bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3039bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3040bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3041bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
30426e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
3043bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
3044bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick */
3045bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
3046f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_array_linear(struct gl_context *ctx,
3047bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const struct gl_texture_object *tObj,
3048bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const struct gl_texture_image *img,
3049bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const GLfloat texcoord[4],
3050de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                       GLfloat rgba[4])
3051bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
3052a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
3053bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint width = img->Width2;
3054bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint height = img->Height;
3055bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLint i0, i1;
3056bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLint array;
3057bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLbitfield useBorderColor = 0x0;
3058bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLfloat a;
3059de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul   GLfloat t0[4], t1[4];
3060bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3061ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   linear_texel_locations(tObj->Sampler.WrapS, img, width, texcoord[0], &i0, &i1, &a);
306258ab56d32308e36f331294047e11c3e0b4b73cdeBrian Paul   array = tex_array_slice(texcoord[1], height);
3063bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3064bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (img->Border) {
3065bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      i0 += img->Border;
3066bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      i1 += img->Border;
3067bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3068bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   else {
3069bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      /* check if sampling texture border color */
3070bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
3071bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
3072bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3073bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3074bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (array < 0 || array >= height)   useBorderColor |= K0BIT;
3075bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3076bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   /* Fetch texels */
3077bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (useBorderColor & (I0BIT | K0BIT)) {
3078b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t0);
3079bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3080bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   else {
3081a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i0, array, 0, t0);
3082bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3083bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (useBorderColor & (I1BIT | K0BIT)) {
3084b48eb05f1f547e2b03a22056f3e82ee7b9065337Brian Paul      get_border_color(tObj, img, t1);
3085bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3086bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   else {
3087a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul      swImg->FetchTexelf(swImg, i1, array, 0, t1);
3088bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3089bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3090bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   /* bilinear interpolation of samples */
3091bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   lerp_rgba(rgba, a, t0, t1);
3092bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3093bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3094bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3095bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
3096f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_array_nearest_mipmap_nearest(struct gl_context *ctx,
3097bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                       const struct gl_texture_object *tObj,
3098bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                       GLuint n, const GLfloat texcoord[][4],
3099de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                       const GLfloat lambda[], GLfloat rgba[][4])
3100bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
3101bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
3102bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   for (i = 0; i < n; i++) {
3103bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLint level = nearest_mipmap_level(tObj, lambda[i]);
3104bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
3105bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                              rgba[i]);
3106bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3107bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3108bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3109bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3110bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
3111f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_array_linear_mipmap_nearest(struct gl_context *ctx,
3112bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                      const struct gl_texture_object *tObj,
3113bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                      GLuint n, const GLfloat texcoord[][4],
3114de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                      const GLfloat lambda[], GLfloat rgba[][4])
3115bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
3116bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
3117bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   ASSERT(lambda != NULL);
3118bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   for (i = 0; i < n; i++) {
3119bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLint level = nearest_mipmap_level(tObj, lambda[i]);
3120bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      sample_1d_array_linear(ctx, tObj, tObj->Image[0][level],
3121bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                             texcoord[i], rgba[i]);
3122bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3123bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3124bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3125bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3126bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
3127f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_array_nearest_mipmap_linear(struct gl_context *ctx,
3128bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                      const struct gl_texture_object *tObj,
3129bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                      GLuint n, const GLfloat texcoord[][4],
3130de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                      const GLfloat lambda[], GLfloat rgba[][4])
3131bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
3132bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
3133bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   ASSERT(lambda != NULL);
3134bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   for (i = 0; i < n; i++) {
3135bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLint level = linear_mipmap_level(tObj, lambda[i]);
3136bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (level >= tObj->_MaxLevel) {
3137bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
3138bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                 texcoord[i], rgba[i]);
3139bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
3140bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      else {
3141de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
3142bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         const GLfloat f = FRAC(lambda[i]);
3143bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
3144bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
3145bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         lerp_rgba(rgba[i], f, t0, t1);
3146bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
3147bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3148bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3149bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3150bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3151bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
3152f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_1d_array_linear_mipmap_linear(struct gl_context *ctx,
31536e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                     const struct gl_texture_object *tObj,
31546e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                                     GLuint n, const GLfloat texcoord[][4],
3155de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                                     const GLfloat lambda[], GLfloat rgba[][4])
3156bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
3157bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
3158bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   ASSERT(lambda != NULL);
3159bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   for (i = 0; i < n; i++) {
3160bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLint level = linear_mipmap_level(tObj, lambda[i]);
3161bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      if (level >= tObj->_MaxLevel) {
3162bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
3163bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                          texcoord[i], rgba[i]);
3164bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
3165bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      else {
3166de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul         GLfloat t0[4], t1[4];  /* texels */
3167bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         const GLfloat f = FRAC(lambda[i]);
3168bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
3169bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
3170bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         lerp_rgba(rgba[i], f, t0, t1);
3171bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
3172bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3173bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3174bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3175bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
31766e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 1D Array texture, nearest filtering for both min/magnification */
3177bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
3178f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_nearest_1d_array(struct gl_context *ctx,
31796e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                        const struct gl_texture_object *tObj, GLuint n,
31806e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian                        const GLfloat texcoords[][4], const GLfloat lambda[],
3181de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                        GLfloat rgba[][4])
3182bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
3183bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
3184bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
3185bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   (void) lambda;
31866e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   for (i = 0; i < n; i++) {
3187bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      sample_1d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
3188bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3189bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3190bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3191bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
31926e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 1D Array texture, linear filtering for both min/magnification */
3193bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
3194f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_linear_1d_array(struct gl_context *ctx,
3195bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const struct gl_texture_object *tObj, GLuint n,
3196bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const GLfloat texcoords[][4],
3197de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                       const GLfloat lambda[], GLfloat rgba[][4])
3198bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
3199bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
3200bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
3201bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   (void) lambda;
32026e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian   for (i = 0; i < n; i++) {
3203bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      sample_1d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
3204bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3205bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3206bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3207bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
32086e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/** Sample 1D Array texture, using lambda to choose between min/magnification */
3209bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanickstatic void
3210f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_lambda_1d_array(struct gl_context *ctx,
3211bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const struct gl_texture_object *tObj, GLuint n,
3212bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                       const GLfloat texcoords[][4], const GLfloat lambda[],
3213de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                       GLfloat rgba[][4])
3214bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick{
3215bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint minStart, minEnd;  /* texels with minification */
3216bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint magStart, magEnd;  /* texels with magnification */
3217bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   GLuint i;
3218bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3219bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   ASSERT(lambda != NULL);
3220bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   compute_min_mag_ranges(tObj, n, lambda,
3221bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                          &minStart, &minEnd, &magStart, &magEnd);
3222bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3223bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (minStart < minEnd) {
3224bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      /* do the minified texels */
3225bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      GLuint m = minEnd - minStart;
3226ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MinFilter) {
3227bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_NEAREST:
3228bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         for (i = minStart; i < minEnd; i++)
3229bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
3230bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                    texcoords[i], rgba[i]);
3231bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
3232bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_LINEAR:
3233bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         for (i = minStart; i < minEnd; i++)
3234bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
3235bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                   texcoords[i], rgba[i]);
3236bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
3237bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_NEAREST_MIPMAP_NEAREST:
3238bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
3239bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                                lambda + minStart, rgba + minStart);
3240bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
3241bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_LINEAR_MIPMAP_NEAREST:
3242bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_linear_mipmap_nearest(ctx, tObj, m,
3243bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                               texcoords + minStart,
3244bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                               lambda + minStart,
3245bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                               rgba + minStart);
3246bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
3247bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_NEAREST_MIPMAP_LINEAR:
3248bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
3249bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                               lambda + minStart, rgba + minStart);
3250bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
3251bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_LINEAR_MIPMAP_LINEAR:
3252bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         sample_1d_array_linear_mipmap_linear(ctx, tObj, m,
3253bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                              texcoords + minStart,
3254bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                              lambda + minStart,
3255bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                              rgba + minStart);
3256bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
3257bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      default:
3258bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         _mesa_problem(ctx, "Bad min filter in sample_1d_array_texture");
3259bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         return;
3260bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
3261bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3262bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3263bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   if (magStart < magEnd) {
3264bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      /* do the magnified texels */
3265ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      switch (tObj->Sampler.MagFilter) {
3266bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_NEAREST:
3267bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         for (i = magStart; i < magEnd; i++)
3268bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
3269bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                              texcoords[i], rgba[i]);
3270bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
3271bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_LINEAR:
3272bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         for (i = magStart; i < magEnd; i++)
3273bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
3274bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick                                   texcoords[i], rgba[i]);
3275bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         break;
3276bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      default:
3277bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         _mesa_problem(ctx, "Bad mag filter in sample_1d_array_texture");
3278bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         return;
3279bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      }
3280bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   }
3281bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick}
3282bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3283bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
32846e0f8b174dddeb743b4bdc0d831eb1121f62ff50Brian/**
3285a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul * Compare texcoord against depth sample.  Return 1.0 or the ambient value.
3286a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul */
32879520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat
3288a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paulshadow_compare(GLenum function, GLfloat coord, GLfloat depthSample,
3289a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul               GLfloat ambient)
3290a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul{
3291a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   switch (function) {
3292a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_LEQUAL:
3293a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return (coord <= depthSample) ? 1.0F : ambient;
3294a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_GEQUAL:
3295a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return (coord >= depthSample) ? 1.0F : ambient;
3296a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_LESS:
3297a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return (coord < depthSample) ? 1.0F : ambient;
3298a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_GREATER:
3299a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return (coord > depthSample) ? 1.0F : ambient;
3300a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_EQUAL:
3301a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return (coord == depthSample) ? 1.0F : ambient;
3302a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_NOTEQUAL:
3303a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return (coord != depthSample) ? 1.0F : ambient;
3304a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_ALWAYS:
3305a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return 1.0F;
3306a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_NEVER:
3307a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return ambient;
3308a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_NONE:
3309a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return depthSample;
3310a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   default:
3311a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      _mesa_problem(NULL, "Bad compare func in shadow_compare");
3312a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return ambient;
3313a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   }
3314a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul}
3315a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
3316a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
3317a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul/**
3318a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul * Compare texcoord against four depth samples.
3319a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul */
33209520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLfloat
3321a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paulshadow_compare4(GLenum function, GLfloat coord,
3322a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                GLfloat depth00, GLfloat depth01,
3323a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                GLfloat depth10, GLfloat depth11,
3324a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                GLfloat ambient, GLfloat wi, GLfloat wj)
3325a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul{
3326a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   const GLfloat d = (1.0F - (GLfloat) ambient) * 0.25F;
3327a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   GLfloat luminance = 1.0F;
3328a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
3329a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   switch (function) {
3330a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_LEQUAL:
33314a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord > depth00)  luminance -= d;
33324a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord > depth01)  luminance -= d;
33334a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord > depth10)  luminance -= d;
33344a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord > depth11)  luminance -= d;
3335a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return luminance;
3336d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor   case GL_GEQUAL:
33374a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord < depth00)  luminance -= d;
33384a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord < depth01)  luminance -= d;
33394a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord < depth10)  luminance -= d;
33404a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord < depth11)  luminance -= d;
3341a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return luminance;
3342d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor   case GL_LESS:
33434a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord >= depth00)  luminance -= d;
33444a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord >= depth01)  luminance -= d;
33454a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord >= depth10)  luminance -= d;
33464a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord >= depth11)  luminance -= d;
3347a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return luminance;
3348d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor   case GL_GREATER:
33494a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord <= depth00)  luminance -= d;
33504a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord <= depth01)  luminance -= d;
33514a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord <= depth10)  luminance -= d;
33524a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord <= depth11)  luminance -= d;
3353d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor      return luminance;
3354d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor   case GL_EQUAL:
33554a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord != depth00)  luminance -= d;
33564a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord != depth01)  luminance -= d;
33574a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord != depth10)  luminance -= d;
33584a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord != depth11)  luminance -= d;
3359a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return luminance;
3360d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor   case GL_NOTEQUAL:
33614a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord == depth00)  luminance -= d;
33624a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord == depth01)  luminance -= d;
33634a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord == depth10)  luminance -= d;
33644a802738b08b1dbddef6c59d0a1324f864b987b0Brian Paul      if (coord == depth11)  luminance -= d;
3365d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor      return luminance;
3366a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_ALWAYS:
3367d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor      return 1.0F;
3368a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_NEVER:
3369a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return ambient;
3370a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   case GL_NONE:
3371a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      /* ordinary bilinear filtering */
3372a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul      return lerp_2d(wi, wj, depth00, depth10, depth01, depth11);
3373a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   default:
3374d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor      _mesa_problem(NULL, "Bad compare func in sample_compare4");
3375d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor      return ambient;
3376a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul   }
3377a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul}
3378a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
3379a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
3380a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul/**
33812b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul * Choose the mipmap level to use when sampling from a depth texture.
33822b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul */
33832b5de09b3ea8754fb004d4f216bca29303f99490Brian Paulstatic int
33842b5de09b3ea8754fb004d4f216bca29303f99490Brian Paulchoose_depth_texture_level(const struct gl_texture_object *tObj, GLfloat lambda)
33852b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul{
33862b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul   GLint level;
33872b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul
3388ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   if (tObj->Sampler.MinFilter == GL_NEAREST || tObj->Sampler.MinFilter == GL_LINEAR) {
3389fb5e6f88fc426e53af26e98d1c336222a8952cc5Brian Paul      /* no mipmapping - use base level */
3390fb5e6f88fc426e53af26e98d1c336222a8952cc5Brian Paul      level = tObj->BaseLevel;
3391fb5e6f88fc426e53af26e98d1c336222a8952cc5Brian Paul   }
3392fb5e6f88fc426e53af26e98d1c336222a8952cc5Brian Paul   else {
3393fb5e6f88fc426e53af26e98d1c336222a8952cc5Brian Paul      /* choose mipmap level */
3394ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      lambda = CLAMP(lambda, tObj->Sampler.MinLod, tObj->Sampler.MaxLod);
3395fb5e6f88fc426e53af26e98d1c336222a8952cc5Brian Paul      level = (GLint) lambda;
3396fb5e6f88fc426e53af26e98d1c336222a8952cc5Brian Paul      level = CLAMP(level, tObj->BaseLevel, tObj->_MaxLevel);
3397fb5e6f88fc426e53af26e98d1c336222a8952cc5Brian Paul   }
33982b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul
33992b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul   return level;
34002b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul}
34012b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul
34022b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul
34032b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul/**
34042b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul * Sample a shadow/depth texture.  This function is incomplete.  It doesn't
34052b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul * check for minification vs. magnification, etc.
34062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
34072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
3408f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergsample_depth_texture( struct gl_context *ctx,
34092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                      const struct gl_texture_object *tObj, GLuint n,
34102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                      const GLfloat texcoords[][4], const GLfloat lambda[],
3411de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul                      GLfloat texel[][4] )
34122cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
34132b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul   const GLint level = choose_depth_texture_level(tObj, lambda[0]);
34142b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul   const struct gl_texture_image *img = tObj->Image[0][level];
3415a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul   const struct swrast_texture_image *swImg = swrast_texture_image_const(img);
34169ebe3b6d369c946e41b5f6a684a4ac4e3509b67cBrian Paul   const GLint width = img->Width;
34179ebe3b6d369c946e41b5f6a684a4ac4e3509b67cBrian Paul   const GLint height = img->Height;
3418bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLint depth = img->Depth;
3419bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick   const GLuint compare_coord = (tObj->Target == GL_TEXTURE_2D_ARRAY_EXT)
3420bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick       ? 3 : 2;
3421de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul   GLfloat ambient;
34222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLenum function;
3423de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul   GLfloat result;
34242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
34251f7c914ad0beea8a29c1a171c7cd1a12f2efe0faBrian Paul   ASSERT(img->_BaseFormat == GL_DEPTH_COMPONENT ||
34261f7c914ad0beea8a29c1a171c7cd1a12f2efe0faBrian Paul          img->_BaseFormat == GL_DEPTH_STENCIL_EXT);
3427b0a0ca8bd9edc13e495a39709cc28953dd3fbd9cBrian Paul
34282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   ASSERT(tObj->Target == GL_TEXTURE_1D ||
34292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul          tObj->Target == GL_TEXTURE_2D ||
3430bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick          tObj->Target == GL_TEXTURE_RECTANGLE_NV ||
3431bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick          tObj->Target == GL_TEXTURE_1D_ARRAY_EXT ||
3432bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick          tObj->Target == GL_TEXTURE_2D_ARRAY_EXT);
34332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
3434ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   ambient = tObj->Sampler.CompareFailValue;
34352cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
3436ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   /* XXXX if tObj->Sampler.MinFilter != tObj->Sampler.MagFilter, we're ignoring lambda */
34372cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
3438ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   function = (tObj->Sampler.CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) ?
3439ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      tObj->Sampler.CompareFunc : GL_NONE;
3440590f6fe05030cb274067a9e58af9d8306d97d0b9Brian Paul
3441ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul   if (tObj->Sampler.MagFilter == GL_NEAREST) {
34422cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLuint i;
34432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      for (i = 0; i < n; i++) {
3444d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor         GLfloat depthSample, depthRef;
3445bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         GLint col, row, slice;
3446fde15a2bae2f2ca552763705f12d53e4606feabfBrian
34472b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul         nearest_texcoord(tObj, level, texcoords[i], &col, &row, &slice);
3448bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3449bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         if (col >= 0 && row >= 0 && col < width && row < height &&
3450bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick             slice >= 0 && slice < depth) {
3451a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul            swImg->FetchTexelf(swImg, col, row, slice, &depthSample);
34529ebe3b6d369c946e41b5f6a684a4ac4e3509b67cBrian Paul         }
34539ebe3b6d369c946e41b5f6a684a4ac4e3509b67cBrian Paul         else {
3454ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            depthSample = tObj->Sampler.BorderColor.f[0];
34559ebe3b6d369c946e41b5f6a684a4ac4e3509b67cBrian Paul         }
34562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
3457d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor         depthRef = CLAMP(texcoords[i][compare_coord], 0.0F, 1.0F);
3458d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor
3459d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor         result = shadow_compare(function, depthRef, depthSample, ambient);
34602cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
3461ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         switch (tObj->Sampler.DepthMode) {
34622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         case GL_LUMINANCE:
3463de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul            ASSIGN_4V(texel[i], result, result, result, 1.0F);
34642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            break;
34652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         case GL_INTENSITY:
3466de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul            ASSIGN_4V(texel[i], result, result, result, result);
34672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            break;
34682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         case GL_ALPHA:
3469de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul            ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
34702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            break;
3471cd5dea640144b45ba2e88c2451f1f01ee08c1c4aIan Romanick         case GL_RED:
3472cd5dea640144b45ba2e88c2451f1f01ee08c1c4aIan Romanick            ASSIGN_4V(texel[i], result, 0.0F, 0.0F, 1.0F);
3473cd5dea640144b45ba2e88c2451f1f01ee08c1c4aIan Romanick            break;
34742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         default:
34752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            _mesa_problem(ctx, "Bad depth texture mode");
34762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
34772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
34782cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
34792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
34802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      GLuint i;
3481ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      ASSERT(tObj->Sampler.MagFilter == GL_LINEAR);
34822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      for (i = 0; i < n; i++) {
3483d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor         GLfloat depth00, depth01, depth10, depth11, depthRef;
34842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         GLint i0, i1, j0, j1;
3485bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         GLint slice;
3486a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul         GLfloat wi, wj;
34872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         GLuint useBorderTexel;
34882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
34892b5de09b3ea8754fb004d4f216bca29303f99490Brian Paul         linear_texcoord(tObj, level, texcoords[i], &i0, &i1, &j0, &j1, &slice,
3490a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                         &wi, &wj);
34912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
34922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         useBorderTexel = 0;
349306f606ce5761e673fca3f6b1f7dd40dace8a9906Brian Paul         if (img->Border) {
349406f606ce5761e673fca3f6b1f7dd40dace8a9906Brian Paul            i0 += img->Border;
349506f606ce5761e673fca3f6b1f7dd40dace8a9906Brian Paul            i1 += img->Border;
3496bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) {
3497bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               j0 += img->Border;
3498bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               j1 += img->Border;
3499bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            }
35002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
35012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
35022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            if (i0 < 0 || i0 >= (GLint) width)   useBorderTexel |= I0BIT;
35032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            if (i1 < 0 || i1 >= (GLint) width)   useBorderTexel |= I1BIT;
35042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            if (j0 < 0 || j0 >= (GLint) height)  useBorderTexel |= J0BIT;
35052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            if (j1 < 0 || j1 >= (GLint) height)  useBorderTexel |= J1BIT;
35062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
35072cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
3508bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         if (slice < 0 || slice >= (GLint) depth) {
3509ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            depth00 = tObj->Sampler.BorderColor.f[0];
3510ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            depth01 = tObj->Sampler.BorderColor.f[0];
3511ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            depth10 = tObj->Sampler.BorderColor.f[0];
3512ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            depth11 = tObj->Sampler.BorderColor.f[0];
35132cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
35142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
3515bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            /* get four depth samples from the texture */
3516bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            if (useBorderTexel & (I0BIT | J0BIT)) {
3517ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul               depth00 = tObj->Sampler.BorderColor.f[0];
3518bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            }
3519bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            else {
3520a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul               swImg->FetchTexelf(swImg, i0, j0, slice, &depth00);
3521bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            }
3522bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            if (useBorderTexel & (I1BIT | J0BIT)) {
3523ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul               depth10 = tObj->Sampler.BorderColor.f[0];
3524bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            }
3525bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            else {
3526a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul               swImg->FetchTexelf(swImg, i1, j0, slice, &depth10);
3527bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            }
3528bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick
3529bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) {
3530bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               if (useBorderTexel & (I0BIT | J1BIT)) {
3531ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul                  depth01 = tObj->Sampler.BorderColor.f[0];
3532bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               }
3533bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               else {
3534a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul                  swImg->FetchTexelf(swImg, i0, j1, slice, &depth01);
3535bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               }
3536bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               if (useBorderTexel & (I1BIT | J1BIT)) {
3537ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul                  depth11 = tObj->Sampler.BorderColor.f[0];
3538bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               }
3539bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               else {
3540a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul                  swImg->FetchTexelf(swImg, i1, j1, slice, &depth11);
3541bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               }
3542bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            }
3543bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            else {
3544bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               depth01 = depth00;
3545bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick               depth11 = depth10;
3546bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            }
35472cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
35482cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
3549d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor         depthRef = CLAMP(texcoords[i][compare_coord], 0.0F, 1.0F);
3550d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor
3551d9f584e663c7447e638acca2c164b16626a5271aPhilip Taylor         result = shadow_compare4(function, depthRef,
3552a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                                  depth00, depth01, depth10, depth11,
3553a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul                                  ambient, wi, wj);
35542cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
3555ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         switch (tObj->Sampler.DepthMode) {
35562cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         case GL_LUMINANCE:
3557a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul            ASSIGN_4V(texel[i], result, result, result, 1.0F);
35582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            break;
35592cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         case GL_INTENSITY:
3560a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul            ASSIGN_4V(texel[i], result, result, result, result);
35612cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            break;
35622cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         case GL_ALPHA:
3563a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul            ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
35642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            break;
35652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         default:
35662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            _mesa_problem(ctx, "Bad depth texture mode");
35672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
3568a35ad020f9449849f7616788aa6bd9e439d6c518Brian Paul
35692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }  /* for */
35702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }  /* if filter */
35712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
35722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
35732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
35742cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
35752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * We use this function when a texture object is in an "incomplete" state.
35762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * When a fragment program attempts to sample an incomplete texture we
35772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * return black (see issue 23 in GL_ARB_fragment_program spec).
35785bfb9356d6df4c8b1e177ebda01631d99355ba25Brian Paul * Note: fragment programs don't observe the texture enable/disable flags.
35792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
35802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paulstatic void
3581f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergnull_sample_func( struct gl_context *ctx,
35822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul		  const struct gl_texture_object *tObj, GLuint n,
35832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul		  const GLfloat texcoords[][4], const GLfloat lambda[],
3584de2afd8688ceb45013d15be7c6e0995199b80e5aBrian Paul		  GLfloat rgba[][4])
35852cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
35862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   GLuint i;
35872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) ctx;
35882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) tObj;
35892cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) texcoords;
35902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   (void) lambda;
35912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   for (i = 0; i < n; i++) {
35922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      rgba[i][RCOMP] = 0;
35932cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      rgba[i][GCOMP] = 0;
35942cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      rgba[i][BCOMP] = 0;
35953fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul      rgba[i][ACOMP] = 1.0;
35962cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
35972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
35982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
35992cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
36002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul/**
36012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul * Choose the texture sampling function for the given texture object.
36022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul */
36032cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paultexture_sample_func
3604f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_choose_texture_sample_func( struct gl_context *ctx,
36052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul				    const struct gl_texture_object *t )
36062cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul{
3607227315278dea9095cee6e508d03b28720b2e7880Brian   if (!t || !t->_Complete) {
36082cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      return &null_sample_func;
36092cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
36102cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   else {
3611ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul      const GLboolean needLambda =
3612ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         (GLboolean) (t->Sampler.MinFilter != t->Sampler.MagFilter);
36131f7c914ad0beea8a29c1a171c7cd1a12f2efe0faBrian Paul      const GLenum format = t->Image[0][t->BaseLevel]->_BaseFormat;
36142cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul
36152cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      switch (t->Target) {
36162cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_TEXTURE_1D:
3617b0a0ca8bd9edc13e495a39709cc28953dd3fbd9cBrian Paul         if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
36182cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_depth_texture;
36192cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36202cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else if (needLambda) {
36212cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_lambda_1d;
36222cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
3623ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         else if (t->Sampler.MinFilter == GL_LINEAR) {
36242cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_linear_1d;
36252cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36262cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
3627ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
36282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_nearest_1d;
36292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_TEXTURE_2D:
3631b0a0ca8bd9edc13e495a39709cc28953dd3fbd9cBrian Paul         if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
36322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_depth_texture;
36332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else if (needLambda) {
36358a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            /* Anisotropic filtering extension. Activated only if mipmaps are used */
36368a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            if (t->Sampler.MaxAnisotropy > 1.0 &&
36378a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger                t->Sampler.MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
36388a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger               return &sample_lambda_2d_aniso;
36398a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            }
36402cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_lambda_2d;
36412cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
3642ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         else if (t->Sampler.MinFilter == GL_LINEAR) {
36432cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_linear_2d;
36442cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36452cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
364606f606ce5761e673fca3f6b1f7dd40dace8a9906Brian Paul            /* check for a few optimized cases */
364706f606ce5761e673fca3f6b1f7dd40dace8a9906Brian Paul            const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
3648eaf376ba354db11f7729452060570b48a029c9a0Brian Paul            const struct swrast_texture_image *swImg =
3649eaf376ba354db11f7729452060570b48a029c9a0Brian Paul               swrast_texture_image_const(img);
3650eaf376ba354db11f7729452060570b48a029c9a0Brian Paul
3651ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
3652ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            if (t->Sampler.WrapS == GL_REPEAT &&
3653ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul                t->Sampler.WrapT == GL_REPEAT &&
3654eaf376ba354db11f7729452060570b48a029c9a0Brian Paul                swImg->_IsPowerOfTwo &&
365506f606ce5761e673fca3f6b1f7dd40dace8a9906Brian Paul                img->Border == 0 &&
36563fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul                img->TexFormat == MESA_FORMAT_RGB888) {
36572cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul               return &opt_sample_rgb_2d;
36582cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            }
3659ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            else if (t->Sampler.WrapS == GL_REPEAT &&
3660ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul                     t->Sampler.WrapT == GL_REPEAT &&
3661eaf376ba354db11f7729452060570b48a029c9a0Brian Paul                     swImg->_IsPowerOfTwo &&
366206f606ce5761e673fca3f6b1f7dd40dace8a9906Brian Paul                     img->Border == 0 &&
36633fa7dbf368bb060220e9f78e666b00d6827166a6Brian Paul                     img->TexFormat == MESA_FORMAT_RGBA8888) {
36642cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul               return &opt_sample_rgba_2d;
36652cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            }
36662cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            else {
36672cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul               return &sample_nearest_2d;
36682cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            }
36692cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36702cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_TEXTURE_3D:
36712cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         if (needLambda) {
36722cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_lambda_3d;
36732cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
3674ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         else if (t->Sampler.MinFilter == GL_LINEAR) {
36752cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_linear_3d;
36762cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36772cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
3678ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
36792cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_nearest_3d;
36802cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36812cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_TEXTURE_CUBE_MAP:
36822cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         if (needLambda) {
36832cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_lambda_cube;
36842cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
3685ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         else if (t->Sampler.MinFilter == GL_LINEAR) {
36862cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_linear_cube;
36872cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36882cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
3689ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
36902cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_nearest_cube;
36912cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
36922cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      case GL_TEXTURE_RECTANGLE_NV:
3693fde15a2bae2f2ca552763705f12d53e4606feabfBrian         if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
3694fde15a2bae2f2ca552763705f12d53e4606feabfBrian            return &sample_depth_texture;
3695fde15a2bae2f2ca552763705f12d53e4606feabfBrian         }
3696fde15a2bae2f2ca552763705f12d53e4606feabfBrian         else if (needLambda) {
36972cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_lambda_rect;
36982cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
3699ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         else if (t->Sampler.MinFilter == GL_LINEAR) {
37002cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_linear_rect;
37012cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
37022cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         else {
3703ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
37042cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul            return &sample_nearest_rect;
37052cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         }
3706bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_TEXTURE_1D_ARRAY_EXT:
3707bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         if (needLambda) {
3708bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            return &sample_lambda_1d_array;
3709bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         }
3710ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         else if (t->Sampler.MinFilter == GL_LINEAR) {
3711bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            return &sample_linear_1d_array;
3712bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         }
3713bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         else {
3714ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
3715bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            return &sample_nearest_1d_array;
3716bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         }
3717bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick      case GL_TEXTURE_2D_ARRAY_EXT:
3718bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         if (needLambda) {
3719bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            return &sample_lambda_2d_array;
3720bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         }
3721ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul         else if (t->Sampler.MinFilter == GL_LINEAR) {
3722bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            return &sample_linear_2d_array;
3723bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         }
3724bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         else {
3725ecfaab88b2577bd0395bc05d75a036126806a9c4Brian Paul            ASSERT(t->Sampler.MinFilter == GL_NEAREST);
3726bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick            return &sample_nearest_2d_array;
3727bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick         }
37282cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      default:
37292cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         _mesa_problem(ctx,
37302cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul                       "invalid target in _swrast_choose_texture_sample_func");
37312cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul         return &null_sample_func;
37322cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul      }
37332cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul   }
37342cd8791cad11ea3961533c0cd8f9c1bbf50ef6ccBrian Paul}
3735