i915_texstate.c revision c9e4aa2b303f9056564724ece0e2733a54d9f569
1/**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "glheader.h"
29#include "macros.h"
30#include "mtypes.h"
31#include "simple_list.h"
32#include "enums.h"
33#include "texformat.h"
34#include "texstore.h"
35
36#include "mm.h"
37
38#include "intel_screen.h"
39#include "intel_ioctl.h"
40#include "intel_tex.h"
41
42#include "i915_context.h"
43#include "i915_reg.h"
44
45static GLint initial_offsets[6][2] = { {0,0},
46				       {0,2},
47				       {1,0},
48				       {1,2},
49				       {1,1},
50				       {1,3} };
51
52
53static GLint step_offsets[6][2] = { {0,2},
54				    {0,2},
55				    {-1,2},
56				    {-1,2},
57				    {-1,1},
58				    {-1,1} };
59
60
61#define I915_TEX_UNIT_ENABLED(unit)		(1<<unit)
62
63static GLuint i915_compressed_alignment(GLint internal_fmt)
64{
65    GLuint alignment = 4;
66
67    switch (internal_fmt) {
68    case GL_COMPRESSED_RGB_FXT1_3DFX:
69    case GL_COMPRESSED_RGBA_FXT1_3DFX:
70        alignment = 8;
71        break;
72
73    default:
74        break;
75    }
76
77    return alignment;
78}
79
80static int align(int value, GLuint alignment)
81{
82    return (value + alignment - 1) & ~(alignment - 1);
83}
84
85static GLuint minify(GLuint d)
86{
87    return MAX2(1, d >> 1);
88}
89
90static void i915LayoutTextureImages( i915ContextPtr i915,
91				     struct gl_texture_object *tObj )
92{
93   const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
94   i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
95   GLint firstLevel, lastLevel, numLevels;
96   GLint i, total_height, pitch;
97
98   /* Compute which mipmap levels we really want to send to the hardware.
99    */
100   driCalculateTextureFirstLastLevel( (driTextureObject *) t );
101
102   /* Figure out the amount of memory required to hold all the mipmap
103    * levels.  Choose the smallest pitch to accomodate the largest
104    * mipmap:
105    */
106   firstLevel = t->intel.base.firstLevel;
107   lastLevel = t->intel.base.lastLevel;
108   numLevels = lastLevel - firstLevel + 1;
109
110
111
112   /* All images must be loaded at this pitch.  Count the number of
113    * lines required:
114    */
115   switch (tObj->Target) {
116   case GL_TEXTURE_CUBE_MAP: {
117      const GLuint dim = tObj->Image[0][firstLevel]->Width;
118      GLuint face;
119
120      pitch = dim * t->intel.texelBytes;
121      pitch *= 2;		/* double pitch for cube layouts */
122      pitch = (pitch + 3) & ~3;
123
124      total_height = dim * 4;
125
126      for ( face = 0 ; face < 6 ; face++) {
127	 GLuint x = initial_offsets[face][0] * dim;
128	 GLuint y = initial_offsets[face][1] * dim;
129	 GLuint d = dim;
130
131	 t->intel.base.dirty_images[face] = ~0;
132
133	 assert(tObj->Image[face][firstLevel]->Width == dim);
134	 assert(tObj->Image[face][firstLevel]->Height == dim);
135
136	 for (i = 0; i < numLevels; i++) {
137	    t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
138	    if (!t->intel.image[face][i].image) {
139	       fprintf(stderr, "no image %d %d\n", face, i);
140	       break;		/* can't happen */
141	    }
142
143	    t->intel.image[face][i].offset =
144	       y * pitch + x * t->intel.texelBytes;
145	    t->intel.image[face][i].internalFormat = baseImage->_BaseFormat;
146
147	    d >>= 1;
148	    x += step_offsets[face][0] * d;
149	    y += step_offsets[face][1] * d;
150	 }
151      }
152      break;
153   }
154   case GL_TEXTURE_3D: {
155      GLuint virtual_height;
156      GLuint tmp_numLevels = numLevels;
157      pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
158      pitch = (pitch + 3) & ~3;
159      t->intel.base.dirty_images[0] = ~0;
160
161      /* Calculate the size of a single slice.  Hardware demands a
162       * minimum of 8 mipmaps, some of which might ultimately not be
163       * used:
164       */
165      if (tmp_numLevels < 9)
166	 tmp_numLevels = 9;
167
168      virtual_height = tObj->Image[0][firstLevel]->Height;
169
170      for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) {
171	 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
172	 if (t->intel.image[0][i].image) {
173	    t->intel.image[0][i].offset = total_height * pitch;
174	    t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
175	 }
176
177	 total_height += MAX2(2, virtual_height);
178	 virtual_height >>= 1;
179      }
180
181      t->intel.depth_pitch = total_height * pitch;
182
183      /* Multiply slice size by texture depth for total size.  It's
184       * remarkable how wasteful of memory all the i8x0 texture
185       * layouts are.
186       */
187      total_height *= t->intel.image[0][0].image->Depth;
188      break;
189   }
190   default:
191      if (baseImage->IsCompressed) {
192          GLuint alignment = i915_compressed_alignment(baseImage->InternalFormat);
193
194          pitch = align(tObj->Image[0][firstLevel]->Width, alignment) * t->intel.texelBytes;
195      } else {
196          pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
197          pitch = (pitch + 3) & ~3;
198      }
199
200      t->intel.base.dirty_images[0] = ~0;
201
202      for ( total_height = i = 0 ; i < numLevels ; i++ ) {
203	 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
204	 if (!t->intel.image[0][i].image)
205	    break;
206
207	 t->intel.image[0][i].offset = total_height * pitch;
208	 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
209	 if (t->intel.image[0][i].image->IsCompressed) {
210	    total_height += (t->intel.image[0][i].image->Height + 3) / 4;
211	 }
212	 else
213	   total_height += MAX2(2, t->intel.image[0][i].image->Height);
214      }
215      break;
216   }
217
218   t->intel.Pitch = pitch;
219   t->intel.base.totalSize = total_height*pitch;
220   t->intel.max_level = numLevels-1;
221}
222
223
224static void i945LayoutTextureImages( i915ContextPtr i915,
225				    struct gl_texture_object *tObj )
226{
227   const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
228   i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
229   GLint firstLevel, lastLevel, numLevels;
230   GLint i, total_height, pitch, sz, max_offset = 0, offset;
231
232
233   /* Compute which mipmap levels we really want to send to the hardware.
234    */
235   driCalculateTextureFirstLastLevel( (driTextureObject *) t );
236
237   /* Figure out the amount of memory required to hold all the mipmap
238    * levels.  Choose the smallest pitch to accomodate the largest
239    * mipmap:
240    */
241   firstLevel = t->intel.base.firstLevel;
242   lastLevel = t->intel.base.lastLevel;
243   numLevels = lastLevel - firstLevel + 1;
244
245
246
247   /* All images must be loaded at this pitch.  Count the number of
248    * lines required:
249    */
250   switch (tObj->Target) {
251   case GL_TEXTURE_CUBE_MAP: {
252      const GLuint dim = tObj->Image[0][firstLevel]->Width;
253      GLuint face;
254
255      /* Depending on the size of the largest images, pitch can be
256       * determined either by the old-style packing of cubemap faces,
257       * or the final row of 4x4, 2x2 and 1x1 faces below this.
258       */
259      if (dim > 32) {
260	 pitch = dim * t->intel.texelBytes;
261	 pitch *= 2;		/* double pitch for cube layouts */
262	 pitch = (pitch + 3) & ~3;
263      }
264      else {
265	 pitch = 14 * 8 * t->intel.texelBytes; /* determined by row of
266						* little maps at
267						* bottom */
268      }
269
270      total_height = dim * 4 + 4;
271
272      for ( face = 0 ; face < 6 ; face++) {
273	 GLuint x = initial_offsets[face][0] * dim;
274	 GLuint y = initial_offsets[face][1] * dim;
275	 GLuint d = dim;
276
277	 if (dim == 4 && face >= 4) {
278	    y = total_height - 4;
279	    x = (face - 4) * 8;
280	 }
281	 else if (dim < 4) {
282	    y = total_height - 4;
283	    x = face * 8;
284	 }
285
286	 t->intel.base.dirty_images[face] = ~0;
287
288	 assert(tObj->Image[face][firstLevel]->Width == dim);
289	 assert(tObj->Image[face][firstLevel]->Height == dim);
290
291	 for (i = 0; i < numLevels; i++) {
292
293
294	    t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
295	    assert(t->intel.image[face][i].image);
296
297	    t->intel.image[face][i].offset =
298	       y * pitch + x * t->intel.texelBytes;
299	    t->intel.image[face][i].internalFormat = baseImage->_BaseFormat;
300
301	    d >>= 1;
302
303	    switch (d) {
304	    case 4:
305	       switch (face) {
306	       case FACE_POS_X:
307	       case FACE_NEG_X:
308		  x += step_offsets[face][0] * d;
309		  y += step_offsets[face][1] * d;
310		  break;
311	       case FACE_POS_Y:
312	       case FACE_NEG_Y:
313		  y += 12;
314		  x -= 8;
315		  break;
316	       case FACE_POS_Z:
317	       case FACE_NEG_Z:
318		  y = total_height - 4;
319		  x = (face - 4) * 8;
320		  break;
321	       }
322
323	    case 2:
324	       y = total_height - 4;
325	       x = 16 + face * 8;
326	       break;
327
328	    case 1:
329	       x += 48;
330	       break;
331
332	    default:
333	       x += step_offsets[face][0] * d;
334	       y += step_offsets[face][1] * d;
335	       break;
336	    }
337	 }
338      }
339      max_offset = total_height * pitch;
340      break;
341   }
342   case GL_TEXTURE_3D: {
343      GLuint depth_packing = 0, depth_pack_pitch;
344      GLuint tmp_numLevels = numLevels;
345      pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
346      pitch = (pitch + 3) & ~3;
347      depth_pack_pitch = pitch;
348
349      t->intel.base.dirty_images[0] = ~0;
350
351
352      for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) {
353	 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
354	 if (!t->intel.image[0][i].image)
355	    break;
356
357
358	 t->intel.image[0][i].offset = total_height * pitch;
359	 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
360
361
362
363	 total_height += MAX2(2, t->intel.image[0][i].image->Height) *
364	    MAX2((t->intel.image[0][i].image->Depth >> depth_packing), 1);
365
366	 /* When alignment dominates, can't increase depth packing?
367	  * Or does pitch grow???  What are the alignment constraints,
368	  * anyway?
369	  */
370	 if (depth_pack_pitch > 4) {
371	    depth_packing++;
372	    depth_pack_pitch <<= 2;
373	 }
374      }
375
376      max_offset = total_height * pitch;
377      break;
378   }
379   default:
380      if (baseImage->IsCompressed) {
381          GLuint alignment = i915_compressed_alignment(baseImage->InternalFormat);
382
383          pitch = align(tObj->Image[0][firstLevel]->Width, alignment);
384          if (numLevels > 2) {
385              GLint width0 = align(minify(tObj->Image[0][firstLevel]->Width), alignment) +
386                  + align(minify(minify(tObj->Image[0][firstLevel]->Width)), alignment);
387
388              if (width0 > pitch)
389                  pitch = width0;
390          }
391          pitch = pitch * t->intel.texelBytes;
392      } else {
393          pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
394          pitch = (pitch + 3) & ~3;
395      }
396
397      t->intel.base.dirty_images[0] = ~0;
398      max_offset = 0;
399
400      for ( offset = i = 0 ; i < numLevels ; i++ ) {
401	 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
402	 if (!t->intel.image[0][i].image)
403	    break;
404
405	 t->intel.image[0][i].offset = offset;
406	 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
407
408	 if (t->intel.image[0][i].image->IsCompressed)
409	    sz = MAX2(1, t->intel.image[0][i].image->Height/4) * pitch;
410	 else
411	    sz = MAX2(2, t->intel.image[0][i].image->Height) * pitch;
412
413	 /* Because the images are packed better, the final offset
414	  * might not be the maximal one:
415	  */
416	 max_offset = MAX2(max_offset, offset + sz);
417
418	 /* LPT change: step right after second mipmap.
419	  */
420	 if (i == 1)
421	    offset += pitch / 2;
422	 else
423	    offset += sz;
424
425      }
426      break;
427   }
428
429   t->intel.Pitch = pitch;
430   t->intel.base.totalSize = max_offset;
431   t->intel.max_level = numLevels-1;
432}
433
434
435
436
437static void i915SetTexImages( i915ContextPtr i915,
438			     struct gl_texture_object *tObj )
439{
440   GLuint textureFormat;
441   i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
442   const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
443   GLint ss2 = 0;
444
445   switch( baseImage->TexFormat->MesaFormat ) {
446   case MESA_FORMAT_L8:
447      t->intel.texelBytes = 1;
448      textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
449      break;
450
451   case MESA_FORMAT_I8:
452      t->intel.texelBytes = 1;
453      textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
454      break;
455
456   case MESA_FORMAT_A8:
457      t->intel.texelBytes = 1;
458      textureFormat = MAPSURF_8BIT | MT_8BIT_A8;
459      break;
460
461   case MESA_FORMAT_AL88:
462      t->intel.texelBytes = 2;
463      textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
464      break;
465
466   case MESA_FORMAT_RGB565:
467      t->intel.texelBytes = 2;
468      textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
469      break;
470
471   case MESA_FORMAT_ARGB1555:
472      t->intel.texelBytes = 2;
473      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
474      break;
475
476   case MESA_FORMAT_ARGB4444:
477      t->intel.texelBytes = 2;
478      textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
479      break;
480
481   case MESA_FORMAT_ARGB8888:
482      t->intel.texelBytes = 4;
483      textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
484      break;
485
486   case MESA_FORMAT_YCBCR_REV:
487      t->intel.texelBytes = 2;
488      textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL);
489      ss2 |= SS2_COLORSPACE_CONVERSION;
490      break;
491
492   case MESA_FORMAT_YCBCR:
493      t->intel.texelBytes = 2;
494      textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY);
495      ss2 |= SS2_COLORSPACE_CONVERSION;
496      break;
497
498   case MESA_FORMAT_RGB_FXT1:
499   case MESA_FORMAT_RGBA_FXT1:
500     t->intel.texelBytes = 2;
501     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
502     break;
503
504   case MESA_FORMAT_Z16:
505      t->intel.texelBytes = 2;
506      textureFormat = (MAPSURF_16BIT | MT_16BIT_L16);
507      break;
508
509   case MESA_FORMAT_RGBA_DXT1:
510   case MESA_FORMAT_RGB_DXT1:
511     /*
512      * DXTn pitches are Width/4 * blocksize in bytes
513      * for DXT1: blocksize=8 so Width/4*8 = Width * 2
514      * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
515      */
516     t->intel.texelBytes = 2;
517     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
518     break;
519
520   case MESA_FORMAT_RGBA_DXT3:
521     t->intel.texelBytes = 4;
522     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
523     break;
524
525   case MESA_FORMAT_RGBA_DXT5:
526     t->intel.texelBytes = 4;
527     textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
528     break;
529
530#if 0
531   case MESA_FORMAT_Z24_S8:
532      t->intel.texelBytes = 4;
533      textureFormat = (MAPSURF_32BIT | MT_32BIT_xL824);
534      break;
535#endif
536
537   default:
538      fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__,
539	      baseImage->TexFormat->MesaFormat);
540      abort();
541   }
542
543   switch (i915->intel.intelScreen->deviceID) {
544   case PCI_CHIP_I945_G:
545   case PCI_CHIP_I945_GM:
546   case PCI_CHIP_I945_GME:
547   case PCI_CHIP_G33_G:
548   case PCI_CHIP_Q33_G:
549   case PCI_CHIP_Q35_G:
550       i945LayoutTextureImages( i915, tObj );
551       break;
552   default:
553       i915LayoutTextureImages( i915, tObj );
554       break;
555   }
556
557   t->Setup[I915_TEXREG_MS3] =
558      (((tObj->Image[0][t->intel.base.firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) |
559       ((tObj->Image[0][t->intel.base.firstLevel]->Width - 1) << MS3_WIDTH_SHIFT) |
560       textureFormat |
561       MS3_USE_FENCE_REGS);
562
563   t->Setup[I915_TEXREG_MS4] =
564      ((((t->intel.Pitch / 4) - 1) << MS4_PITCH_SHIFT) |
565       MS4_CUBE_FACE_ENA_MASK |
566       (((t->intel.max_level * 4)) << MS4_MAX_LOD_SHIFT) |
567       ((tObj->Image[0][t->intel.base.firstLevel]->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
568
569   t->Setup[I915_TEXREG_SS2] &= ~(SS2_COLORSPACE_CONVERSION);
570   t->Setup[I915_TEXREG_SS2] |= ss2;
571
572   t->intel.dirty = I915_UPLOAD_TEX_ALL;
573
574}
575
576
577/* The i915 (and related graphics cores) do not support GL_CLAMP.  The
578 * Intel drivers for "other operating systems" implement GL_CLAMP as
579 * GL_CLAMP_TO_EDGE, so the same is done here.
580 */
581static GLuint translate_wrap_mode( GLenum wrap )
582{
583   switch( wrap ) {
584   case GL_REPEAT: return TEXCOORDMODE_WRAP;
585   case GL_CLAMP:  return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
586   case GL_CLAMP_TO_EDGE: return TEXCOORDMODE_CLAMP_EDGE;
587   case GL_CLAMP_TO_BORDER: return TEXCOORDMODE_CLAMP_BORDER;
588   case GL_MIRRORED_REPEAT: return TEXCOORDMODE_MIRROR;
589   default: return TEXCOORDMODE_WRAP;
590   }
591}
592
593
594/**
595 */
596static void i915ImportTexObjState( struct gl_texture_object *texObj )
597{
598   i915TextureObjectPtr t = (i915TextureObjectPtr)texObj->DriverData;
599   int minFilt = 0, mipFilt = 0, magFilt = 0, shadow = 0;
600
601   if(INTEL_DEBUG&DEBUG_DRI)
602      fprintf(stderr, "%s\n", __FUNCTION__);
603
604   switch (texObj->MinFilter) {
605   case GL_NEAREST:
606      minFilt = FILTER_NEAREST;
607      mipFilt = MIPFILTER_NONE;
608      break;
609   case GL_LINEAR:
610      minFilt = FILTER_LINEAR;
611      mipFilt = MIPFILTER_NONE;
612      break;
613   case GL_NEAREST_MIPMAP_NEAREST:
614      minFilt = FILTER_NEAREST;
615      mipFilt = MIPFILTER_NEAREST;
616      break;
617   case GL_LINEAR_MIPMAP_NEAREST:
618      minFilt = FILTER_LINEAR;
619      mipFilt = MIPFILTER_NEAREST;
620      break;
621   case GL_NEAREST_MIPMAP_LINEAR:
622      minFilt = FILTER_NEAREST;
623      mipFilt = MIPFILTER_LINEAR;
624      break;
625   case GL_LINEAR_MIPMAP_LINEAR:
626      minFilt = FILTER_LINEAR;
627      mipFilt = MIPFILTER_LINEAR;
628      break;
629   default:
630      break;
631   }
632
633   if ( texObj->MaxAnisotropy > 1.0 ) {
634      minFilt = FILTER_ANISOTROPIC;
635      magFilt = FILTER_ANISOTROPIC;
636   }
637   else {
638      switch (texObj->MagFilter) {
639      case GL_NEAREST:
640	 magFilt = FILTER_NEAREST;
641	 break;
642      case GL_LINEAR:
643	 magFilt = FILTER_LINEAR;
644	 break;
645      default:
646	 break;
647      }
648   }
649
650   if (texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
651       texObj->Target != GL_TEXTURE_3D) {
652
653      shadow = SS2_SHADOW_ENABLE;
654      shadow |= intel_translate_compare_func( texObj->CompareFunc );
655
656      minFilt = FILTER_4X4_FLAT;
657      magFilt = FILTER_4X4_FLAT;
658   }
659
660
661   t->Setup[I915_TEXREG_SS2] &= ~(SS2_MIN_FILTER_MASK |
662				 SS2_MIP_FILTER_MASK |
663				 SS2_MAG_FILTER_MASK |
664				 SS2_SHADOW_ENABLE |
665				 SS2_SHADOW_FUNC_MASK);
666   t->Setup[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
667				(mipFilt << SS2_MIP_FILTER_SHIFT) |
668				(magFilt << SS2_MAG_FILTER_SHIFT) |
669				shadow);
670
671   {
672      GLuint ss3 = t->Setup[I915_TEXREG_SS3] & ~(SS3_TCX_ADDR_MODE_MASK |
673						SS3_TCY_ADDR_MODE_MASK |
674						SS3_TCZ_ADDR_MODE_MASK);
675      GLenum ws = texObj->WrapS;
676      GLenum wt = texObj->WrapT;
677      GLenum wr = texObj->WrapR;
678
679      t->refs_border_color = 0;
680
681      if (texObj->Target == GL_TEXTURE_3D &&
682	  (texObj->MinFilter != GL_NEAREST ||
683	   texObj->MagFilter != GL_NEAREST)) {
684
685	 /* Try to mimic GL_CLAMP functionality a little better -
686	  * switch to CLAMP_TO_BORDER whenever a non-NEAREST filter is
687	  * in use.  Only do this for 3D textures at the moment --
688	  * doing it universally would fix the conform texbc.c
689	  * failure, though.
690	  */
691	 if (ws == GL_CLAMP) ws = GL_CLAMP_TO_BORDER;
692	 if (wt == GL_CLAMP) wt = GL_CLAMP_TO_BORDER;
693	 if (wr == GL_CLAMP) wr = GL_CLAMP_TO_BORDER;
694
695	 /* 3D textures don't seem to respect the border color.
696	  * Fallback if there's ever a danger that they might refer to
697	  * it.
698	  */
699	 if (ws == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
700	 if (wt == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
701	 if (wr == GL_CLAMP_TO_BORDER) t->refs_border_color = 1;
702      }
703
704      ss3 |= translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT;
705      ss3 |= translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT;
706      ss3 |= translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT;
707
708      if (ss3 != t->Setup[I915_TEXREG_SS3]) {
709	 t->intel.dirty = I915_UPLOAD_TEX_ALL;
710	 t->Setup[I915_TEXREG_SS3] = ss3;
711      }
712   }
713
714   {
715      const GLubyte *color = texObj->_BorderChan;
716
717      t->Setup[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(color[0],color[1],
718						     color[2],color[3]);
719   }
720}
721
722
723
724static void i915_import_tex_unit( i915ContextPtr i915,
725				 i915TextureObjectPtr t,
726				 GLuint unit )
727{
728   GLuint state[I915_TEX_SETUP_SIZE];
729
730   if(INTEL_DEBUG&DEBUG_TEXTURE)
731      fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
732
733   if (i915->intel.CurrentTexObj[unit])
734      i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
735
736   i915->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
737   t->intel.base.bound |= (1 << unit);
738
739   if (t->intel.dirty & I915_UPLOAD_TEX(unit)) {
740      i915ImportTexObjState( t->intel.base.tObj );
741      t->intel.dirty &= ~I915_UPLOAD_TEX(unit);
742   }
743
744   state[I915_TEXREG_MS2] = t->intel.TextureOffset;
745   state[I915_TEXREG_MS3] = t->Setup[I915_TEXREG_MS3];
746   state[I915_TEXREG_MS4] = t->Setup[I915_TEXREG_MS4];
747
748   state[I915_TEXREG_SS2] = (i915->state.Tex[unit][I915_TEXREG_SS2] &
749			    SS2_LOD_BIAS_MASK);
750   state[I915_TEXREG_SS2] |= (t->Setup[I915_TEXREG_SS2] & ~SS2_LOD_BIAS_MASK);
751
752   state[I915_TEXREG_SS3] = (i915->state.Tex[unit][I915_TEXREG_SS3] &
753			    SS3_NORMALIZED_COORDS);
754   state[I915_TEXREG_SS3] |= (t->Setup[I915_TEXREG_SS3] &
755			     ~(SS3_NORMALIZED_COORDS|
756			       SS3_TEXTUREMAP_INDEX_MASK));
757
758   state[I915_TEXREG_SS3] |= (unit<<SS3_TEXTUREMAP_INDEX_SHIFT);
759
760   state[I915_TEXREG_SS4] = t->Setup[I915_TEXREG_SS4];
761
762
763   if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) {
764      I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) );
765      memcpy(i915->state.Tex[unit], state, sizeof(state));
766   }
767}
768
769
770
771static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
772{
773   i915ContextPtr i915 = I915_CONTEXT(ctx);
774   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
775   struct gl_texture_object *tObj = texUnit->_Current;
776   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
777
778   if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, unit);
779
780   if (!(i915->state.active & I915_UPLOAD_TEX(unit))) {
781      I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
782   }
783
784   /* Fallback if there's a texture border */
785   if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
786      return GL_FALSE;
787   }
788
789
790   /* Update state if this is a different texture object to last
791    * time.
792    */
793   if (i915->intel.CurrentTexObj[unit] != &t->intel ||
794       (t->intel.dirty & I915_UPLOAD_TEX(unit))) {
795      i915_import_tex_unit( i915, t, unit);
796      i915->tex_program.translated = 0;
797   }
798
799   return GL_TRUE;
800}
801
802static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
803{
804   i915ContextPtr i915 = I915_CONTEXT(ctx);
805   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
806   struct gl_texture_object *tObj = texUnit->_Current;
807   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
808   GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
809
810   ss3 &= ~SS3_NORMALIZED_COORDS;
811
812   if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
813      I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
814      i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
815   }
816
817   /* Upload teximages (not pipelined)
818    */
819   if (t->intel.base.dirty_images[0]) {
820      i915SetTexImages( i915, tObj );
821      if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
822	 return GL_FALSE;
823      }
824   }
825
826   return GL_TRUE;
827}
828
829
830static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
831{
832   i915ContextPtr i915 = I915_CONTEXT(ctx);
833   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
834   struct gl_texture_object *tObj = texUnit->_Current;
835   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
836   GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
837
838   ss3 |= SS3_NORMALIZED_COORDS;
839
840   if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
841      I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
842      i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
843   }
844
845   /* Upload teximages (not pipelined)
846    */
847   if (t->intel.base.dirty_images[0]) {
848      i915SetTexImages( i915, tObj );
849      if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) {
850	 return GL_FALSE;
851      }
852   }
853
854   return GL_TRUE;
855}
856
857static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
858{
859   i915ContextPtr i915 = I915_CONTEXT(ctx);
860   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
861   struct gl_texture_object *tObj = texUnit->_Current;
862   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
863   GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3];
864   GLuint face;
865
866   ss3 |= SS3_NORMALIZED_COORDS;
867
868   if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) {
869      I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
870      i915->state.Tex[unit][I915_TEXREG_SS3] = ss3;
871   }
872
873   /* Upload teximages (not pipelined)
874    */
875   if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
876        t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
877        t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
878      i915SetTexImages( i915, tObj );
879   }
880
881   /* upload (per face) */
882   for (face = 0; face < 6; face++) {
883      if (t->intel.base.dirty_images[face]) {
884	 if (!intelUploadTexImages( &i915->intel, &t->intel, face )) {
885	    return GL_FALSE;
886	 }
887      }
888   }
889
890
891   return GL_TRUE;
892}
893
894static GLboolean enable_tex_3d( GLcontext *ctx, GLuint unit )
895{
896   struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
897   i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData;
898
899   /* 3D textures on I915 seem to get bogus border colors, hence this
900    * fallback:
901    */
902   if (t->refs_border_color)
903      return GL_FALSE;
904
905   return GL_TRUE;
906}
907
908
909
910
911static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
912{
913   i915ContextPtr i915 = I915_CONTEXT(ctx);
914
915   if (i915->state.active & I915_UPLOAD_TEX(unit)) {
916      I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_FALSE);
917   }
918
919   /* The old texture is no longer bound to this texture unit.
920    * Mark it as such.
921    */
922   if ( i915->intel.CurrentTexObj[unit] != NULL ) {
923      i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
924      i915->intel.CurrentTexObj[unit] = NULL;
925   }
926
927   return GL_TRUE;
928}
929
930static GLboolean i915UpdateTexUnit( GLcontext *ctx, GLuint unit )
931{
932   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
933
934   if (texUnit->_ReallyEnabled &&
935       INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024)
936      return GL_FALSE;
937
938   switch (texUnit->_ReallyEnabled) {
939   case TEXTURE_1D_BIT:
940   case TEXTURE_2D_BIT:
941      return (enable_tex_2d( ctx, unit ) &&
942	      enable_tex_common( ctx, unit ));
943   case TEXTURE_RECT_BIT:
944      return (enable_tex_rect( ctx, unit ) &&
945	      enable_tex_common( ctx, unit ));
946   case TEXTURE_CUBE_BIT:
947      return (enable_tex_cube( ctx, unit ) &&
948	      enable_tex_common( ctx, unit ));
949   case TEXTURE_3D_BIT:
950       return (enable_tex_2d( ctx, unit ) &&
951	       enable_tex_common( ctx, unit ) &&
952	       enable_tex_3d( ctx, unit));
953   case 0:
954      return disable_tex( ctx, unit );
955   default:
956      return GL_FALSE;
957   }
958}
959
960
961void i915UpdateTextureState( intelContextPtr intel )
962{
963   GLcontext *ctx = &intel->ctx;
964   GLboolean ok = GL_TRUE;
965   GLuint i;
966
967   for (i = 0 ; i < I915_TEX_UNITS && ok ; i++) {
968      ok = i915UpdateTexUnit( ctx, i );
969   }
970
971   FALLBACK( intel, I915_FALLBACK_TEXTURE, !ok );
972}
973
974
975
976