fix up radeon span functions using latest r200 code from Brian,
[mesa.git] / src / mesa / drivers / dri / i915 / i830_texstate.c
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 "i830_context.h"
43 #include "i830_reg.h"
44
45 static const GLint initial_offsets[6][2] = { {0,0},
46 {0,2},
47 {1,0},
48 {1,2},
49 {1,1},
50 {1,3} };
51
52 static const GLint step_offsets[6][2] = { {0,2},
53 {0,2},
54 {-1,2},
55 {-1,2},
56 {-1,1},
57 {-1,1} };
58
59 #define I830_TEX_UNIT_ENABLED(unit) (1<<unit)
60
61 static GLboolean i830SetTexImages( i830ContextPtr i830,
62 struct gl_texture_object *tObj )
63 {
64 GLuint total_height, pitch, i, textureFormat;
65 i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
66 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
67 GLint firstLevel, lastLevel, numLevels;
68
69 switch( baseImage->TexFormat->MesaFormat ) {
70 case MESA_FORMAT_L8:
71 t->intel.texelBytes = 1;
72 textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
73 break;
74
75 case MESA_FORMAT_I8:
76 t->intel.texelBytes = 1;
77 textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
78 break;
79
80 case MESA_FORMAT_A8:
81 t->intel.texelBytes = 1;
82 textureFormat = MAPSURF_8BIT | MT_8BIT_I8; /* Kludge -- check with conform, glean */
83 break;
84
85 case MESA_FORMAT_AL88:
86 t->intel.texelBytes = 2;
87 textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
88 break;
89
90 case MESA_FORMAT_RGB565:
91 t->intel.texelBytes = 2;
92 textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
93 break;
94
95 case MESA_FORMAT_ARGB1555:
96 t->intel.texelBytes = 2;
97 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
98 break;
99
100 case MESA_FORMAT_ARGB4444:
101 t->intel.texelBytes = 2;
102 textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
103 break;
104
105 case MESA_FORMAT_ARGB8888:
106 t->intel.texelBytes = 4;
107 textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
108 break;
109
110 case MESA_FORMAT_YCBCR_REV:
111 t->intel.texelBytes = 2;
112 textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL |
113 TM0S1_COLORSPACE_CONVERSION);
114 break;
115
116 case MESA_FORMAT_YCBCR:
117 t->intel.texelBytes = 2;
118 textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */
119 TM0S1_COLORSPACE_CONVERSION);
120 break;
121
122 case MESA_FORMAT_RGB_FXT1:
123 case MESA_FORMAT_RGBA_FXT1:
124 t->intel.texelBytes = 2;
125 textureFormat = MAPSURF_COMPRESSED | MT_COMPRESS_FXT1;
126 break;
127
128 case MESA_FORMAT_RGBA_DXT1:
129 case MESA_FORMAT_RGB_DXT1:
130 /*
131 * DXTn pitches are Width/4 * blocksize in bytes
132 * for DXT1: blocksize=8 so Width/4*8 = Width * 2
133 * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
134 */
135 t->intel.texelBytes = 2;
136 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
137 break;
138 case MESA_FORMAT_RGBA_DXT3:
139 t->intel.texelBytes = 4;
140 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
141 break;
142 case MESA_FORMAT_RGBA_DXT5:
143 t->intel.texelBytes = 4;
144 textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
145 break;
146
147 default:
148 fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
149 abort();
150 }
151
152 /* Compute which mipmap levels we really want to send to the hardware.
153 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
154 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
155 * Yes, this looks overly complicated, but it's all needed.
156 */
157 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
158
159
160 /* Figure out the amount of memory required to hold all the mipmap
161 * levels. Choose the smallest pitch to accomodate the largest
162 * mipmap:
163 */
164 firstLevel = t->intel.base.firstLevel;
165 lastLevel = t->intel.base.lastLevel;
166 numLevels = lastLevel - firstLevel + 1;
167
168
169 /* All images must be loaded at this pitch. Count the number of
170 * lines required:
171 */
172 switch (tObj->Target) {
173 case GL_TEXTURE_CUBE_MAP: {
174 const GLuint dim = tObj->Image[0][firstLevel]->Width;
175 GLuint face;
176
177 pitch = dim * t->intel.texelBytes;
178 pitch *= 2; /* double pitch for cube layouts */
179 pitch = (pitch + 3) & ~3;
180
181 total_height = dim * 4;
182
183 for ( face = 0 ; face < 6 ; face++) {
184 GLuint x = initial_offsets[face][0] * dim;
185 GLuint y = initial_offsets[face][1] * dim;
186 GLuint d = dim;
187
188 t->intel.base.dirty_images[face] = ~0;
189
190 assert(tObj->Image[face][firstLevel]->Width == dim);
191 assert(tObj->Image[face][firstLevel]->Height == dim);
192
193 for (i = 0; i < numLevels; i++) {
194 t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
195 if (!t->intel.image[face][i].image) {
196 fprintf(stderr, "no image %d %d\n", face, i);
197 break; /* can't happen */
198 }
199
200 t->intel.image[face][i].offset =
201 y * pitch + x * t->intel.texelBytes;
202 t->intel.image[face][i].internalFormat = baseImage->_BaseFormat;
203
204 d >>= 1;
205 x += step_offsets[face][0] * d;
206 y += step_offsets[face][1] * d;
207 }
208 }
209 break;
210 }
211 default:
212 pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
213 pitch = (pitch + 3) & ~3;
214 t->intel.base.dirty_images[0] = ~0;
215
216 for ( total_height = i = 0 ; i < numLevels ; i++ ) {
217 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
218 if (!t->intel.image[0][i].image)
219 break;
220
221 t->intel.image[0][i].offset = total_height * pitch;
222 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
223 if (t->intel.image[0][i].image->IsCompressed)
224 {
225 if (t->intel.image[0][i].image->Height > 4)
226 total_height += t->intel.image[0][i].image->Height/4;
227 else
228 total_height += 1;
229 }
230 else
231 total_height += MAX2(2, t->intel.image[0][i].image->Height);
232 }
233 break;
234 }
235
236 t->intel.Pitch = pitch;
237 t->intel.base.totalSize = total_height*pitch;
238 t->intel.max_level = i-1;
239 t->Setup[I830_TEXREG_TM0S1] =
240 (((tObj->Image[0][firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) |
241 ((tObj->Image[0][firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) |
242 textureFormat);
243 t->Setup[I830_TEXREG_TM0S2] =
244 (((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) |
245 TM0S2_CUBE_FACE_ENA_MASK;
246 t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
247 t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
248 t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
249 t->intel.dirty = I830_UPLOAD_TEX_ALL;
250
251 return intelUploadTexImages( &i830->intel, &t->intel, 0 );
252 }
253
254
255 static void i830_import_tex_unit( i830ContextPtr i830,
256 i830TextureObjectPtr t,
257 GLuint unit )
258 {
259 if(INTEL_DEBUG&DEBUG_TEXTURE)
260 fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
261
262 if (i830->intel.CurrentTexObj[unit])
263 i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
264
265 i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
266 t->intel.base.bound |= (1 << unit);
267
268 I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
269
270 i830->state.Tex[unit][I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
271 (LOAD_TEXTURE_MAP0 << unit) | 4);
272 i830->state.Tex[unit][I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE |
273 t->intel.TextureOffset);
274
275 i830->state.Tex[unit][I830_TEXREG_TM0S1] = t->Setup[I830_TEXREG_TM0S1];
276 i830->state.Tex[unit][I830_TEXREG_TM0S2] = t->Setup[I830_TEXREG_TM0S2];
277
278 i830->state.Tex[unit][I830_TEXREG_TM0S3] &= TM0S3_LOD_BIAS_MASK;
279 i830->state.Tex[unit][I830_TEXREG_TM0S3] |= (t->Setup[I830_TEXREG_TM0S3] &
280 ~TM0S3_LOD_BIAS_MASK);
281
282 i830->state.Tex[unit][I830_TEXREG_TM0S4] = t->Setup[I830_TEXREG_TM0S4];
283 i830->state.Tex[unit][I830_TEXREG_MCS] = (t->Setup[I830_TEXREG_MCS] &
284 ~MAP_UNIT_MASK);
285 i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE];
286 i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit);
287
288 t->intel.dirty &= ~I830_UPLOAD_TEX(unit);
289 }
290
291
292
293 static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
294 {
295 i830ContextPtr i830 = I830_CONTEXT(ctx);
296 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
297 struct gl_texture_object *tObj = texUnit->_Current;
298 i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
299
300 if (0) fprintf(stderr, "%s\n", __FUNCTION__);
301
302 /* Fallback if there's a texture border */
303 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
304 fprintf(stderr, "Texture border\n");
305 return GL_FALSE;
306 }
307
308 /* Upload teximages (not pipelined)
309 */
310 if (t->intel.base.dirty_images[0]) {
311 if (!i830SetTexImages( i830, tObj )) {
312 return GL_FALSE;
313 }
314 }
315
316 /* Update state if this is a different texture object to last
317 * time.
318 */
319 if (i830->intel.CurrentTexObj[unit] != &t->intel ||
320 (t->intel.dirty & I830_UPLOAD_TEX(unit))) {
321 i830_import_tex_unit( i830, t, unit);
322 }
323
324 I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
325
326 return GL_TRUE;
327 }
328
329 static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
330 {
331 i830ContextPtr i830 = I830_CONTEXT(ctx);
332 GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
333
334 mcs &= ~TEXCOORDS_ARE_NORMAL;
335 mcs |= TEXCOORDS_ARE_IN_TEXELUNITS;
336
337 if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
338 || (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
339 I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
340 i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
341 i830->state.Tex[unit][I830_TEXREG_CUBE] = 0;
342 }
343
344 return GL_TRUE;
345 }
346
347
348 static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
349 {
350 i830ContextPtr i830 = I830_CONTEXT(ctx);
351 GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
352
353 mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
354 mcs |= TEXCOORDS_ARE_NORMAL;
355
356 if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
357 || (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
358 I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
359 i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
360 i830->state.Tex[unit][I830_TEXREG_CUBE] = 0;
361 }
362
363 return GL_TRUE;
364 }
365
366
367 static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
368 {
369 i830ContextPtr i830 = I830_CONTEXT(ctx);
370 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
371 struct gl_texture_object *tObj = texUnit->_Current;
372 i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
373 GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
374 const GLuint cube = CUBE_NEGX_ENABLE | CUBE_POSX_ENABLE
375 | CUBE_NEGY_ENABLE | CUBE_POSY_ENABLE
376 | CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE;
377 GLuint face;
378
379 mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
380 mcs |= TEXCOORDS_ARE_NORMAL;
381
382 if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
383 || (cube != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
384 I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
385 i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
386 i830->state.Tex[unit][I830_TEXREG_CUBE] = cube;
387 }
388
389 /* Upload teximages (not pipelined)
390 */
391 if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
392 t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
393 t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
394 i830SetTexImages( i830, tObj );
395 }
396
397 /* upload (per face) */
398 for (face = 0; face < 6; face++) {
399 if (t->intel.base.dirty_images[face]) {
400 if (!intelUploadTexImages( &i830->intel, &t->intel, face )) {
401 return GL_FALSE;
402 }
403 }
404 }
405
406
407 return GL_TRUE;
408 }
409
410
411 static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
412 {
413 i830ContextPtr i830 = I830_CONTEXT(ctx);
414
415 /* This is happening too often. I need to conditionally send diffuse
416 * state to the card. Perhaps a diffuse dirty flag of some kind.
417 * Will need to change this logic if more than 2 texture units are
418 * used. We need to only do this up to the last unit enabled, or unit
419 * one if nothing is enabled.
420 */
421
422 if ( i830->intel.CurrentTexObj[unit] != NULL ) {
423 /* The old texture is no longer bound to this texture unit.
424 * Mark it as such.
425 */
426
427 i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
428 i830->intel.CurrentTexObj[unit] = NULL;
429 }
430
431 return GL_TRUE;
432 }
433
434 static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
435 {
436 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
437
438 if (texUnit->_ReallyEnabled &&
439 INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024)
440 return GL_FALSE;
441
442 switch(texUnit->_ReallyEnabled) {
443 case TEXTURE_1D_BIT:
444 case TEXTURE_2D_BIT:
445 return (enable_tex_common( ctx, unit ) &&
446 enable_tex_2d( ctx, unit ));
447 case TEXTURE_RECT_BIT:
448 return (enable_tex_common( ctx, unit ) &&
449 enable_tex_rect( ctx, unit ));
450 case TEXTURE_CUBE_BIT:
451 return (enable_tex_common( ctx, unit ) &&
452 enable_tex_cube( ctx, unit ));
453 case 0:
454 return disable_tex( ctx, unit );
455 default:
456 return GL_FALSE;
457 }
458 }
459
460
461 void i830UpdateTextureState( intelContextPtr intel )
462 {
463 i830ContextPtr i830 = I830_CONTEXT(intel);
464 GLcontext *ctx = &intel->ctx;
465 GLboolean ok;
466
467 if (0) fprintf(stderr, "%s\n", __FUNCTION__);
468
469 I830_ACTIVESTATE(i830, I830_UPLOAD_TEX_ALL, GL_FALSE);
470
471 ok = (i830UpdateTexUnit( ctx, 0 ) &&
472 i830UpdateTexUnit( ctx, 1 ) &&
473 i830UpdateTexUnit( ctx, 2 ) &&
474 i830UpdateTexUnit( ctx, 3 ));
475
476 FALLBACK( intel, I830_FALLBACK_TEXTURE, !ok );
477
478 if (ok)
479 i830EmitTextureBlend( i830 );
480 }
481
482
483