225d23179e10a029e58e9bb948cea6aa8ed34d9f
[mesa.git] / src / mesa / drivers / dri / mach64 / mach64_tex.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 "mach64_context.h"
33 #include "mach64_ioctl.h"
34 #include "mach64_state.h"
35 #include "mach64_vb.h"
36 #include "mach64_tris.h"
37 #include "mach64_tex.h"
38
39 #include "main/context.h"
40 #include "main/macros.h"
41 #include "main/simple_list.h"
42 #include "main/enums.h"
43 #include "main/texstore.h"
44 #include "main/texformat.h"
45 #include "main/teximage.h"
46 #include "main/texobj.h"
47 #include "main/imports.h"
48
49
50 static void mach64SetTexWrap( mach64TexObjPtr t,
51 GLenum swrap, GLenum twrap )
52 {
53 switch ( swrap ) {
54 case GL_CLAMP:
55 case GL_CLAMP_TO_EDGE:
56 case GL_CLAMP_TO_BORDER:
57 t->ClampS = GL_TRUE;
58 break;
59 case GL_REPEAT:
60 t->ClampS = GL_FALSE;
61 break;
62 }
63
64 switch ( twrap ) {
65 case GL_CLAMP:
66 case GL_CLAMP_TO_EDGE:
67 case GL_CLAMP_TO_BORDER:
68 t->ClampT = GL_TRUE;
69 break;
70 case GL_REPEAT:
71 t->ClampT = GL_FALSE;
72 break;
73 }
74 }
75
76 static void mach64SetTexFilter( mach64TexObjPtr t,
77 GLenum minf, GLenum magf )
78 {
79 switch ( minf ) {
80 case GL_NEAREST:
81 case GL_NEAREST_MIPMAP_NEAREST:
82 case GL_NEAREST_MIPMAP_LINEAR:
83 t->BilinearMin = GL_FALSE;
84 break;
85 case GL_LINEAR:
86 case GL_LINEAR_MIPMAP_NEAREST:
87 case GL_LINEAR_MIPMAP_LINEAR:
88 t->BilinearMin = GL_TRUE;
89 break;
90 }
91
92 switch ( magf ) {
93 case GL_NEAREST:
94 t->BilinearMag = GL_FALSE;
95 break;
96 case GL_LINEAR:
97 t->BilinearMag = GL_TRUE;
98 break;
99 }
100 }
101
102 static void mach64SetTexBorderColor( mach64TexObjPtr t, const GLfloat c[4] )
103 {
104 #if 0
105 GLuint border = mach64PackColor( 4, c[0], c[1], c[2], c[3] );
106 #endif
107 }
108
109
110 static mach64TexObjPtr
111 mach64AllocTexObj( struct gl_texture_object *texObj )
112 {
113 mach64TexObjPtr t;
114
115 if ( MACH64_DEBUG & DEBUG_VERBOSE_API )
116 fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj );
117
118 t = (mach64TexObjPtr) CALLOC_STRUCT( mach64_texture_object );
119 texObj->DriverData = t;
120 if ( !t )
121 return NULL;
122
123 /* Initialize non-image-dependent parts of the state:
124 */
125 t->base.tObj = texObj;
126 t->base.dirty_images[0] = (1 << 0);
127
128 t->bufAddr = 0;
129
130 make_empty_list( (driTextureObject *) t );
131
132 mach64SetTexWrap( t, texObj->WrapS, texObj->WrapT );
133 mach64SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
134 mach64SetTexBorderColor( t, texObj->BorderColor );
135
136 return t;
137 }
138
139
140 /* Called by the _mesa_store_teximage[123]d() functions. */
141 static const struct gl_texture_format *
142 mach64ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
143 GLenum format, GLenum type )
144 {
145 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
146 (void) format;
147 (void) type;
148
149 switch ( internalFormat ) {
150 case GL_ALPHA:
151 case GL_ALPHA4:
152 case GL_ALPHA8:
153 case GL_ALPHA12:
154 case GL_ALPHA16:
155 case GL_COMPRESSED_ALPHA:
156 case 2:
157 case GL_LUMINANCE_ALPHA:
158 case GL_LUMINANCE4_ALPHA4:
159 case GL_LUMINANCE6_ALPHA2:
160 case GL_LUMINANCE8_ALPHA8:
161 case GL_LUMINANCE12_ALPHA4:
162 case GL_LUMINANCE12_ALPHA12:
163 case GL_LUMINANCE16_ALPHA16:
164 case GL_COMPRESSED_LUMINANCE_ALPHA:
165 case 4:
166 case GL_RGBA:
167 case GL_RGBA2:
168 case GL_COMPRESSED_RGBA:
169 if (mmesa->mach64Screen->cpp == 4)
170 return &_mesa_texformat_argb8888;
171 else
172 return &_mesa_texformat_argb4444;
173
174 case GL_RGB5_A1:
175 if (mmesa->mach64Screen->cpp == 4)
176 return &_mesa_texformat_argb8888;
177 else
178 return &_mesa_texformat_argb1555;
179
180 case GL_RGBA8:
181 case GL_RGB10_A2:
182 case GL_RGBA12:
183 case GL_RGBA16:
184 case GL_RGBA4:
185 if (mmesa->mach64Screen->cpp == 4)
186 return &_mesa_texformat_argb8888;
187 else
188 return &_mesa_texformat_argb4444;
189
190 case 3:
191 case GL_RGB:
192 case GL_R3_G3_B2:
193 case GL_RGB4:
194 case GL_RGB5:
195 case GL_RGB8:
196 case GL_RGB10:
197 case GL_RGB12:
198 case GL_RGB16:
199 case GL_COMPRESSED_RGB:
200 if (mmesa->mach64Screen->cpp == 4)
201 return &_mesa_texformat_argb8888;
202 else
203 return &_mesa_texformat_rgb565;
204
205 case 1:
206 case GL_LUMINANCE:
207 case GL_LUMINANCE4:
208 case GL_LUMINANCE8:
209 case GL_LUMINANCE12:
210 case GL_LUMINANCE16:
211 case GL_COMPRESSED_LUMINANCE:
212 if (mmesa->mach64Screen->cpp == 4)
213 return &_mesa_texformat_argb8888; /* inefficient but accurate */
214 else
215 return &_mesa_texformat_argb1555;
216
217 case GL_INTENSITY4:
218 case GL_INTENSITY:
219 case GL_INTENSITY8:
220 case GL_INTENSITY12:
221 case GL_INTENSITY16:
222 case GL_COMPRESSED_INTENSITY:
223 if (mmesa->mach64Screen->cpp == 4)
224 return &_mesa_texformat_argb8888; /* inefficient but accurate */
225 else
226 return &_mesa_texformat_argb4444;
227
228 case GL_COLOR_INDEX:
229 case GL_COLOR_INDEX1_EXT:
230 case GL_COLOR_INDEX2_EXT:
231 case GL_COLOR_INDEX4_EXT:
232 case GL_COLOR_INDEX8_EXT:
233 case GL_COLOR_INDEX12_EXT:
234 case GL_COLOR_INDEX16_EXT:
235 return &_mesa_texformat_ci8;
236
237 case GL_YCBCR_MESA:
238 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
239 type == GL_UNSIGNED_BYTE)
240 return &_mesa_texformat_ycbcr;
241 else
242 return &_mesa_texformat_ycbcr_rev;
243
244 default:
245 _mesa_problem( ctx, "unexpected format in %s", __FUNCTION__ );
246 return NULL;
247 }
248 }
249
250 static void mach64TexImage1D( GLcontext *ctx, GLenum target, GLint level,
251 GLint internalFormat,
252 GLint width, GLint border,
253 GLenum format, GLenum type, const GLvoid *pixels,
254 const struct gl_pixelstore_attrib *packing,
255 struct gl_texture_object *texObj,
256 struct gl_texture_image *texImage )
257 {
258 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
259 driTextureObject * t = (driTextureObject *) texObj->DriverData;
260
261 if ( t ) {
262 driSwapOutTextureObject( t );
263 }
264 else {
265 t = (driTextureObject *) mach64AllocTexObj(texObj);
266 if (!t) {
267 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
268 return;
269 }
270 }
271
272 /* Note, this will call mach64ChooseTextureFormat */
273 _mesa_store_teximage1d( ctx, target, level, internalFormat,
274 width, border, format, type,
275 pixels, packing, texObj, texImage );
276
277 mmesa->new_state |= MACH64_NEW_TEXTURE;
278 }
279
280 static void mach64TexSubImage1D( GLcontext *ctx,
281 GLenum target,
282 GLint level,
283 GLint xoffset,
284 GLsizei width,
285 GLenum format, GLenum type,
286 const GLvoid *pixels,
287 const struct gl_pixelstore_attrib *packing,
288 struct gl_texture_object *texObj,
289 struct gl_texture_image *texImage )
290 {
291 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
292 driTextureObject * t = (driTextureObject *) texObj->DriverData;
293
294 assert( t ); /* this _should_ be true */
295 if ( t ) {
296 driSwapOutTextureObject( t );
297 }
298 else {
299 t = (driTextureObject *) mach64AllocTexObj(texObj);
300 if (!t) {
301 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
302 return;
303 }
304 }
305
306 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
307 format, type, pixels, packing, texObj,
308 texImage);
309
310 mmesa->new_state |= MACH64_NEW_TEXTURE;
311 }
312
313 static void mach64TexImage2D( GLcontext *ctx, GLenum target, GLint level,
314 GLint internalFormat,
315 GLint width, GLint height, GLint border,
316 GLenum format, GLenum type, const GLvoid *pixels,
317 const struct gl_pixelstore_attrib *packing,
318 struct gl_texture_object *texObj,
319 struct gl_texture_image *texImage )
320 {
321 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
322 driTextureObject * t = (driTextureObject *) texObj->DriverData;
323
324 if ( t ) {
325 driSwapOutTextureObject( t );
326 }
327 else {
328 t = (driTextureObject *) mach64AllocTexObj(texObj);
329 if (!t) {
330 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
331 return;
332 }
333 }
334
335 /* Note, this will call mach64ChooseTextureFormat */
336 _mesa_store_teximage2d( ctx, target, level, internalFormat,
337 width, height, border, format, type, pixels,
338 &ctx->Unpack, texObj, texImage );
339
340 mmesa->new_state |= MACH64_NEW_TEXTURE;
341 }
342
343 static void mach64TexSubImage2D( GLcontext *ctx,
344 GLenum target,
345 GLint level,
346 GLint xoffset, GLint yoffset,
347 GLsizei width, GLsizei height,
348 GLenum format, GLenum type,
349 const GLvoid *pixels,
350 const struct gl_pixelstore_attrib *packing,
351 struct gl_texture_object *texObj,
352 struct gl_texture_image *texImage )
353 {
354 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
355 driTextureObject * t = (driTextureObject *) texObj->DriverData;
356
357 assert( t ); /* this _should_ be true */
358 if ( t ) {
359 driSwapOutTextureObject( t );
360 }
361 else {
362 t = (driTextureObject *) mach64AllocTexObj(texObj);
363 if (!t) {
364 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
365 return;
366 }
367 }
368
369 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
370 height, format, type, pixels, packing, texObj,
371 texImage);
372
373 mmesa->new_state |= MACH64_NEW_TEXTURE;
374 }
375
376 /* ================================================================
377 * Device Driver API texture functions
378 */
379
380 static void mach64DDTexEnv( GLcontext *ctx, GLenum target,
381 GLenum pname, const GLfloat *param )
382 {
383 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
384 #if 0
385 struct gl_texture_unit *texUnit;
386 GLubyte c[4];
387 #endif
388
389 if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
390 fprintf( stderr, "%s( %s )\n",
391 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
392 }
393
394 switch ( pname ) {
395 case GL_TEXTURE_ENV_MODE:
396 FLUSH_BATCH( mmesa );
397 mmesa->new_state |= MACH64_NEW_TEXTURE | MACH64_NEW_ALPHA;
398 break;
399
400 #if 0
401 case GL_TEXTURE_ENV_COLOR:
402 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
403 CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] );
404 CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] );
405 CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] );
406 CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] );
407 mmesa->env_color = mach64PackColor( 32, c[0], c[1], c[2], c[3] );
408 if ( mmesa->setup.constant_color_c != mmesa->env_color ) {
409 FLUSH_BATCH( mmesa );
410 mmesa->setup.constant_color_c = mmesa->env_color;
411
412 mmesa->new_state |= MACH64_NEW_TEXTURE;
413
414 /* More complex multitexture/multipass fallbacks for GL_BLEND
415 * can be done later, but this allows a single pass GL_BLEND
416 * in some cases (ie. Performer town demo).
417 */
418 mmesa->blend_flags &= ~MACH64_BLEND_ENV_COLOR;
419 if ( mmesa->env_color != 0x00000000 &&
420 mmesa->env_color != 0xff000000 &&
421 mmesa->env_color != 0x00ffffff &&
422 mmesa->env_color != 0xffffffff )) {
423 mmesa->blend_flags |= MACH64_BLEND_ENV_COLOR;
424 }
425 }
426 break;
427 #endif
428
429 default:
430 return;
431 }
432 }
433
434 static void mach64DDTexParameter( GLcontext *ctx, GLenum target,
435 struct gl_texture_object *tObj,
436 GLenum pname, const GLfloat *params )
437 {
438 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
439 mach64TexObjPtr t = (mach64TexObjPtr)tObj->DriverData;
440
441 if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
442 fprintf( stderr, "%s( %s )\n",
443 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
444 }
445
446 if ( ( target != GL_TEXTURE_2D ) &&
447 ( target != GL_TEXTURE_1D ) ) {
448 return;
449 }
450
451 if (!t) {
452 t = mach64AllocTexObj(tObj);
453 if (!t) {
454 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexParameter");
455 return;
456 }
457 }
458
459 switch ( pname ) {
460 case GL_TEXTURE_MIN_FILTER:
461 case GL_TEXTURE_MAG_FILTER:
462 if ( t->base.bound ) FLUSH_BATCH( mmesa );
463 mach64SetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
464 break;
465
466 case GL_TEXTURE_WRAP_S:
467 case GL_TEXTURE_WRAP_T:
468 if ( t->base.bound ) FLUSH_BATCH( mmesa );
469 mach64SetTexWrap( t, tObj->WrapS, tObj->WrapT );
470 break;
471
472 case GL_TEXTURE_BORDER_COLOR:
473 if ( t->base.bound ) FLUSH_BATCH( mmesa );
474 mach64SetTexBorderColor( t, tObj->BorderColor );
475 break;
476
477 case GL_TEXTURE_BASE_LEVEL:
478 /* From Radeon/Rage128:
479 * This isn't the most efficient solution but there doesn't appear to
480 * be a nice alternative. Since there's no LOD clamping,
481 * we just have to rely on loading the right subset of mipmap levels
482 * to simulate a clamped LOD.
483 *
484 * For mach64 we're only concerned with the base level
485 * since that's the only texture we upload.
486 */
487 if ( t->base.bound ) FLUSH_BATCH( mmesa );
488 driSwapOutTextureObject( (driTextureObject *) t );
489 break;
490
491 default:
492 return;
493 }
494
495 mmesa->new_state |= MACH64_NEW_TEXTURE;
496 }
497
498 static void mach64DDBindTexture( GLcontext *ctx, GLenum target,
499 struct gl_texture_object *tObj )
500 {
501 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
502 GLint unit = ctx->Texture.CurrentUnit;
503
504 if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
505 fprintf( stderr, "%s( %p ) unit=%d\n",
506 __FUNCTION__, tObj, unit );
507 }
508
509 FLUSH_BATCH( mmesa );
510
511 if ( mmesa->CurrentTexObj[unit] ) {
512 mmesa->CurrentTexObj[unit]->base.bound &= ~(1 << unit);
513 mmesa->CurrentTexObj[unit] = NULL;
514 }
515
516 mmesa->new_state |= MACH64_NEW_TEXTURE;
517 }
518
519 static void mach64DDDeleteTexture( GLcontext *ctx,
520 struct gl_texture_object *tObj )
521 {
522 mach64ContextPtr mmesa = MACH64_CONTEXT(ctx);
523 driTextureObject * t = (driTextureObject *) tObj->DriverData;
524
525 if ( t ) {
526 if ( t->bound && mmesa ) {
527 FLUSH_BATCH( mmesa );
528
529 mmesa->new_state |= MACH64_NEW_TEXTURE;
530 }
531
532 driDestroyTextureObject( t );
533
534 /* Free mipmap images and the texture object itself */
535 _mesa_delete_texture_object(ctx, tObj);
536 }
537 }
538
539 /**
540 * Allocate a new texture object.
541 * Called via ctx->Driver.NewTextureObject.
542 * Note: we could use containment here to 'derive' the driver-specific
543 * texture object from the core mesa gl_texture_object. Not done at this time.
544 */
545 static struct gl_texture_object *
546 mach64NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
547 {
548 struct gl_texture_object *obj;
549 obj = _mesa_new_texture_object(ctx, name, target);
550 mach64AllocTexObj( obj );
551 return obj;
552 }
553
554 void mach64InitTextureFuncs( struct dd_function_table *functions )
555 {
556 functions->TexEnv = mach64DDTexEnv;
557 functions->ChooseTextureFormat = mach64ChooseTextureFormat;
558 functions->TexImage1D = mach64TexImage1D;
559 functions->TexSubImage1D = mach64TexSubImage1D;
560 functions->TexImage2D = mach64TexImage2D;
561 functions->TexSubImage2D = mach64TexSubImage2D;
562 functions->TexParameter = mach64DDTexParameter;
563 functions->BindTexture = mach64DDBindTexture;
564 functions->NewTextureObject = mach64NewTextureObject;
565 functions->DeleteTexture = mach64DDDeleteTexture;
566 functions->IsTextureResident = driIsTextureResident;
567
568 functions->UpdateTexturePalette = NULL;
569 functions->ActiveTexture = NULL;
570 functions->PrioritizeTexture = NULL;
571
572 driInitTextureFormats();
573 }