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