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