1 /* $XFree86$ */ /* -*- 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"
41 #include "simple_list.h"
44 #include "texformat.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
, GLubyte 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
);
122 /* Initialize non-image-dependent parts of the state:
130 make_empty_list( t
);
132 mach64SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
133 /*mach64SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );*/
134 mach64SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
135 mach64SetTexBorderColor( t
, texObj
->_BorderChan
);
141 /* Called by the _mesa_store_teximage[123]d() functions. */
142 static const struct gl_texture_format
*
143 mach64ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
144 GLenum format
, GLenum type
)
146 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
150 switch ( internalFormat
) {
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
:
167 if (mmesa
->mach64Screen
->cpp
== 4)
168 return &_mesa_texformat_argb8888
;
170 return &_mesa_texformat_argb4444
;
173 if (mmesa
->mach64Screen
->cpp
== 4)
174 return &_mesa_texformat_argb8888
;
176 return &_mesa_texformat_argb1555
;
183 if (mmesa
->mach64Screen
->cpp
== 4)
184 return &_mesa_texformat_argb8888
;
186 return &_mesa_texformat_argb4444
;
197 if (mmesa
->mach64Screen
->cpp
== 4)
198 return &_mesa_texformat_argb8888
;
200 return &_mesa_texformat_rgb565
;
208 if (mmesa
->mach64Screen
->cpp
== 4)
209 return &_mesa_texformat_argb8888
; /* inefficient but accurate */
211 return &_mesa_texformat_argb1555
;
218 if (mmesa
->mach64Screen
->cpp
== 4)
219 return &_mesa_texformat_argb8888
; /* inefficient but accurate */
221 return &_mesa_texformat_argb4444
;
224 case GL_COLOR_INDEX1_EXT
:
225 case GL_COLOR_INDEX2_EXT
:
226 case GL_COLOR_INDEX4_EXT
:
227 case GL_COLOR_INDEX8_EXT
:
228 case GL_COLOR_INDEX12_EXT
:
229 case GL_COLOR_INDEX16_EXT
:
230 return &_mesa_texformat_ci8
;
233 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
234 type
== GL_UNSIGNED_BYTE
)
235 return &_mesa_texformat_ycbcr
;
237 return &_mesa_texformat_ycbcr_rev
;
240 _mesa_problem( ctx
, "unexpected format in %s", __FUNCTION__
);
245 static void mach64TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
246 GLint internalFormat
,
247 GLint width
, GLint border
,
248 GLenum format
, GLenum type
, const GLvoid
*pixels
,
249 const struct gl_pixelstore_attrib
*packing
,
250 struct gl_texture_object
*texObj
,
251 struct gl_texture_image
*texImage
)
253 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
254 mach64TexObjPtr t
= (mach64TexObjPtr
) texObj
->DriverData
;
257 mach64SwapOutTexObj( mmesa
, t
);
260 t
= mach64AllocTexObj(texObj
);
262 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
265 texObj
->DriverData
= t
;
268 /* Note, this will call mach64ChooseTextureFormat */
269 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
270 width
, border
, format
, type
,
271 pixels
, packing
, texObj
, texImage
);
273 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
276 static void mach64TexSubImage1D( GLcontext
*ctx
,
281 GLenum format
, GLenum type
,
282 const GLvoid
*pixels
,
283 const struct gl_pixelstore_attrib
*packing
,
284 struct gl_texture_object
*texObj
,
285 struct gl_texture_image
*texImage
)
287 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
288 mach64TexObjPtr t
= (mach64TexObjPtr
) texObj
->DriverData
;
290 assert( t
); /* this _should_ be true */
292 mach64SwapOutTexObj( mmesa
, t
);
295 t
= mach64AllocTexObj(texObj
);
297 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
300 texObj
->DriverData
= t
;
303 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
304 format
, type
, pixels
, packing
, texObj
,
307 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
310 static void mach64TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
311 GLint internalFormat
,
312 GLint width
, GLint height
, GLint border
,
313 GLenum format
, GLenum type
, const GLvoid
*pixels
,
314 const struct gl_pixelstore_attrib
*packing
,
315 struct gl_texture_object
*texObj
,
316 struct gl_texture_image
*texImage
)
318 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
319 mach64TexObjPtr t
= (mach64TexObjPtr
) texObj
->DriverData
;
322 mach64SwapOutTexObj( mmesa
, t
);
325 t
= mach64AllocTexObj(texObj
);
327 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
330 texObj
->DriverData
= t
;
333 /* Note, this will call mach64ChooseTextureFormat */
334 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
335 width
, height
, border
, format
, type
, pixels
,
336 &ctx
->Unpack
, texObj
, texImage
);
338 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
341 static void mach64TexSubImage2D( GLcontext
*ctx
,
344 GLint xoffset
, GLint yoffset
,
345 GLsizei width
, GLsizei height
,
346 GLenum format
, GLenum type
,
347 const GLvoid
*pixels
,
348 const struct gl_pixelstore_attrib
*packing
,
349 struct gl_texture_object
*texObj
,
350 struct gl_texture_image
*texImage
)
352 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
353 mach64TexObjPtr t
= (mach64TexObjPtr
) texObj
->DriverData
;
355 assert( t
); /* this _should_ be true */
357 mach64SwapOutTexObj( mmesa
, t
);
360 t
= mach64AllocTexObj(texObj
);
362 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
365 texObj
->DriverData
= t
;
368 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
369 height
, format
, type
, pixels
, packing
, texObj
,
372 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
375 /* Due to the way we must program texture state into the Rage Pro,
376 * we must leave these calculations to the absolute last minute.
378 void mach64EmitTexStateLocked( mach64ContextPtr mmesa
,
382 drm_mach64_sarea_t
*sarea
= mmesa
->sarea
;
383 drm_mach64_context_regs_t
*regs
= &(mmesa
->setup
);
385 /* for multitex, both textures must be local or AGP */
387 assert(t0
->heap
== t1
->heap
);
390 if (t0
->heap
== MACH64_CARD_HEAP
) {
391 #if ENABLE_PERF_BOXES
392 mmesa
->c_texsrc_card
++;
394 mmesa
->setup
.tex_cntl
&= ~MACH64_TEX_SRC_AGP
;
396 #if ENABLE_PERF_BOXES
397 mmesa
->c_texsrc_agp
++;
399 mmesa
->setup
.tex_cntl
|= MACH64_TEX_SRC_AGP
;
401 mmesa
->setup
.tex_offset
= t0
->offset
;
405 mmesa
->setup
.secondary_tex_off
= t1
->offset
;
408 memcpy( &sarea
->context_state
.tex_size_pitch
, ®s
->tex_size_pitch
,
409 MACH64_NR_TEXTURE_REGS
* sizeof(GLuint
) );
413 /* ================================================================
414 * Device Driver API texture functions
417 static void mach64DDTexEnv( GLcontext
*ctx
, GLenum target
,
418 GLenum pname
, const GLfloat
*param
)
420 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
422 struct gl_texture_unit
*texUnit
;
426 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
427 fprintf( stderr
, "%s( %s )\n",
428 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
432 case GL_TEXTURE_ENV_MODE
:
433 FLUSH_BATCH( mmesa
);
434 mmesa
->new_state
|= MACH64_NEW_TEXTURE
| MACH64_NEW_ALPHA
;
438 case GL_TEXTURE_ENV_COLOR
:
439 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
440 CLAMPED_FLOAT_TO_UBYTE( c
[0], texUnit
->EnvColor
[0] );
441 CLAMPED_FLOAT_TO_UBYTE( c
[1], texUnit
->EnvColor
[1] );
442 CLAMPED_FLOAT_TO_UBYTE( c
[2], texUnit
->EnvColor
[2] );
443 CLAMPED_FLOAT_TO_UBYTE( c
[3], texUnit
->EnvColor
[3] );
444 mmesa
->env_color
= mach64PackColor( 32, c
[0], c
[1], c
[2], c
[3] );
445 if ( mmesa
->setup
.constant_color_c
!= mmesa
->env_color
) {
446 FLUSH_BATCH( mmesa
);
447 mmesa
->setup
.constant_color_c
= mmesa
->env_color
;
449 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
451 /* More complex multitexture/multipass fallbacks for GL_BLEND
452 * can be done later, but this allows a single pass GL_BLEND
453 * in some cases (ie. Performer town demo).
455 mmesa
->blend_flags
&= ~MACH64_BLEND_ENV_COLOR
;
456 if ( mmesa
->env_color
!= 0x00000000 &&
457 mmesa
->env_color
!= 0xff000000 &&
458 mmesa
->env_color
!= 0x00ffffff &&
459 mmesa
->env_color
!= 0xffffffff )) {
460 mmesa
->blend_flags
|= MACH64_BLEND_ENV_COLOR
;
471 static void mach64DDTexParameter( GLcontext
*ctx
, GLenum target
,
472 struct gl_texture_object
*tObj
,
473 GLenum pname
, const GLfloat
*params
)
475 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
476 mach64TexObjPtr t
= (mach64TexObjPtr
)tObj
->DriverData
;
478 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
479 fprintf( stderr
, "%s( %s )\n",
480 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
483 if ( ( target
!= GL_TEXTURE_2D
) &&
484 ( target
!= GL_TEXTURE_1D
) ) {
489 t
= mach64AllocTexObj(tObj
);
491 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexParameter");
494 tObj
->DriverData
= t
;
498 case GL_TEXTURE_MIN_FILTER
:
499 case GL_TEXTURE_MAG_FILTER
:
500 if ( t
->bound
) FLUSH_BATCH( mmesa
);
501 mach64SetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
504 case GL_TEXTURE_WRAP_S
:
505 case GL_TEXTURE_WRAP_T
:
506 if ( t
->bound
) FLUSH_BATCH( mmesa
);
507 mach64SetTexWrap( t
, tObj
->WrapS
, tObj
->WrapT
);
510 case GL_TEXTURE_BORDER_COLOR
:
511 if ( t
->bound
) FLUSH_BATCH( mmesa
);
512 mach64SetTexBorderColor( t
, tObj
->_BorderChan
);
515 case GL_TEXTURE_BASE_LEVEL
:
516 /* From Radeon/Rage128:
517 * This isn't the most efficient solution but there doesn't appear to
518 * be a nice alternative. Since there's no LOD clamping,
519 * we just have to rely on loading the right subset of mipmap levels
520 * to simulate a clamped LOD.
522 * For mach64 we're only concerned with the base level
523 * since that's the only texture we upload.
525 if ( t
->bound
) FLUSH_BATCH( mmesa
);
526 mach64SwapOutTexObj( mmesa
, t
);
533 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
536 static void mach64DDBindTexture( GLcontext
*ctx
, GLenum target
,
537 struct gl_texture_object
*tObj
)
539 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
540 GLint unit
= ctx
->Texture
.CurrentUnit
;
542 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
543 fprintf( stderr
, "%s( %p ) unit=%d\n",
544 __FUNCTION__
, tObj
, unit
);
547 FLUSH_BATCH( mmesa
);
549 if ( mmesa
->CurrentTexObj
[unit
] ) {
550 mmesa
->CurrentTexObj
[unit
]->bound
&= ~(unit
+1);
551 mmesa
->CurrentTexObj
[unit
] = NULL
;
554 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
557 static void mach64DDDeleteTexture( GLcontext
*ctx
,
558 struct gl_texture_object
*tObj
)
560 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
561 mach64TexObjPtr t
= (mach64TexObjPtr
)tObj
->DriverData
;
564 if ( t
->bound
&& mmesa
) {
565 FLUSH_BATCH( mmesa
);
567 mmesa
->CurrentTexObj
[t
->bound
-1] = 0;
568 mmesa
->new_state
|= MACH64_NEW_TEXTURE
;
571 mach64DestroyTexObj( mmesa
, t
);
572 tObj
->DriverData
= NULL
;
573 /* Free mipmap images and the texture object itself */
574 _mesa_delete_texture_object(ctx
, tObj
);
579 static GLboolean
mach64DDIsTextureResident( GLcontext
*ctx
,
580 struct gl_texture_object
*tObj
)
582 mach64TexObjPtr t
= (mach64TexObjPtr
)tObj
->DriverData
;
584 return ( t
&& t
->memBlock
);
588 void mach64InitTextureFuncs( struct dd_function_table
*functions
)
590 functions
->TexEnv
= mach64DDTexEnv
;
591 functions
->ChooseTextureFormat
= mach64ChooseTextureFormat
;
592 functions
->TexImage1D
= mach64TexImage1D
;
593 functions
->TexSubImage1D
= mach64TexSubImage1D
;
594 functions
->TexImage2D
= mach64TexImage2D
;
595 functions
->TexSubImage2D
= mach64TexSubImage2D
;
596 functions
->TexImage3D
= _mesa_store_teximage3d
;
597 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
598 functions
->CopyTexImage1D
= _swrast_copy_teximage1d
;
599 functions
->CopyTexImage2D
= _swrast_copy_teximage2d
;
600 functions
->CopyTexSubImage1D
= _swrast_copy_texsubimage1d
;
601 functions
->CopyTexSubImage2D
= _swrast_copy_texsubimage2d
;
602 functions
->CopyTexSubImage3D
= _swrast_copy_texsubimage3d
;
603 functions
->TexParameter
= mach64DDTexParameter
;
604 functions
->BindTexture
= mach64DDBindTexture
;
605 functions
->DeleteTexture
= mach64DDDeleteTexture
;
606 functions
->UpdateTexturePalette
= NULL
;
607 functions
->ActiveTexture
= NULL
;
608 functions
->IsTextureResident
= mach64DDIsTextureResident
;
609 functions
->PrioritizeTexture
= NULL
;