r300: half float support
[mesa.git] / src / mesa / drivers / dri / mach64 / mach64_texstate.c
1 /* -*- mode: c; c-basic-offset: 3 -*- */
2 /*
3 * Copyright 2000 Gareth Hughes
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 "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /*
26 * Authors:
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * José Fonseca <j_r_fonseca@yahoo.co.uk>
30 */
31
32 #include "main/glheader.h"
33 #include "main/imports.h"
34 #include "main/context.h"
35 #include "main/macros.h"
36
37 #include "mach64_context.h"
38 #include "mach64_ioctl.h"
39 #include "mach64_state.h"
40 #include "mach64_vb.h"
41 #include "mach64_tris.h"
42 #include "mach64_tex.h"
43
44 static void mach64SetTexImages( mach64ContextPtr mmesa,
45 const struct gl_texture_object *tObj )
46 {
47 mach64TexObjPtr t = (mach64TexObjPtr) tObj->DriverData;
48 struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
49 int totalSize;
50
51 assert(t);
52 assert(baseImage);
53
54 if ( MACH64_DEBUG & DEBUG_VERBOSE_API )
55 fprintf( stderr, "%s( %p )\n", __FUNCTION__, tObj );
56
57 switch (baseImage->TexFormat) {
58 case MESA_FORMAT_ARGB8888:
59 t->textureFormat = MACH64_DATATYPE_ARGB8888;
60 break;
61 case MESA_FORMAT_ARGB4444:
62 t->textureFormat = MACH64_DATATYPE_ARGB4444;
63 break;
64 case MESA_FORMAT_RGB565:
65 t->textureFormat = MACH64_DATATYPE_RGB565;
66 break;
67 case MESA_FORMAT_ARGB1555:
68 t->textureFormat = MACH64_DATATYPE_ARGB1555;
69 break;
70 case MESA_FORMAT_RGB332:
71 t->textureFormat = MACH64_DATATYPE_RGB332;
72 break;
73 case MESA_FORMAT_RGB888:
74 t->textureFormat = MACH64_DATATYPE_RGB8;
75 break;
76 case MESA_FORMAT_CI8:
77 t->textureFormat = MACH64_DATATYPE_CI8;
78 break;
79 case MESA_FORMAT_YCBCR:
80 t->textureFormat = MACH64_DATATYPE_YVYU422;
81 break;
82 case MESA_FORMAT_YCBCR_REV:
83 t->textureFormat = MACH64_DATATYPE_VYUY422;
84 break;
85 default:
86 _mesa_problem(mmesa->glCtx, "Bad texture format in %s", __FUNCTION__);
87 };
88
89 totalSize = ( baseImage->Height *
90 baseImage->Width *
91 _mesa_get_format_bytes(baseImage->TexFormat) );
92
93 totalSize = (totalSize + 31) & ~31;
94
95 t->base.totalSize = totalSize;
96 t->base.firstLevel = tObj->BaseLevel;
97 t->base.lastLevel = tObj->BaseLevel;
98
99 /* Set the texture format */
100 if ( ( baseImage->_BaseFormat == GL_RGBA ) ||
101 ( baseImage->_BaseFormat == GL_ALPHA ) ||
102 ( baseImage->_BaseFormat == GL_LUMINANCE_ALPHA ) ) {
103 t->hasAlpha = 1;
104 } else {
105 t->hasAlpha = 0;
106 }
107
108 t->widthLog2 = baseImage->WidthLog2;
109 t->heightLog2 = baseImage->HeightLog2;
110 t->maxLog2 = baseImage->MaxLog2;
111 }
112
113 static void mach64UpdateTextureEnv( GLcontext *ctx, int unit )
114 {
115 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
116 GLint source = mmesa->tmu_source[unit];
117 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
118 const struct gl_texture_object *tObj = texUnit->_Current;
119 const GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
120 GLuint s = mmesa->setup.scale_3d_cntl;
121
122 if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
123 fprintf( stderr, "%s( %p, %d )\n",
124 __FUNCTION__, ctx, unit );
125 }
126
127 /* REPLACE MODULATE DECAL GL_BLEND
128 *
129 * ALPHA C = Cf C = Cf undef C = Cf
130 * A = At A = AfAt A = AfAt
131 *
132 * LUMINANCE C = Ct C = CfCt undef C = Cf(1-Ct)+CcCt
133 * A = Af A = Af A = Af
134 *
135 * LUMINANCE_ALPHA C = Ct C = CfCt undef C = Cf(1-Ct)+CcCt
136 * A = At A = AfAt A = AfAt
137 *
138 * INTENSITY C = Ct C = CfCt undef C = Cf(1-Ct)+CcCt
139 * A = At A = AfAt A = Af(1-At)+AcAt
140 *
141 * RGB C = Ct C = CfCt C = Ct C = Cf(1-Ct)+CcCt
142 * A = Af A = Af A = Af A = Af
143 *
144 * RGBA C = Ct C = CfCt C = Cf(1-At)+CtAt C = Cf(1-Ct)+CcCt
145 * A = At A = AfAt A = Af A = AfAt
146 */
147
148
149 if ( unit == 0 ) {
150 s &= ~MACH64_TEX_LIGHT_FCN_MASK;
151
152 /* Set the texture environment state
153 * Need to verify these are working correctly, but the
154 * texenv Mesa demo seems to work.
155 */
156 switch ( texUnit->EnvMode ) {
157 case GL_REPLACE:
158 switch ( format ) {
159 case GL_ALPHA:
160 case GL_LUMINANCE_ALPHA:
161 case GL_INTENSITY:
162 /* Not compliant - can't get At */
163 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
164 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
165 break;
166 default:
167 s |= MACH64_TEX_LIGHT_FCN_REPLACE;
168 }
169 break;
170 case GL_MODULATE:
171 switch ( format ) {
172 case GL_ALPHA:
173 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
174 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
175 break;
176 case GL_RGB:
177 case GL_LUMINANCE:
178 /* These should be compliant */
179 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
180 break;
181 case GL_LUMINANCE_ALPHA:
182 case GL_INTENSITY:
183 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
184 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
185 break;
186 case GL_RGBA:
187 /* Should fallback when blending enabled for complete compliance */
188 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
189 break;
190 default:
191 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
192 }
193 break;
194 case GL_DECAL:
195 switch ( format ) {
196 case GL_RGBA:
197 s |= MACH64_TEX_LIGHT_FCN_ALPHA_DECAL;
198 break;
199 case GL_RGB:
200 s |= MACH64_TEX_LIGHT_FCN_REPLACE;
201 break;
202 case GL_ALPHA:
203 case GL_LUMINANCE_ALPHA:
204 /* undefined - disable texturing, pass fragment unmodified */
205 /* Also, pass fragment alpha instead of texture alpha */
206 s &= ~MACH64_TEX_MAP_AEN;
207 s |= MACH64_TEXTURE_DISABLE;
208 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
209 break;
210 case GL_LUMINANCE:
211 case GL_INTENSITY:
212 /* undefined - disable texturing, pass fragment unmodified */
213 s |= MACH64_TEXTURE_DISABLE;
214 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
215 break;
216 default:
217 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
218 }
219 break;
220 case GL_BLEND:
221 /* GL_BLEND not supported by RagePRO, use software */
222 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
223 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
224 break;
225 case GL_ADD:
226 case GL_COMBINE:
227 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
228 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
229 break;
230 default:
231 s |= MACH64_TEX_LIGHT_FCN_MODULATE;
232 }
233
234 if ( mmesa->setup.scale_3d_cntl != s ) {
235 mmesa->setup.scale_3d_cntl = s;
236 mmesa->dirty |= MACH64_UPLOAD_SCALE_3D_CNTL;
237 }
238
239 } else {
240 /* blend = 0, modulate = 1 - initialize to blend */
241 mmesa->setup.tex_cntl &= ~MACH64_COMP_COMBINE_MODULATE;
242 /* Set the texture composite function for multitexturing*/
243 switch ( texUnit->EnvMode ) {
244 case GL_BLEND:
245 /* GL_BLEND not supported by RagePRO, use software */
246 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
247 mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
248 break;
249 case GL_MODULATE:
250 /* Should fallback when blending enabled for complete compliance */
251 mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
252 break;
253 case GL_REPLACE:
254 switch ( format ) {
255 case GL_ALPHA:
256 mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
257 break;
258 default: /* not supported by RagePRO */
259 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
260 mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
261 }
262 break;
263 case GL_DECAL:
264 switch ( format ) {
265 case GL_ALPHA:
266 case GL_LUMINANCE:
267 case GL_LUMINANCE_ALPHA:
268 case GL_INTENSITY:
269 /* undefined, disable compositing and pass fragment unmodified */
270 mmesa->setup.tex_cntl &= ~MACH64_TEXTURE_COMPOSITE;
271 break;
272 default: /* not supported by RagePRO */
273 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
274 mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
275 }
276 break;
277 case GL_ADD:
278 case GL_COMBINE:
279 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
280 mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
281 break;
282 default:
283 mmesa->setup.tex_cntl |= MACH64_COMP_COMBINE_MODULATE;
284 }
285 }
286 }
287
288
289 static void mach64UpdateTextureUnit( GLcontext *ctx, int unit )
290 {
291 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
292 int source = mmesa->tmu_source[unit];
293 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
294 const struct gl_texture_object *tObj = ctx->Texture.Unit[source]._Current;
295 mach64TexObjPtr t = tObj->DriverData;
296 GLuint d = mmesa->setup.dp_pix_width;
297 GLuint s = mmesa->setup.scale_3d_cntl;
298
299 assert(unit == 0 || unit == 1); /* only two tex units */
300
301 if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
302 fprintf( stderr, "%s( %p, %d ) enabled=0x%x 0x%x\n",
303 __FUNCTION__, ctx, unit, ctx->Texture.Unit[0]._ReallyEnabled,
304 ctx->Texture.Unit[1]._ReallyEnabled);
305 }
306
307 if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
308
309 assert(t); /* should have driver tex data by now */
310
311 /* Fallback if there's a texture border */
312 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
313 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
314 return;
315 }
316
317 /* Upload teximages */
318 if (t->base.dirty_images[0]) {
319 mach64SetTexImages( mmesa, tObj );
320 mmesa->dirty |= (MACH64_UPLOAD_TEX0IMAGE << unit);
321 }
322
323 /* Bind to the given texture unit */
324 mmesa->CurrentTexObj[unit] = t;
325 t->base.bound |= (1 << unit);
326
327 if ( t->base.memBlock )
328 driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
329
330 /* register setup */
331 if ( unit == 0 ) {
332 d &= ~MACH64_SCALE_PIX_WIDTH_MASK;
333 d |= (t->textureFormat << 28);
334
335 s &= ~(MACH64_TEXTURE_DISABLE |
336 MACH64_TEX_CACHE_SPLIT |
337 MACH64_TEX_BLEND_FCN_MASK |
338 MACH64_TEX_MAP_AEN);
339
340 if ( mmesa->multitex ) {
341 s |= MACH64_TEX_BLEND_FCN_TRILINEAR | MACH64_TEX_CACHE_SPLIT;
342 } else if ( t->BilinearMin ) {
343 s |= MACH64_TEX_BLEND_FCN_LINEAR;
344 } else {
345 s |= MACH64_TEX_BLEND_FCN_NEAREST;
346 }
347 if ( t->BilinearMag ) {
348 s |= MACH64_BILINEAR_TEX_EN;
349 } else {
350 s &= ~MACH64_BILINEAR_TEX_EN;
351 }
352
353 if ( t->hasAlpha ) {
354 s |= MACH64_TEX_MAP_AEN;
355 }
356
357 mmesa->setup.tex_cntl &= ~(MACH64_TEXTURE_CLAMP_S |
358 MACH64_TEXTURE_CLAMP_T |
359 MACH64_SECONDARY_STW);
360
361 if ( t->ClampS ) {
362 mmesa->setup.tex_cntl |= MACH64_TEXTURE_CLAMP_S;
363 }
364 if ( t->ClampT ) {
365 mmesa->setup.tex_cntl |= MACH64_TEXTURE_CLAMP_T;
366 }
367
368 mmesa->setup.tex_size_pitch |= ((t->widthLog2 << 0) |
369 (t->maxLog2 << 4) |
370 (t->heightLog2 << 8));
371 } else {
372
373 /* Enable texture mapping mode */
374 s &= ~MACH64_TEXTURE_DISABLE;
375
376 d &= ~MACH64_COMPOSITE_PIX_WIDTH_MASK;
377 d |= (t->textureFormat << 4);
378
379 mmesa->setup.tex_cntl &= ~(MACH64_COMP_ALPHA |
380 MACH64_SEC_TEX_CLAMP_S |
381 MACH64_SEC_TEX_CLAMP_T);
382 mmesa->setup.tex_cntl |= (MACH64_TEXTURE_COMPOSITE |
383 MACH64_SECONDARY_STW);
384
385 if ( t->BilinearMin ) {
386 mmesa->setup.tex_cntl |= MACH64_COMP_BLEND_BILINEAR;
387 } else {
388 mmesa->setup.tex_cntl &= ~MACH64_COMP_BLEND_BILINEAR;
389 }
390 if ( t->BilinearMag ) {
391 mmesa->setup.tex_cntl |= MACH64_COMP_FILTER_BILINEAR;
392 } else {
393 mmesa->setup.tex_cntl &= ~MACH64_COMP_FILTER_BILINEAR;
394 }
395
396 if ( t->hasAlpha ) {
397 mmesa->setup.tex_cntl |= MACH64_COMP_ALPHA;
398 }
399 if ( t->ClampS ) {
400 mmesa->setup.tex_cntl |= MACH64_SEC_TEX_CLAMP_S;
401 }
402 if ( t->ClampT ) {
403 mmesa->setup.tex_cntl |= MACH64_SEC_TEX_CLAMP_T;
404 }
405
406 mmesa->setup.tex_size_pitch |= ((t->widthLog2 << 16) |
407 (t->maxLog2 << 20) |
408 (t->heightLog2 << 24));
409 }
410
411 if ( mmesa->setup.scale_3d_cntl != s ) {
412 mmesa->setup.scale_3d_cntl = s;
413 mmesa->dirty |= MACH64_UPLOAD_SCALE_3D_CNTL;
414 }
415
416 if ( mmesa->setup.dp_pix_width != d ) {
417 mmesa->setup.dp_pix_width = d;
418 mmesa->dirty |= MACH64_UPLOAD_DP_PIX_WIDTH;
419 }
420 }
421 else if (texUnit->_ReallyEnabled) {
422 /* 3D or cube map texture enabled - fallback */
423 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_TRUE );
424 }
425 else {
426 /* texture unit disabled */
427 }
428 }
429
430
431 /* Update the hardware texture state */
432 void mach64UpdateTextureState( GLcontext *ctx )
433 {
434 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
435
436 if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
437 fprintf( stderr, "%s( %p ) en=0x%x 0x%x\n",
438 __FUNCTION__, ctx, ctx->Texture.Unit[0]._ReallyEnabled,
439 ctx->Texture.Unit[1]._ReallyEnabled);
440 }
441
442 /* Clear any texturing fallbacks */
443 FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_FALSE );
444
445 /* Unbind any currently bound textures */
446 if ( mmesa->CurrentTexObj[0] ) mmesa->CurrentTexObj[0]->base.bound = 0;
447 if ( mmesa->CurrentTexObj[1] ) mmesa->CurrentTexObj[1]->base.bound = 0;
448 mmesa->CurrentTexObj[0] = NULL;
449 mmesa->CurrentTexObj[1] = NULL;
450
451 /* Disable all texturing until it is known to be good */
452 mmesa->setup.scale_3d_cntl |= MACH64_TEXTURE_DISABLE;
453 mmesa->setup.scale_3d_cntl &= ~MACH64_TEX_MAP_AEN;
454 mmesa->setup.tex_cntl &= ~MACH64_TEXTURE_COMPOSITE;
455
456 mmesa->setup.tex_size_pitch = 0x00000000;
457
458 mmesa->tmu_source[0] = 0;
459 mmesa->tmu_source[1] = 1;
460 mmesa->multitex = 0;
461
462 if (ctx->Texture._EnabledUnits & 0x2) {
463 /* unit 1 enabled */
464 if (ctx->Texture._EnabledUnits & 0x1) {
465 /* units 0 and 1 enabled */
466 mmesa->multitex = 1;
467 mach64UpdateTextureUnit( ctx, 0 );
468 mach64UpdateTextureEnv( ctx, 0 );
469 mach64UpdateTextureUnit( ctx, 1 );
470 mach64UpdateTextureEnv( ctx, 1 );
471 } else {
472 mmesa->tmu_source[0] = 1;
473 mmesa->tmu_source[1] = 0;
474 mach64UpdateTextureUnit( ctx, 0 );
475 mach64UpdateTextureEnv( ctx, 0 );
476 }
477 } else if (ctx->Texture._EnabledUnits & 0x1) {
478 /* only unit 0 enabled */
479 mach64UpdateTextureUnit( ctx, 0 );
480 mach64UpdateTextureEnv( ctx, 0 );
481 }
482
483 mmesa->dirty |= (MACH64_UPLOAD_SCALE_3D_CNTL |
484 MACH64_UPLOAD_TEXTURE);
485 }
486
487
488 /* Due to the way we must program texture state into the Rage Pro,
489 * we must leave these calculations to the absolute last minute.
490 */
491 void mach64EmitTexStateLocked( mach64ContextPtr mmesa,
492 mach64TexObjPtr t0,
493 mach64TexObjPtr t1 )
494 {
495 drm_mach64_sarea_t *sarea = mmesa->sarea;
496 drm_mach64_context_regs_t *regs = &(mmesa->setup);
497
498 /* for multitex, both textures must be local or AGP */
499 if ( t0 && t1 )
500 assert(t0->heap == t1->heap);
501
502 if ( t0 ) {
503 if (t0->heap == MACH64_CARD_HEAP) {
504 #if ENABLE_PERF_BOXES
505 mmesa->c_texsrc_card++;
506 #endif
507 mmesa->setup.tex_cntl &= ~MACH64_TEX_SRC_AGP;
508 } else {
509 #if ENABLE_PERF_BOXES
510 mmesa->c_texsrc_agp++;
511 #endif
512 mmesa->setup.tex_cntl |= MACH64_TEX_SRC_AGP;
513 }
514 mmesa->setup.tex_offset = t0->bufAddr;
515 }
516
517 if ( t1 ) {
518 mmesa->setup.secondary_tex_off = t1->bufAddr;
519 }
520
521 memcpy( &sarea->context_state.tex_size_pitch, &regs->tex_size_pitch,
522 MACH64_NR_TEXTURE_REGS * sizeof(GLuint) );
523 }
524