1 /* -*- mode: c; c-basic-offset: 3 -*- */
3 * Copyright 2000 Gareth Hughes
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:
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
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.
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * José Fonseca <j_r_fonseca@yahoo.co.uk>
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"
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"
50 static void mach64SetTexWrap( mach64TexObjPtr t
,
51 GLenum swrap
, GLenum twrap
)
55 case GL_CLAMP_TO_EDGE
:
56 case GL_CLAMP_TO_BORDER
:
66 case GL_CLAMP_TO_EDGE
:
67 case GL_CLAMP_TO_BORDER
:
76 static void mach64SetTexFilter( mach64TexObjPtr t
,
77 GLenum minf
, GLenum magf
)
81 case GL_NEAREST_MIPMAP_NEAREST
:
82 case GL_NEAREST_MIPMAP_LINEAR
:
83 t
->BilinearMin
= GL_FALSE
;
86 case GL_LINEAR_MIPMAP_NEAREST
:
87 case GL_LINEAR_MIPMAP_LINEAR
:
88 t
->BilinearMin
= GL_TRUE
;
94 t
->BilinearMag
= GL_FALSE
;
97 t
->BilinearMag
= GL_TRUE
;
102 static void mach64SetTexBorderColor( mach64TexObjPtr t
, const GLfloat c
[4] )
105 GLuint border
= mach64PackColor( 4, c
[0], c
[1], c
[2], c
[3] );
110 static mach64TexObjPtr
111 mach64AllocTexObj( struct gl_texture_object
*texObj
)
115 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
)
116 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, texObj
);
118 t
= (mach64TexObjPtr
) CALLOC_STRUCT( mach64_texture_object
);
119 texObj
->DriverData
= t
;
123 /* Initialize non-image-dependent parts of the state:
125 t
->base
.tObj
= texObj
;
126 t
->base
.dirty_images
[0] = (1 << 0);
130 make_empty_list( (driTextureObject
*) t
);
132 mach64SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
133 mach64SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
134 mach64SetTexBorderColor( t
, texObj
->BorderColor
);
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
)
145 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
149 switch ( internalFormat
) {
155 case GL_COMPRESSED_ALPHA
:
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
:
168 case GL_COMPRESSED_RGBA
:
169 if (mmesa
->mach64Screen
->cpp
== 4)
170 return &_mesa_texformat_argb8888
;
172 return &_mesa_texformat_argb4444
;
175 if (mmesa
->mach64Screen
->cpp
== 4)
176 return &_mesa_texformat_argb8888
;
178 return &_mesa_texformat_argb1555
;
185 if (mmesa
->mach64Screen
->cpp
== 4)
186 return &_mesa_texformat_argb8888
;
188 return &_mesa_texformat_argb4444
;
199 case GL_COMPRESSED_RGB
:
200 if (mmesa
->mach64Screen
->cpp
== 4)
201 return &_mesa_texformat_argb8888
;
203 return &_mesa_texformat_rgb565
;
211 case GL_COMPRESSED_LUMINANCE
:
212 if (mmesa
->mach64Screen
->cpp
== 4)
213 return &_mesa_texformat_argb8888
; /* inefficient but accurate */
215 return &_mesa_texformat_argb1555
;
222 case GL_COMPRESSED_INTENSITY
:
223 if (mmesa
->mach64Screen
->cpp
== 4)
224 return &_mesa_texformat_argb8888
; /* inefficient but accurate */
226 return &_mesa_texformat_argb4444
;
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
;
238 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
239 type
== GL_UNSIGNED_BYTE
)
240 return &_mesa_texformat_ycbcr
;
242 return &_mesa_texformat_ycbcr_rev
;
245 _mesa_problem( ctx
, "unexpected format in %s", __FUNCTION__
);
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
)
258 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
259 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
262 driSwapOutTextureObject( t
);
265 t
= (driTextureObject
*) mach64AllocTexObj(texObj
);
267 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
272 /* Note, this will call mach64ChooseTextureFormat */
273 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
274 width
, border
, format
, type
,
275 pixels
, packing
, texObj
, texImage
);
277 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
280 static void mach64TexSubImage1D( GLcontext
*ctx
,
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
)
291 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
292 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
294 assert( t
); /* this _should_ be true */
296 driSwapOutTextureObject( t
);
299 t
= (driTextureObject
*) mach64AllocTexObj(texObj
);
301 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
306 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
307 format
, type
, pixels
, packing
, texObj
,
310 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
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
)
321 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
322 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
325 driSwapOutTextureObject( t
);
328 t
= (driTextureObject
*) mach64AllocTexObj(texObj
);
330 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
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
);
340 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
343 static void mach64TexSubImage2D( GLcontext
*ctx
,
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
)
354 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
355 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
357 assert( t
); /* this _should_ be true */
359 driSwapOutTextureObject( t
);
362 t
= (driTextureObject
*) mach64AllocTexObj(texObj
);
364 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
369 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
370 height
, format
, type
, pixels
, packing
, texObj
,
373 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
376 /* ================================================================
377 * Device Driver API texture functions
380 static void mach64DDTexEnv( GLcontext
*ctx
, GLenum target
,
381 GLenum pname
, const GLfloat
*param
)
383 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
385 struct gl_texture_unit
*texUnit
;
389 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
390 fprintf( stderr
, "%s( %s )\n",
391 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
395 case GL_TEXTURE_ENV_MODE
:
396 FLUSH_BATCH( mmesa
);
397 mmesa
->new_state
|= MACH64_NEW_TEXTURE
| MACH64_NEW_ALPHA
;
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
;
412 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
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).
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
;
434 static void mach64DDTexParameter( GLcontext
*ctx
, GLenum target
,
435 struct gl_texture_object
*tObj
,
436 GLenum pname
, const GLfloat
*params
)
438 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
439 mach64TexObjPtr t
= (mach64TexObjPtr
)tObj
->DriverData
;
441 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
442 fprintf( stderr
, "%s( %s )\n",
443 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
446 if ( ( target
!= GL_TEXTURE_2D
) &&
447 ( target
!= GL_TEXTURE_1D
) ) {
452 t
= mach64AllocTexObj(tObj
);
454 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexParameter");
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
);
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
);
472 case GL_TEXTURE_BORDER_COLOR
:
473 if ( t
->base
.bound
) FLUSH_BATCH( mmesa
);
474 mach64SetTexBorderColor( t
, tObj
->BorderColor
);
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.
484 * For mach64 we're only concerned with the base level
485 * since that's the only texture we upload.
487 if ( t
->base
.bound
) FLUSH_BATCH( mmesa
);
488 driSwapOutTextureObject( (driTextureObject
*) t
);
495 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
498 static void mach64DDBindTexture( GLcontext
*ctx
, GLenum target
,
499 struct gl_texture_object
*tObj
)
501 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
502 GLint unit
= ctx
->Texture
.CurrentUnit
;
504 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
505 fprintf( stderr
, "%s( %p ) unit=%d\n",
506 __FUNCTION__
, tObj
, unit
);
509 FLUSH_BATCH( mmesa
);
511 if ( mmesa
->CurrentTexObj
[unit
] ) {
512 mmesa
->CurrentTexObj
[unit
]->base
.bound
&= ~(1 << unit
);
513 mmesa
->CurrentTexObj
[unit
] = NULL
;
516 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
519 static void mach64DDDeleteTexture( GLcontext
*ctx
,
520 struct gl_texture_object
*tObj
)
522 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
523 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
526 if ( t
->bound
&& mmesa
) {
527 FLUSH_BATCH( mmesa
);
529 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
532 driDestroyTextureObject( t
);
534 /* Free mipmap images and the texture object itself */
535 _mesa_delete_texture_object(ctx
, tObj
);
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.
545 static struct gl_texture_object
*
546 mach64NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
548 struct gl_texture_object
*obj
;
549 obj
= _mesa_new_texture_object(ctx
, name
, target
);
550 mach64AllocTexObj( obj
);
554 void mach64InitTextureFuncs( struct dd_function_table
*functions
)
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
;
568 functions
->UpdateTexturePalette
= NULL
;
569 functions
->ActiveTexture
= NULL
;
570 functions
->PrioritizeTexture
= NULL
;
572 driInitTextureFormats();