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