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