radeon_context.c revision d450d0b0e228e5b16c04b2a1acb9ea549aa690f2
1/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v 1.9 2003/09/24 02:43:12 dawes Exp $ */
2/**************************************************************************
3
4Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5                     VA Linux Systems Inc., Fremont, California.
6
7All Rights Reserved.
8
9Permission is hereby granted, free of charge, to any person obtaining
10a copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice (including the
18next paragraph) shall be included in all copies or substantial
19portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29**************************************************************************/
30
31/*
32 * Authors:
33 *   Kevin E. Martin <martin@valinux.com>
34 *   Gareth Hughes <gareth@valinux.com>
35 *   Keith Whitwell <keith@tungstengraphics.com>
36 */
37
38#include "glheader.h"
39#include "api_arrayelt.h"
40#include "context.h"
41#include "simple_list.h"
42#include "imports.h"
43#include "matrix.h"
44#include "extensions.h"
45
46#include "swrast/swrast.h"
47#include "swrast_setup/swrast_setup.h"
48#include "array_cache/acache.h"
49
50#include "tnl/tnl.h"
51#include "tnl/t_pipeline.h"
52
53#include "radeon_context.h"
54#include "radeon_ioctl.h"
55#include "radeon_state.h"
56#include "radeon_span.h"
57#include "radeon_tex.h"
58#include "radeon_swtcl.h"
59#include "radeon_tcl.h"
60#include "radeon_vtxfmt.h"
61#include "radeon_maos.h"
62
63#define DRIVER_DATE	"20030328"
64
65#include "vblank.h"
66#include "utils.h"
67#include "xmlpool.h" /* for symbolic values of enum-type options */
68#ifndef RADEON_DEBUG
69int RADEON_DEBUG = (0);
70#endif
71
72
73/* Return the width and height of the given buffer.
74 */
75static void radeonGetBufferSize( GLframebuffer *buffer,
76				 GLuint *width, GLuint *height )
77{
78   GET_CURRENT_CONTEXT(ctx);
79   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
80
81   LOCK_HARDWARE( rmesa );
82   *width  = rmesa->dri.drawable->w;
83   *height = rmesa->dri.drawable->h;
84   UNLOCK_HARDWARE( rmesa );
85}
86
87/* Return various strings for glGetString().
88 */
89static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name )
90{
91   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
92   static char buffer[128];
93   unsigned   offset;
94   GLuint agp_mode = rmesa->radeonScreen->IsPCI ? 0 :
95      rmesa->radeonScreen->AGPMode;
96
97   switch ( name ) {
98   case GL_VENDOR:
99      return (GLubyte *)"Tungsten Graphics, Inc.";
100
101   case GL_RENDERER:
102      offset = driGetRendererString( buffer, "Radeon", DRIVER_DATE,
103				     agp_mode );
104
105      sprintf( & buffer[ offset ], "%sTCL",
106	       !(rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
107	       ? "" : "NO-" );
108
109      return (GLubyte *)buffer;
110
111   default:
112      return NULL;
113   }
114}
115
116
117/* Extension strings exported by the R100 driver.
118 */
119static const char * const card_extensions[] =
120{
121    "GL_ARB_multisample",
122    "GL_ARB_multitexture",
123    "GL_ARB_texture_border_clamp",
124    "GL_ARB_texture_compression",
125    "GL_ARB_texture_env_add",
126    "GL_ARB_texture_env_combine",
127    "GL_ARB_texture_env_dot3",
128    "GL_ARB_texture_mirrored_repeat",
129    "GL_EXT_blend_logic_op",
130    "GL_EXT_blend_subtract",
131    "GL_EXT_secondary_color",
132    "GL_EXT_texture_edge_clamp",
133    "GL_EXT_texture_env_add",
134    "GL_EXT_texture_env_combine",
135    "GL_EXT_texture_env_dot3",
136    "GL_EXT_texture_filter_anisotropic",
137    "GL_EXT_texture_lod_bias",
138    "GL_ATI_texture_env_combine3",
139    "GL_ATI_texture_mirror_once",
140    "GL_IBM_texture_mirrored_repeat",
141    "GL_MESA_ycbcr_texture",
142    "GL_NV_blend_square",
143    "GL_SGIS_generate_mipmap",
144    "GL_SGIS_texture_border_clamp",
145    "GL_SGIS_texture_edge_clamp",
146    NULL
147};
148
149extern const struct tnl_pipeline_stage _radeon_texrect_stage;
150extern const struct tnl_pipeline_stage _radeon_render_stage;
151extern const struct tnl_pipeline_stage _radeon_tcl_stage;
152
153static const struct tnl_pipeline_stage *radeon_pipeline[] = {
154
155   /* Try and go straight to t&l
156    */
157   &_radeon_tcl_stage,
158
159   /* Catch any t&l fallbacks
160    */
161   &_tnl_vertex_transform_stage,
162   &_tnl_normal_transform_stage,
163   &_tnl_lighting_stage,
164   &_tnl_fog_coordinate_stage,
165   &_tnl_texgen_stage,
166   &_tnl_texture_transform_stage,
167
168   /* Scale texture rectangle to 0..1.
169    */
170   &_radeon_texrect_stage,
171
172   &_radeon_render_stage,
173   &_tnl_render_stage,		/* FALLBACK:  */
174   0,
175};
176
177
178
179/* Initialize the driver's misc functions.
180 */
181static void radeonInitDriverFuncs( GLcontext *ctx )
182{
183    ctx->Driver.GetBufferSize		= radeonGetBufferSize;
184    ctx->Driver.ResizeBuffers           = _swrast_alloc_buffers;
185    ctx->Driver.GetString		= radeonGetString;
186
187    ctx->Driver.Error			= NULL;
188    ctx->Driver.DrawPixels		= NULL;
189    ctx->Driver.Bitmap			= NULL;
190}
191
192static const struct dri_debug_control debug_control[] =
193{
194    { "fall",  DEBUG_FALLBACKS },
195    { "tex",   DEBUG_TEXTURE },
196    { "ioctl", DEBUG_IOCTL },
197    { "prim",  DEBUG_PRIMS },
198    { "vert",  DEBUG_VERTS },
199    { "state", DEBUG_STATE },
200    { "code",  DEBUG_CODEGEN },
201    { "vfmt",  DEBUG_VFMT },
202    { "vtxf",  DEBUG_VFMT },
203    { "verb",  DEBUG_VERBOSE },
204    { "dri",   DEBUG_DRI },
205    { "dma",   DEBUG_DMA },
206    { "san",   DEBUG_SANITY },
207    { NULL,    0 }
208};
209
210
211static int
212get_ust_nop( int64_t * ust )
213{
214   *ust = 1;
215   return 0;
216}
217
218
219/* Create the device specific context.
220 */
221GLboolean
222radeonCreateContext( const __GLcontextModes *glVisual,
223                     __DRIcontextPrivate *driContextPriv,
224                     void *sharedContextPrivate)
225{
226   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
227   radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
228   radeonContextPtr rmesa;
229   GLcontext *ctx, *shareCtx;
230   int i;
231   int tcl_mode, fthrottle_mode;
232
233   assert(glVisual);
234   assert(driContextPriv);
235   assert(screen);
236
237   /* Allocate the Radeon context */
238   rmesa = (radeonContextPtr) CALLOC( sizeof(*rmesa) );
239   if ( !rmesa )
240      return GL_FALSE;
241
242   /* Allocate the Mesa context */
243   if (sharedContextPrivate)
244      shareCtx = ((radeonContextPtr) sharedContextPrivate)->glCtx;
245   else
246      shareCtx = NULL;
247   rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE);
248   if (!rmesa->glCtx) {
249      FREE(rmesa);
250      return GL_FALSE;
251   }
252   driContextPriv->driverPrivate = rmesa;
253
254   /* Init radeon context data */
255   rmesa->dri.context = driContextPriv;
256   rmesa->dri.screen = sPriv;
257   rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */
258   rmesa->dri.hwContext = driContextPriv->hHWContext;
259   rmesa->dri.hwLock = &sPriv->pSAREA->lock;
260   rmesa->dri.fd = sPriv->fd;
261   rmesa->dri.drmMinor = sPriv->drmMinor;
262
263   /* Parse configuration files */
264   driParseConfigFiles (&rmesa->optionCache, &screen->optionCache,
265			screen->driScreen->myNum, "radeon");
266
267   rmesa->radeonScreen = screen;
268   rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA +
269				       screen->sarea_priv_offset);
270
271
272   rmesa->dma.buf0_address = rmesa->radeonScreen->buffers->list[0].address;
273
274   (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
275   make_empty_list( & rmesa->swapped );
276
277   rmesa->nr_heaps = screen->numTexHeaps;
278   for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
279      rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
280	    screen->texSize[i],
281	    12,
282	    RADEON_NR_TEX_REGIONS,
283	    rmesa->sarea->texList[i],
284	    & rmesa->sarea->texAge[i],
285	    & rmesa->swapped,
286	    sizeof( radeonTexObj ),
287	    (destroy_texture_object_t *) radeonDestroyTexObj );
288
289      driSetTextureSwapCounterLocation( rmesa->texture_heaps[i],
290					& rmesa->c_textureSwaps );
291   }
292   rmesa->texture_depth = driQueryOptioni (&rmesa->optionCache,
293					   "texture_depth");
294   if (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
295      rmesa->texture_depth = ( screen->cpp == 4 ) ?
296	 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
297
298   rmesa->swtcl.RenderIndex = ~0;
299   rmesa->lost_context = 1;
300
301   /* Set the maximum texture size small enough that we can guarentee that
302    * all texture units can bind a maximal texture and have them both in
303    * texturable memory at once.
304    */
305
306   ctx = rmesa->glCtx;
307   ctx->Const.MaxTextureUnits = 2;
308   ctx->Const.MaxTextureImageUnits = 2;
309   ctx->Const.MaxTextureCoordUnits = 2;
310
311   driCalculateMaxTextureLevels( rmesa->texture_heaps,
312				 rmesa->nr_heaps,
313				 & ctx->Const,
314				 4,
315				 11, /* max 2D texture size is 2048x2048 */
316				 0,  /* 3D textures unsupported. */
317				 0,  /* cube textures unsupported. */
318				 11, /* max rect texture size is 2048x2048. */
319				 12,
320				 GL_FALSE );
321
322   ctx->Const.MaxTextureMaxAnisotropy = 16.0;
323
324   /* No wide points.
325    */
326   ctx->Const.MinPointSize = 1.0;
327   ctx->Const.MinPointSizeAA = 1.0;
328   ctx->Const.MaxPointSize = 1.0;
329   ctx->Const.MaxPointSizeAA = 1.0;
330
331   ctx->Const.MinLineWidth = 1.0;
332   ctx->Const.MinLineWidthAA = 1.0;
333   ctx->Const.MaxLineWidth = 10.0;
334   ctx->Const.MaxLineWidthAA = 10.0;
335   ctx->Const.LineWidthGranularity = 0.0625;
336
337   /* Set maxlocksize (and hence vb size) small enough to avoid
338    * fallbacks in radeon_tcl.c.  ie. guarentee that all vertices can
339    * fit in a single dma buffer for indexed rendering of quad strips,
340    * etc.
341    */
342   ctx->Const.MaxArrayLockSize =
343      MIN2( ctx->Const.MaxArrayLockSize,
344 	    RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE );
345
346   rmesa->boxes = 0;
347
348   /* Initialize the software rasterizer and helper modules.
349    */
350   _swrast_CreateContext( ctx );
351   _ac_CreateContext( ctx );
352   _tnl_CreateContext( ctx );
353   _swsetup_CreateContext( ctx );
354   _ae_create_context( ctx );
355
356   /* Install the customized pipeline:
357    */
358   _tnl_destroy_pipeline( ctx );
359   _tnl_install_pipeline( ctx, radeon_pipeline );
360   ctx->Driver.FlushVertices = radeonFlushVertices;
361
362   /* Try and keep materials and vertices separate:
363    */
364   _tnl_isolate_materials( ctx, GL_TRUE );
365
366
367/*     _mesa_allow_light_in_model( ctx, GL_FALSE ); */
368
369   /* Try and keep materials and vertices separate:
370    */
371   _tnl_isolate_materials( ctx, GL_TRUE );
372
373
374   /* Configure swrast to match hardware characteristics:
375    */
376   _swrast_allow_pixel_fog( ctx, GL_FALSE );
377   _swrast_allow_vertex_fog( ctx, GL_TRUE );
378
379
380   _math_matrix_ctr( &rmesa->TexGenMatrix[0] );
381   _math_matrix_ctr( &rmesa->TexGenMatrix[1] );
382   _math_matrix_ctr( &rmesa->tmpmat );
383   _math_matrix_set_identity( &rmesa->TexGenMatrix[0] );
384   _math_matrix_set_identity( &rmesa->TexGenMatrix[1] );
385   _math_matrix_set_identity( &rmesa->tmpmat );
386
387   driInitExtensions( ctx, card_extensions, GL_TRUE );
388
389   if (rmesa->dri.drmMinor >= 9)
390      _mesa_enable_extension( ctx, "GL_NV_texture_rectangle");
391
392   radeonInitDriverFuncs( ctx );
393   radeonInitIoctlFuncs( ctx );
394   radeonInitStateFuncs( ctx );
395   radeonInitSpanFuncs( ctx );
396   radeonInitTextureFuncs( ctx );
397   radeonInitState( rmesa );
398   radeonInitSwtcl( ctx );
399
400   _mesa_vector4f_alloc( &rmesa->tcl.ObjClean, 0,
401			 ctx->Const.MaxArrayLockSize, 32 );
402
403   fthrottle_mode = driQueryOptioni(&rmesa->optionCache, "fthrottle_mode");
404   rmesa->iw.irq_seq = -1;
405   rmesa->irqsEmitted = 0;
406   rmesa->do_irqs = (rmesa->radeonScreen->irq != 0 &&
407		     fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS);
408
409   rmesa->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
410
411   rmesa->vblank_flags = (rmesa->radeonScreen->irq != 0)
412       ? driGetDefaultVBlankFlags(&rmesa->optionCache) : VBLANK_FLAG_NO_IRQ;
413#ifndef _SOLO
414   rmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
415   if ( rmesa->get_ust == NULL ) {
416      rmesa->get_ust = get_ust_nop;
417   }
418#else
419   rmesa->get_ust = get_ust_nop;
420#endif
421
422   (*rmesa->get_ust)( & rmesa->swap_ust );
423
424
425#if DO_DEBUG
426   RADEON_DEBUG = driParseDebugString( getenv( "RADEON_DEBUG" ),
427				       debug_control );
428#endif
429
430   tcl_mode = driQueryOptioni(&rmesa->optionCache, "tcl_mode");
431   if (driQueryOptionb(&rmesa->optionCache, "no_rast")) {
432      fprintf(stderr, "disabling 3D acceleration\n");
433      FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1);
434   } else if (tcl_mode == DRI_CONF_TCL_SW ||
435	      !(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
436      rmesa->radeonScreen->chipset &= ~RADEON_CHIPSET_TCL;
437      fprintf(stderr, "disabling TCL support\n");
438      TCL_FALLBACK(rmesa->glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
439   }
440
441   if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL) {
442      if (tcl_mode >= DRI_CONF_TCL_VTXFMT)
443	 radeonVtxfmtInit( ctx, tcl_mode >= DRI_CONF_TCL_CODEGEN );
444
445      _tnl_need_dlist_norm_lengths( ctx, GL_FALSE );
446   }
447   return GL_TRUE;
448}
449
450
451/* Destroy the device specific context.
452 */
453/* Destroy the Mesa and driver specific context data.
454 */
455void radeonDestroyContext( __DRIcontextPrivate *driContextPriv )
456{
457   GET_CURRENT_CONTEXT(ctx);
458   radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
459   radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
460
461   /* check if we're deleting the currently bound context */
462   if (rmesa == current) {
463      RADEON_FIREVERTICES( rmesa );
464      _mesa_make_current2(NULL, NULL, NULL);
465   }
466
467   /* Free radeon context resources */
468   assert(rmesa); /* should never be null */
469   if ( rmesa ) {
470      GLboolean   release_texture_heaps;
471
472
473      release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
474      _swsetup_DestroyContext( rmesa->glCtx );
475      _tnl_DestroyContext( rmesa->glCtx );
476      _ac_DestroyContext( rmesa->glCtx );
477      _swrast_DestroyContext( rmesa->glCtx );
478
479      radeonDestroySwtcl( rmesa->glCtx );
480      radeonReleaseArrays( rmesa->glCtx, ~0 );
481      if (rmesa->dma.current.buf) {
482	 radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
483	 radeonFlushCmdBuf( rmesa, __FUNCTION__ );
484      }
485
486      if (!(rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)) {
487	 int tcl_mode = driQueryOptioni(&rmesa->optionCache, "tcl_mode");
488	 if (tcl_mode >= DRI_CONF_TCL_VTXFMT)
489	    radeonVtxfmtDestroy( rmesa->glCtx );
490      }
491
492      /* free the Mesa context */
493      rmesa->glCtx->DriverCtx = NULL;
494      _mesa_destroy_context( rmesa->glCtx );
495
496      _mesa_vector4f_free( &rmesa->tcl.ObjClean );
497
498      if (rmesa->state.scissor.pClipRects) {
499	 FREE(rmesa->state.scissor.pClipRects);
500	 rmesa->state.scissor.pClipRects = 0;
501      }
502
503      if ( release_texture_heaps ) {
504         /* This share group is about to go away, free our private
505          * texture object data.
506          */
507         int i;
508
509         for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
510	    driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
511	    rmesa->texture_heaps[ i ] = NULL;
512         }
513
514	 assert( is_empty_list( & rmesa->swapped ) );
515      }
516
517      /* free the option cache */
518      driDestroyOptionCache (&rmesa->optionCache);
519
520      FREE( rmesa );
521   }
522}
523
524
525
526
527void
528radeonSwapBuffers( __DRIdrawablePrivate *dPriv )
529{
530
531   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
532      radeonContextPtr rmesa;
533      GLcontext *ctx;
534      rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
535      ctx = rmesa->glCtx;
536      if (ctx->Visual.doubleBufferMode) {
537         _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
538
539         if ( rmesa->doPageFlip ) {
540            radeonPageFlip( dPriv );
541         }
542         else {
543            radeonCopyBuffer( dPriv );
544         }
545      }
546   }
547   else {
548      /* XXX this shouldn't be an error but we can't handle it for now */
549      _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
550   }
551}
552
553
554/* Force the context `c' to be the current context and associate with it
555 * buffer `b'.
556 */
557GLboolean
558radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
559                   __DRIdrawablePrivate *driDrawPriv,
560                   __DRIdrawablePrivate *driReadPriv )
561{
562   if ( driContextPriv ) {
563      radeonContextPtr newCtx =
564	 (radeonContextPtr) driContextPriv->driverPrivate;
565
566      if (RADEON_DEBUG & DEBUG_DRI)
567	 fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newCtx->glCtx);
568
569      if ( newCtx->dri.drawable != driDrawPriv ) {
570	 driDrawableInitVBlank( driDrawPriv, newCtx->vblank_flags );
571	 newCtx->dri.drawable = driDrawPriv;
572	 radeonUpdateWindow( newCtx->glCtx );
573	 radeonUpdateViewportOffset( newCtx->glCtx );
574      }
575
576      _mesa_make_current2( newCtx->glCtx,
577			   (GLframebuffer *) driDrawPriv->driverPrivate,
578			   (GLframebuffer *) driReadPriv->driverPrivate );
579
580      if ( !newCtx->glCtx->Viewport.Width ) {
581	 _mesa_set_viewport( newCtx->glCtx, 0, 0,
582			     driDrawPriv->w, driDrawPriv->h );
583      }
584
585      if (newCtx->vb.enabled)
586	 radeonVtxfmtMakeCurrent( newCtx->glCtx );
587
588   } else {
589      if (RADEON_DEBUG & DEBUG_DRI)
590	 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
591      _mesa_make_current( 0, 0 );
592   }
593
594   if (RADEON_DEBUG & DEBUG_DRI)
595      fprintf(stderr, "End %s\n", __FUNCTION__);
596   return GL_TRUE;
597}
598
599/* Force the context `c' to be unbound from its buffer.
600 */
601GLboolean
602radeonUnbindContext( __DRIcontextPrivate *driContextPriv )
603{
604   radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
605
606   if (RADEON_DEBUG & DEBUG_DRI)
607      fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx);
608
609   return GL_TRUE;
610}
611