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