1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v 1.9 2003/09/24 02:43:12 dawes Exp $ */
2 /**************************************************************************
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Kevin E. Martin <martin@valinux.com>
34 * Gareth Hughes <gareth@valinux.com>
35 * Keith Whitwell <keith@tungstengraphics.com>
39 #include "api_arrayelt.h"
41 #include "simple_list.h"
44 #include "extensions.h"
46 #include "swrast/swrast.h"
47 #include "swrast_setup/swrast_setup.h"
48 #include "array_cache/acache.h"
51 #include "tnl/t_pipeline.h"
53 #include "drivers/common/driverfuncs.h"
55 #include "radeon_context.h"
56 #include "radeon_ioctl.h"
57 #include "radeon_state.h"
58 #include "radeon_span.h"
59 #include "radeon_tex.h"
60 #include "radeon_swtcl.h"
61 #include "radeon_tcl.h"
62 #include "radeon_vtxfmt.h"
63 #include "radeon_maos.h"
65 #define DRIVER_DATE "20041007"
69 #include "xmlpool.h" /* for symbolic values of enum-type options */
71 int RADEON_DEBUG
= (0);
75 /* Return the width and height of the given buffer.
77 static void radeonGetBufferSize( GLframebuffer
*buffer
,
78 GLuint
*width
, GLuint
*height
)
80 GET_CURRENT_CONTEXT(ctx
);
81 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
83 LOCK_HARDWARE( rmesa
);
84 *width
= rmesa
->dri
.drawable
->w
;
85 *height
= rmesa
->dri
.drawable
->h
;
86 UNLOCK_HARDWARE( rmesa
);
89 /* Return various strings for glGetString().
91 static const GLubyte
*radeonGetString( GLcontext
*ctx
, GLenum name
)
93 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
94 static char buffer
[128];
96 GLuint agp_mode
= rmesa
->radeonScreen
->IsPCI
? 0 :
97 rmesa
->radeonScreen
->AGPMode
;
101 return (GLubyte
*)"Tungsten Graphics, Inc.";
104 offset
= driGetRendererString( buffer
, "Radeon", DRIVER_DATE
,
107 sprintf( & buffer
[ offset
], " %sTCL",
108 !(rmesa
->TclFallback
& RADEON_TCL_FALLBACK_TCL_DISABLE
)
111 return (GLubyte
*)buffer
;
119 /* Extension strings exported by the R100 driver.
121 static const char * const card_extensions
[] =
123 "GL_ARB_multisample",
124 "GL_ARB_multitexture",
125 "GL_ARB_texture_border_clamp",
126 "GL_ARB_texture_compression",
127 "GL_ARB_texture_env_add",
128 "GL_ARB_texture_env_combine",
129 "GL_ARB_texture_env_crossbar",
130 "GL_ARB_texture_env_dot3",
131 "GL_ARB_texture_mirrored_repeat",
132 "GL_EXT_blend_logic_op",
133 "GL_EXT_blend_subtract",
134 "GL_EXT_secondary_color",
135 "GL_EXT_stencil_wrap",
136 "GL_EXT_texture_edge_clamp",
137 "GL_EXT_texture_env_combine",
138 "GL_EXT_texture_env_dot3",
139 "GL_EXT_texture_filter_anisotropic",
140 "GL_EXT_texture_lod_bias",
141 "GL_EXT_texture_mirror_clamp",
142 "GL_ATI_texture_env_combine3",
143 "GL_ATI_texture_mirror_once",
144 "GL_MESA_ycbcr_texture",
145 "GL_NV_blend_square",
146 "GL_SGIS_generate_mipmap",
150 extern const struct tnl_pipeline_stage _radeon_texrect_stage
;
151 extern const struct tnl_pipeline_stage _radeon_render_stage
;
152 extern const struct tnl_pipeline_stage _radeon_tcl_stage
;
154 static const struct tnl_pipeline_stage
*radeon_pipeline
[] = {
156 /* Try and go straight to t&l
160 /* Catch any t&l fallbacks
162 &_tnl_vertex_transform_stage
,
163 &_tnl_normal_transform_stage
,
164 &_tnl_lighting_stage
,
165 &_tnl_fog_coordinate_stage
,
167 &_tnl_texture_transform_stage
,
169 /* Scale texture rectangle to 0..1.
171 &_radeon_texrect_stage
,
173 &_radeon_render_stage
,
174 &_tnl_render_stage
, /* FALLBACK: */
180 /* Initialize the driver's misc functions.
182 static void radeonInitDriverFuncs( struct dd_function_table
*functions
)
184 functions
->GetBufferSize
= radeonGetBufferSize
;
185 functions
->ResizeBuffers
= _swrast_alloc_buffers
;
186 functions
->GetString
= radeonGetString
;
189 static const struct dri_debug_control debug_control
[] =
191 { "fall", DEBUG_FALLBACKS
},
192 { "tex", DEBUG_TEXTURE
},
193 { "ioctl", DEBUG_IOCTL
},
194 { "prim", DEBUG_PRIMS
},
195 { "vert", DEBUG_VERTS
},
196 { "state", DEBUG_STATE
},
197 { "code", DEBUG_CODEGEN
},
198 { "vfmt", DEBUG_VFMT
},
199 { "vtxf", DEBUG_VFMT
},
200 { "verb", DEBUG_VERBOSE
},
201 { "dri", DEBUG_DRI
},
202 { "dma", DEBUG_DMA
},
203 { "san", DEBUG_SANITY
},
209 get_ust_nop( int64_t * ust
)
216 /* Create the device specific context.
219 radeonCreateContext( const __GLcontextModes
*glVisual
,
220 __DRIcontextPrivate
*driContextPriv
,
221 void *sharedContextPrivate
)
223 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
224 radeonScreenPtr screen
= (radeonScreenPtr
)(sPriv
->private);
225 struct dd_function_table functions
;
226 radeonContextPtr rmesa
;
227 GLcontext
*ctx
, *shareCtx
;
229 int tcl_mode
, fthrottle_mode
;
232 assert(driContextPriv
);
235 /* Allocate the Radeon context */
236 rmesa
= (radeonContextPtr
) CALLOC( sizeof(*rmesa
) );
240 /* Parse configuration files.
241 * Do this here so that initialMaxAnisotropy is set before we create
242 * the default textures.
244 driParseConfigFiles (&rmesa
->optionCache
, &screen
->optionCache
,
245 screen
->driScreen
->myNum
, "radeon");
246 rmesa
->initialMaxAnisotropy
= driQueryOptionf(&rmesa
->optionCache
,
247 "def_max_anisotropy");
249 /* Init default driver functions then plug in our Radeon-specific functions
250 * (the texture functions are especially important)
252 _mesa_init_driver_functions( &functions
);
253 radeonInitDriverFuncs( &functions
);
254 radeonInitTextureFuncs( &functions
);
256 /* Allocate the Mesa context */
257 if (sharedContextPrivate
)
258 shareCtx
= ((radeonContextPtr
) sharedContextPrivate
)->glCtx
;
261 rmesa
->glCtx
= _mesa_create_context(glVisual
, shareCtx
,
262 &functions
, (void *) rmesa
);
267 driContextPriv
->driverPrivate
= rmesa
;
269 /* Init radeon context data */
270 rmesa
->dri
.context
= driContextPriv
;
271 rmesa
->dri
.screen
= sPriv
;
272 rmesa
->dri
.drawable
= NULL
; /* Set by XMesaMakeCurrent */
273 rmesa
->dri
.hwContext
= driContextPriv
->hHWContext
;
274 rmesa
->dri
.hwLock
= &sPriv
->pSAREA
->lock
;
275 rmesa
->dri
.fd
= sPriv
->fd
;
276 rmesa
->dri
.drmMinor
= sPriv
->drmMinor
;
278 rmesa
->radeonScreen
= screen
;
279 rmesa
->sarea
= (drm_radeon_sarea_t
*)((GLubyte
*)sPriv
->pSAREA
+
280 screen
->sarea_priv_offset
);
283 rmesa
->dma
.buf0_address
= rmesa
->radeonScreen
->buffers
->list
[0].address
;
285 (void) memset( rmesa
->texture_heaps
, 0, sizeof( rmesa
->texture_heaps
) );
286 make_empty_list( & rmesa
->swapped
);
288 rmesa
->nr_heaps
= screen
->numTexHeaps
;
289 for ( i
= 0 ; i
< rmesa
->nr_heaps
; i
++ ) {
290 rmesa
->texture_heaps
[i
] = driCreateTextureHeap( i
, rmesa
,
293 RADEON_NR_TEX_REGIONS
,
294 (drmTextureRegionPtr
)rmesa
->sarea
->tex_list
[i
],
295 & rmesa
->sarea
->tex_age
[i
],
297 sizeof( radeonTexObj
),
298 (destroy_texture_object_t
*) radeonDestroyTexObj
);
300 driSetTextureSwapCounterLocation( rmesa
->texture_heaps
[i
],
301 & rmesa
->c_textureSwaps
);
303 rmesa
->texture_depth
= driQueryOptioni (&rmesa
->optionCache
,
305 if (rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FB
)
306 rmesa
->texture_depth
= ( screen
->cpp
== 4 ) ?
307 DRI_CONF_TEXTURE_DEPTH_32
: DRI_CONF_TEXTURE_DEPTH_16
;
309 rmesa
->swtcl
.RenderIndex
= ~0;
310 rmesa
->hw
.all_dirty
= GL_TRUE
;
312 /* Set the maximum texture size small enough that we can guarentee that
313 * all texture units can bind a maximal texture and have them both in
314 * texturable memory at once.
318 ctx
->Const
.MaxTextureUnits
= 2;
319 ctx
->Const
.MaxTextureImageUnits
= 2;
320 ctx
->Const
.MaxTextureCoordUnits
= 2;
322 driCalculateMaxTextureLevels( rmesa
->texture_heaps
,
326 11, /* max 2D texture size is 2048x2048 */
327 0, /* 3D textures unsupported. */
328 0, /* cube textures unsupported. */
329 11, /* max rect texture size is 2048x2048. */
333 ctx
->Const
.MaxTextureMaxAnisotropy
= 16.0;
337 ctx
->Const
.MinPointSize
= 1.0;
338 ctx
->Const
.MinPointSizeAA
= 1.0;
339 ctx
->Const
.MaxPointSize
= 1.0;
340 ctx
->Const
.MaxPointSizeAA
= 1.0;
342 ctx
->Const
.MinLineWidth
= 1.0;
343 ctx
->Const
.MinLineWidthAA
= 1.0;
344 ctx
->Const
.MaxLineWidth
= 10.0;
345 ctx
->Const
.MaxLineWidthAA
= 10.0;
346 ctx
->Const
.LineWidthGranularity
= 0.0625;
348 /* Set maxlocksize (and hence vb size) small enough to avoid
349 * fallbacks in radeon_tcl.c. ie. guarentee that all vertices can
350 * fit in a single dma buffer for indexed rendering of quad strips,
353 ctx
->Const
.MaxArrayLockSize
=
354 MIN2( ctx
->Const
.MaxArrayLockSize
,
355 RADEON_BUFFER_SIZE
/ RADEON_MAX_TCL_VERTSIZE
);
359 /* Initialize the software rasterizer and helper modules.
361 _swrast_CreateContext( ctx
);
362 _ac_CreateContext( ctx
);
363 _tnl_CreateContext( ctx
);
364 _swsetup_CreateContext( ctx
);
365 _ae_create_context( ctx
);
367 /* Install the customized pipeline:
369 _tnl_destroy_pipeline( ctx
);
370 _tnl_install_pipeline( ctx
, radeon_pipeline
);
371 ctx
->Driver
.FlushVertices
= radeonFlushVertices
;
373 /* Try and keep materials and vertices separate:
375 _tnl_isolate_materials( ctx
, GL_TRUE
);
378 /* _mesa_allow_light_in_model( ctx, GL_FALSE ); */
380 /* Try and keep materials and vertices separate:
382 _tnl_isolate_materials( ctx
, GL_TRUE
);
385 /* Configure swrast and T&L to match hardware characteristics:
387 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
388 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
389 _tnl_allow_pixel_fog( ctx
, GL_FALSE
);
390 _tnl_allow_vertex_fog( ctx
, GL_TRUE
);
393 _math_matrix_ctr( &rmesa
->TexGenMatrix
[0] );
394 _math_matrix_ctr( &rmesa
->TexGenMatrix
[1] );
395 _math_matrix_ctr( &rmesa
->tmpmat
);
396 _math_matrix_set_identity( &rmesa
->TexGenMatrix
[0] );
397 _math_matrix_set_identity( &rmesa
->TexGenMatrix
[1] );
398 _math_matrix_set_identity( &rmesa
->tmpmat
);
400 driInitExtensions( ctx
, card_extensions
, GL_TRUE
);
401 if (rmesa
->glCtx
->Mesa_DXTn
) {
402 _mesa_enable_extension( ctx
, "GL_EXT_texture_compression_s3tc" );
403 _mesa_enable_extension( ctx
, "GL_S3_s3tc" );
405 else if (driQueryOptionb (&rmesa
->optionCache
, "force_s3tc_enable")) {
406 _mesa_enable_extension( ctx
, "GL_EXT_texture_compression_s3tc" );
409 if (rmesa
->dri
.drmMinor
>= 9)
410 _mesa_enable_extension( ctx
, "GL_NV_texture_rectangle");
412 /* XXX these should really go right after _mesa_init_driver_functions() */
413 radeonInitIoctlFuncs( ctx
);
414 radeonInitStateFuncs( ctx
);
415 radeonInitSpanFuncs( ctx
);
416 radeonInitState( rmesa
);
417 radeonInitSwtcl( ctx
);
419 _mesa_vector4f_alloc( &rmesa
->tcl
.ObjClean
, 0,
420 ctx
->Const
.MaxArrayLockSize
, 32 );
422 fthrottle_mode
= driQueryOptioni(&rmesa
->optionCache
, "fthrottle_mode");
423 rmesa
->iw
.irq_seq
= -1;
424 rmesa
->irqsEmitted
= 0;
425 rmesa
->do_irqs
= (rmesa
->radeonScreen
->irq
!= 0 &&
426 fthrottle_mode
== DRI_CONF_FTHROTTLE_IRQS
);
428 rmesa
->do_usleeps
= (fthrottle_mode
== DRI_CONF_FTHROTTLE_USLEEPS
);
430 rmesa
->vblank_flags
= (rmesa
->radeonScreen
->irq
!= 0)
431 ? driGetDefaultVBlankFlags(&rmesa
->optionCache
) : VBLANK_FLAG_NO_IRQ
;
433 rmesa
->get_ust
= (PFNGLXGETUSTPROC
) glXGetProcAddress( (const GLubyte
*) "__glXGetUST" );
434 if ( rmesa
->get_ust
== NULL
) {
435 rmesa
->get_ust
= get_ust_nop
;
437 (*rmesa
->get_ust
)( & rmesa
->swap_ust
);
441 RADEON_DEBUG
= driParseDebugString( getenv( "RADEON_DEBUG" ),
445 tcl_mode
= driQueryOptioni(&rmesa
->optionCache
, "tcl_mode");
446 if (driQueryOptionb(&rmesa
->optionCache
, "no_rast")) {
447 fprintf(stderr
, "disabling 3D acceleration\n");
448 FALLBACK(rmesa
, RADEON_FALLBACK_DISABLE
, 1);
449 } else if (tcl_mode
== DRI_CONF_TCL_SW
||
450 !(rmesa
->radeonScreen
->chipset
& RADEON_CHIPSET_TCL
)) {
451 if (rmesa
->radeonScreen
->chipset
& RADEON_CHIPSET_TCL
) {
452 rmesa
->radeonScreen
->chipset
&= ~RADEON_CHIPSET_TCL
;
453 fprintf(stderr
, "Disabling HW TCL support\n");
455 TCL_FALLBACK(rmesa
->glCtx
, RADEON_TCL_FALLBACK_TCL_DISABLE
, 1);
458 if (rmesa
->radeonScreen
->chipset
& RADEON_CHIPSET_TCL
) {
459 if (tcl_mode
>= DRI_CONF_TCL_VTXFMT
)
460 radeonVtxfmtInit( ctx
, tcl_mode
>= DRI_CONF_TCL_CODEGEN
);
462 _tnl_need_dlist_norm_lengths( ctx
, GL_FALSE
);
468 /* Destroy the device specific context.
470 /* Destroy the Mesa and driver specific context data.
472 void radeonDestroyContext( __DRIcontextPrivate
*driContextPriv
)
474 GET_CURRENT_CONTEXT(ctx
);
475 radeonContextPtr rmesa
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
476 radeonContextPtr current
= ctx
? RADEON_CONTEXT(ctx
) : NULL
;
478 /* check if we're deleting the currently bound context */
479 if (rmesa
== current
) {
480 RADEON_FIREVERTICES( rmesa
);
481 _mesa_make_current2(NULL
, NULL
, NULL
);
484 /* Free radeon context resources */
485 assert(rmesa
); /* should never be null */
487 GLboolean release_texture_heaps
;
490 release_texture_heaps
= (rmesa
->glCtx
->Shared
->RefCount
== 1);
491 _swsetup_DestroyContext( rmesa
->glCtx
);
492 _tnl_DestroyContext( rmesa
->glCtx
);
493 _ac_DestroyContext( rmesa
->glCtx
);
494 _swrast_DestroyContext( rmesa
->glCtx
);
496 radeonDestroySwtcl( rmesa
->glCtx
);
497 radeonReleaseArrays( rmesa
->glCtx
, ~0 );
498 if (rmesa
->dma
.current
.buf
) {
499 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
500 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
503 if (!(rmesa
->TclFallback
& RADEON_TCL_FALLBACK_TCL_DISABLE
)) {
504 int tcl_mode
= driQueryOptioni(&rmesa
->optionCache
, "tcl_mode");
505 if (tcl_mode
>= DRI_CONF_TCL_VTXFMT
)
506 radeonVtxfmtDestroy( rmesa
->glCtx
);
509 /* free the Mesa context */
510 rmesa
->glCtx
->DriverCtx
= NULL
;
511 _mesa_destroy_context( rmesa
->glCtx
);
513 _mesa_vector4f_free( &rmesa
->tcl
.ObjClean
);
515 if (rmesa
->state
.scissor
.pClipRects
) {
516 FREE(rmesa
->state
.scissor
.pClipRects
);
517 rmesa
->state
.scissor
.pClipRects
= 0;
520 if ( release_texture_heaps
) {
521 /* This share group is about to go away, free our private
522 * texture object data.
526 for ( i
= 0 ; i
< rmesa
->nr_heaps
; i
++ ) {
527 driDestroyTextureHeap( rmesa
->texture_heaps
[ i
] );
528 rmesa
->texture_heaps
[ i
] = NULL
;
531 assert( is_empty_list( & rmesa
->swapped
) );
534 /* free the option cache */
535 driDestroyOptionCache (&rmesa
->optionCache
);
545 radeonSwapBuffers( __DRIdrawablePrivate
*dPriv
)
548 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
549 radeonContextPtr rmesa
;
551 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
553 if (ctx
->Visual
.doubleBufferMode
) {
554 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
556 if ( rmesa
->doPageFlip
) {
557 radeonPageFlip( dPriv
);
560 radeonCopyBuffer( dPriv
);
565 /* XXX this shouldn't be an error but we can't handle it for now */
566 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
571 /* Force the context `c' to be the current context and associate with it
575 radeonMakeCurrent( __DRIcontextPrivate
*driContextPriv
,
576 __DRIdrawablePrivate
*driDrawPriv
,
577 __DRIdrawablePrivate
*driReadPriv
)
579 if ( driContextPriv
) {
580 radeonContextPtr newCtx
=
581 (radeonContextPtr
) driContextPriv
->driverPrivate
;
583 if (RADEON_DEBUG
& DEBUG_DRI
)
584 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
, (void *) newCtx
->glCtx
);
586 if ( newCtx
->dri
.drawable
!= driDrawPriv
) {
587 driDrawableInitVBlank( driDrawPriv
, newCtx
->vblank_flags
);
588 newCtx
->dri
.drawable
= driDrawPriv
;
589 radeonUpdateWindow( newCtx
->glCtx
);
590 radeonUpdateViewportOffset( newCtx
->glCtx
);
593 _mesa_make_current2( newCtx
->glCtx
,
594 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
595 (GLframebuffer
*) driReadPriv
->driverPrivate
);
597 if (newCtx
->vb
.enabled
)
598 radeonVtxfmtMakeCurrent( newCtx
->glCtx
);
601 if (RADEON_DEBUG
& DEBUG_DRI
)
602 fprintf(stderr
, "%s ctx is null\n", __FUNCTION__
);
603 _mesa_make_current( 0, 0 );
606 if (RADEON_DEBUG
& DEBUG_DRI
)
607 fprintf(stderr
, "End %s\n", __FUNCTION__
);
611 /* Force the context `c' to be unbound from its buffer.
614 radeonUnbindContext( __DRIcontextPrivate
*driContextPriv
)
616 radeonContextPtr rmesa
= (radeonContextPtr
) driContextPriv
->driverPrivate
;
618 if (RADEON_DEBUG
& DEBUG_DRI
)
619 fprintf(stderr
, "%s ctx %p\n", __FUNCTION__
, (void *) rmesa
->glCtx
);