patch to import Jon Smirl's work from Bitkeeper
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_context.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v 1.7 2003/02/08 21:26:45 dawes Exp $ */
2 /**************************************************************************
3
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
6
7 All Rights Reserved.
8
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:
16
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.
20
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.
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 #ifndef RADEON_DEBUG
68 int RADEON_DEBUG = (0);
69 #endif
70
71
72
73 /* Return the width and height of the given buffer.
74 */
75 static 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 */
89 static 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 ], "%s %sTCL",
106 ( rmesa->dri.drmMinor < 3 ) ? " DRM-COMPAT" : "",
107 !(rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
108 ? "" : "NO-" );
109
110 return (GLubyte *)buffer;
111
112 default:
113 return NULL;
114 }
115 }
116
117
118 /* Extension strings exported by the R100 driver.
119 */
120 static const char * const card_extensions[] =
121 {
122 "GL_ARB_multisample",
123 "GL_ARB_multitexture",
124 "GL_ARB_texture_border_clamp",
125 "GL_ARB_texture_compression",
126 "GL_ARB_texture_env_add",
127 "GL_ARB_texture_env_combine",
128 "GL_ARB_texture_env_dot3",
129 "GL_ARB_texture_mirrored_repeat",
130 "GL_EXT_blend_logic_op",
131 "GL_EXT_blend_subtract",
132 "GL_EXT_secondary_color",
133 "GL_EXT_texture_edge_clamp",
134 "GL_EXT_texture_env_add",
135 "GL_EXT_texture_env_combine",
136 "GL_EXT_texture_env_dot3",
137 "GL_EXT_texture_filter_anisotropic",
138 "GL_EXT_texture_lod_bias",
139 "GL_ATI_texture_env_combine3",
140 "GL_ATI_texture_mirror_once",
141 "GL_IBM_texture_mirrored_repeat",
142 "GL_MESA_ycbcr_texture",
143 "GL_NV_blend_square",
144 "GL_SGIS_generate_mipmap",
145 "GL_SGIS_texture_border_clamp",
146 "GL_SGIS_texture_edge_clamp",
147 NULL
148 };
149
150 extern const struct gl_pipeline_stage _radeon_texrect_stage;
151 extern const struct gl_pipeline_stage _radeon_render_stage;
152 extern const struct gl_pipeline_stage _radeon_tcl_stage;
153
154 static const struct gl_pipeline_stage *radeon_pipeline[] = {
155
156 /* Try and go straight to t&l
157 */
158 &_radeon_tcl_stage,
159
160 /* Catch any t&l fallbacks
161 */
162 &_tnl_vertex_transform_stage,
163 &_tnl_normal_transform_stage,
164 &_tnl_lighting_stage,
165 &_tnl_fog_coordinate_stage,
166 &_tnl_texgen_stage,
167 &_tnl_texture_transform_stage,
168
169 /* Scale texture rectangle to 0..1.
170 */
171 &_radeon_texrect_stage,
172
173 &_radeon_render_stage,
174 &_tnl_render_stage, /* FALLBACK: */
175 0,
176 };
177
178
179
180 /* Initialize the driver's misc functions.
181 */
182 static void radeonInitDriverFuncs( GLcontext *ctx )
183 {
184 ctx->Driver.GetBufferSize = radeonGetBufferSize;
185 ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
186 ctx->Driver.GetString = radeonGetString;
187
188 ctx->Driver.Error = NULL;
189 ctx->Driver.DrawPixels = NULL;
190 ctx->Driver.Bitmap = NULL;
191 }
192
193 static const struct dri_debug_control debug_control[] =
194 {
195 { "fall", DEBUG_FALLBACKS },
196 { "tex", DEBUG_TEXTURE },
197 { "ioctl", DEBUG_IOCTL },
198 { "prim", DEBUG_PRIMS },
199 { "vert", DEBUG_VERTS },
200 { "state", DEBUG_STATE },
201 { "code", DEBUG_CODEGEN },
202 { "vfmt", DEBUG_VFMT },
203 { "vtxf", DEBUG_VFMT },
204 { "verb", DEBUG_VERBOSE },
205 { "dri", DEBUG_DRI },
206 { "dma", DEBUG_DMA },
207 { "san", DEBUG_SANITY },
208 { NULL, 0 }
209 };
210
211
212 static int
213 get_ust_nop( uint64_t * ust )
214 {
215 *ust = 1;
216 return 0;
217 }
218
219
220 /* Create the device specific context.
221 */
222 GLboolean
223 radeonCreateContext( const __GLcontextModes *glVisual,
224 __DRIcontextPrivate *driContextPriv,
225 void *sharedContextPrivate)
226 {
227 __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
228 radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
229 radeonContextPtr rmesa;
230 GLcontext *ctx, *shareCtx;
231 int i;
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
262 /* If we don't have 1.3, fallback to the 1.1 interfaces.
263 */
264 if (getenv("RADEON_COMPAT") || sPriv->drmMinor < 3 )
265 rmesa->dri.drmMinor = 1;
266 else
267 rmesa->dri.drmMinor = sPriv->drmMinor;
268
269 rmesa->radeonScreen = screen;
270 rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA +
271 screen->sarea_priv_offset);
272
273
274 rmesa->dma.buf0_address = rmesa->radeonScreen->buffers->list[0].address;
275
276 (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
277 make_empty_list( & rmesa->swapped );
278
279 rmesa->nr_heaps = screen->numTexHeaps;
280 for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
281 rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
282 screen->texSize[i],
283 12,
284 RADEON_NR_TEX_REGIONS,
285 rmesa->sarea->texList[i],
286 & rmesa->sarea->texAge[i],
287 & rmesa->swapped,
288 sizeof( radeonTexObj ),
289 (destroy_texture_object_t *) radeonDestroyTexObj );
290
291 driSetTextureSwapCounterLocation( rmesa->texture_heaps[i],
292 & rmesa->c_textureSwaps );
293 }
294
295 rmesa->swtcl.RenderIndex = ~0;
296 rmesa->lost_context = 1;
297
298 /* Set the maximum texture size small enough that we can guarentee that
299 * all texture units can bind a maximal texture and have them both in
300 * texturable memory at once.
301 */
302
303 ctx = rmesa->glCtx;
304 ctx->Const.MaxTextureUnits = 2;
305
306 driCalculateMaxTextureLevels( rmesa->texture_heaps,
307 rmesa->nr_heaps,
308 & ctx->Const,
309 4,
310 11, /* max 2D texture size is 2048x2048 */
311 0, /* 3D textures unsupported. */
312 0, /* cube textures unsupported. */
313 11, /* max rect texture size is 2048x2048. */
314 12,
315 GL_FALSE );
316
317 ctx->Const.MaxTextureMaxAnisotropy = 16.0;
318
319 /* No wide points.
320 */
321 ctx->Const.MinPointSize = 1.0;
322 ctx->Const.MinPointSizeAA = 1.0;
323 ctx->Const.MaxPointSize = 1.0;
324 ctx->Const.MaxPointSizeAA = 1.0;
325
326 ctx->Const.MinLineWidth = 1.0;
327 ctx->Const.MinLineWidthAA = 1.0;
328 ctx->Const.MaxLineWidth = 10.0;
329 ctx->Const.MaxLineWidthAA = 10.0;
330 ctx->Const.LineWidthGranularity = 0.0625;
331
332 /* Set maxlocksize (and hence vb size) small enough to avoid
333 * fallbacks in radeon_tcl.c. ie. guarentee that all vertices can
334 * fit in a single dma buffer for indexed rendering of quad strips,
335 * etc.
336 */
337 ctx->Const.MaxArrayLockSize =
338 MIN2( ctx->Const.MaxArrayLockSize,
339 RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE );
340
341 rmesa->boxes = (getenv("LIBGL_PERFORMANCE_BOXES") != NULL);
342
343 /* Initialize the software rasterizer and helper modules.
344 */
345 _swrast_CreateContext( ctx );
346 _ac_CreateContext( ctx );
347 _tnl_CreateContext( ctx );
348 _swsetup_CreateContext( ctx );
349 _ae_create_context( ctx );
350
351 /* Install the customized pipeline:
352 */
353 _tnl_destroy_pipeline( ctx );
354 _tnl_install_pipeline( ctx, radeon_pipeline );
355 ctx->Driver.FlushVertices = radeonFlushVertices;
356
357 /* Try and keep materials and vertices separate:
358 */
359 _tnl_isolate_materials( ctx, GL_TRUE );
360
361
362 /* _mesa_allow_light_in_model( ctx, GL_FALSE ); */
363
364 /* Try and keep materials and vertices separate:
365 */
366 _tnl_isolate_materials( ctx, GL_TRUE );
367
368
369 /* Configure swrast to match hardware characteristics:
370 */
371 _swrast_allow_pixel_fog( ctx, GL_FALSE );
372 _swrast_allow_vertex_fog( ctx, GL_TRUE );
373
374
375 _math_matrix_ctr( &rmesa->TexGenMatrix[0] );
376 _math_matrix_ctr( &rmesa->TexGenMatrix[1] );
377 _math_matrix_ctr( &rmesa->tmpmat );
378 _math_matrix_set_identity( &rmesa->TexGenMatrix[0] );
379 _math_matrix_set_identity( &rmesa->TexGenMatrix[1] );
380 _math_matrix_set_identity( &rmesa->tmpmat );
381
382 driInitExtensions( ctx, card_extensions, GL_TRUE );
383
384 if (rmesa->dri.drmMinor >= 9)
385 _mesa_enable_extension( ctx, "GL_NV_texture_rectangle");
386
387 radeonInitDriverFuncs( ctx );
388 radeonInitIoctlFuncs( ctx );
389 radeonInitStateFuncs( ctx );
390 radeonInitSpanFuncs( ctx );
391 radeonInitTextureFuncs( ctx );
392 radeonInitState( rmesa );
393 radeonInitSwtcl( ctx );
394
395 rmesa->iw.irq_seq = -1;
396 rmesa->irqsEmitted = 0;
397 rmesa->do_irqs = (rmesa->radeonScreen->irq && !getenv("RADEON_NO_IRQS"));
398
399 rmesa->do_usleeps = !getenv("RADEON_NO_USLEEPS");
400
401 rmesa->vblank_flags = (rmesa->do_irqs)
402 ? driGetDefaultVBlankFlags() : VBLANK_FLAG_NO_IRQ;
403
404 #ifndef _SOLO
405 rmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( "__glXGetUST" );
406 if ( rmesa->get_ust == NULL )
407 #endif
408 {
409 rmesa->get_ust = get_ust_nop;
410 }
411
412 (*rmesa->get_ust)( & rmesa->swap_ust );
413
414
415 #if DO_DEBUG
416 RADEON_DEBUG = driParseDebugString( getenv( "RADEON_DEBUG" ),
417 debug_control );
418 #endif
419
420 if (getenv("RADEON_NO_RAST")) {
421 fprintf(stderr, "disabling 3D acceleration\n");
422 FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1);
423 }
424 else if (getenv("RADEON_TCL_FORCE_ENABLE")) {
425 fprintf(stderr, "Enabling TCL support... this will probably crash\n");
426 fprintf(stderr, " your card if it isn't capable of TCL!\n");
427 rmesa->radeonScreen->chipset |= RADEON_CHIPSET_TCL;
428 } else if (getenv("RADEON_TCL_FORCE_DISABLE") ||
429 rmesa->dri.drmMinor < 3 ||
430 !(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
431 rmesa->radeonScreen->chipset &= ~RADEON_CHIPSET_TCL;
432 fprintf(stderr, "disabling TCL support\n");
433 TCL_FALLBACK(rmesa->glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
434 }
435
436 if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL) {
437 if (!getenv("RADEON_NO_VTXFMT"))
438 radeonVtxfmtInit( ctx );
439
440 _tnl_need_dlist_norm_lengths( ctx, GL_FALSE );
441 }
442 return GL_TRUE;
443 }
444
445
446 /* Destroy the device specific context.
447 */
448 /* Destroy the Mesa and driver specific context data.
449 */
450 void radeonDestroyContext( __DRIcontextPrivate *driContextPriv )
451 {
452 GET_CURRENT_CONTEXT(ctx);
453 radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
454 radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
455
456 /* check if we're deleting the currently bound context */
457 if (rmesa == current) {
458 RADEON_FIREVERTICES( rmesa );
459 _mesa_make_current2(NULL, NULL, NULL);
460 }
461
462 /* Free radeon context resources */
463 assert(rmesa); /* should never be null */
464 if ( rmesa ) {
465 GLboolean release_texture_heaps;
466
467
468 release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
469 _swsetup_DestroyContext( rmesa->glCtx );
470 _tnl_DestroyContext( rmesa->glCtx );
471 _ac_DestroyContext( rmesa->glCtx );
472 _swrast_DestroyContext( rmesa->glCtx );
473
474 radeonDestroySwtcl( rmesa->glCtx );
475 radeonReleaseArrays( rmesa->glCtx, ~0 );
476 if (rmesa->dma.current.buf) {
477 radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
478 radeonFlushCmdBuf( rmesa, __FUNCTION__ );
479 }
480
481 if (!rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
482 if (!getenv("RADEON_NO_VTXFMT"))
483 radeonVtxfmtDestroy( rmesa->glCtx );
484
485 /* free the Mesa context */
486 rmesa->glCtx->DriverCtx = NULL;
487 _mesa_destroy_context( rmesa->glCtx );
488
489 if (rmesa->state.scissor.pClipRects) {
490 FREE(rmesa->state.scissor.pClipRects);
491 rmesa->state.scissor.pClipRects = 0;
492 }
493
494 if ( release_texture_heaps ) {
495 /* This share group is about to go away, free our private
496 * texture object data.
497 */
498 int i;
499
500 /* this assert is not correct, default textures are always on swap list
501 assert( is_empty_list( & rmesa->swapped ) ); */
502
503 for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
504 driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
505 rmesa->texture_heaps[ i ] = NULL;
506 }
507 }
508
509 FREE( rmesa );
510 }
511 }
512
513
514
515
516 void
517 radeonSwapBuffers( __DRIdrawablePrivate *dPriv )
518 {
519
520 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
521 radeonContextPtr rmesa;
522 GLcontext *ctx;
523 rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
524 ctx = rmesa->glCtx;
525 if (ctx->Visual.doubleBufferMode) {
526 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
527
528 if ( rmesa->doPageFlip ) {
529 radeonPageFlip( dPriv );
530 }
531 else {
532 radeonCopyBuffer( dPriv );
533 }
534 }
535 }
536 else {
537 /* XXX this shouldn't be an error but we can't handle it for now */
538 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
539 }
540 }
541
542
543 /* Force the context `c' to be the current context and associate with it
544 * buffer `b'.
545 */
546 GLboolean
547 radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
548 __DRIdrawablePrivate *driDrawPriv,
549 __DRIdrawablePrivate *driReadPriv )
550 {
551 if ( driContextPriv ) {
552 radeonContextPtr newCtx =
553 (radeonContextPtr) driContextPriv->driverPrivate;
554
555 if (RADEON_DEBUG & DEBUG_DRI)
556 fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newCtx->glCtx);
557
558 if ( newCtx->dri.drawable != driDrawPriv ) {
559 newCtx->dri.drawable = driDrawPriv;
560 radeonUpdateWindow( newCtx->glCtx );
561 radeonUpdateViewportOffset( newCtx->glCtx );
562 }
563
564 _mesa_make_current2( newCtx->glCtx,
565 (GLframebuffer *) driDrawPriv->driverPrivate,
566 (GLframebuffer *) driReadPriv->driverPrivate );
567
568 if ( !newCtx->glCtx->Viewport.Width ) {
569 _mesa_set_viewport( newCtx->glCtx, 0, 0,
570 driDrawPriv->w, driDrawPriv->h );
571 }
572
573 if (newCtx->vb.enabled)
574 radeonVtxfmtMakeCurrent( newCtx->glCtx );
575
576 } else {
577 if (RADEON_DEBUG & DEBUG_DRI)
578 fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
579 _mesa_make_current( 0, 0 );
580 }
581
582 if (RADEON_DEBUG & DEBUG_DRI)
583 fprintf(stderr, "End %s\n", __FUNCTION__);
584 return GL_TRUE;
585 }
586
587 /* Force the context `c' to be unbound from its buffer.
588 */
589 GLboolean
590 radeonUnbindContext( __DRIcontextPrivate *driContextPriv )
591 {
592 radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
593
594 if (RADEON_DEBUG & DEBUG_DRI)
595 fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx);
596
597 return GL_TRUE;
598 }