r200_context.c revision c73f4fdb65a6bae4b02348d73f2efdb8f2c5583a
1/*
2Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3
4The Weather Channel (TM) funded Tungsten Graphics to develop the
5initial release of the Radeon 8500 driver under the XFree86 license.
6This notice must be preserved.
7
8Permission is hereby granted, free of charge, to any person obtaining
9a copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial
18portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28**************************************************************************/
29
30/*
31 * Authors:
32 *   Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35#include "main/glheader.h"
36#include "main/api_arrayelt.h"
37#include "main/context.h"
38#include "main/simple_list.h"
39#include "main/imports.h"
40#include "main/matrix.h"
41#include "main/extensions.h"
42#include "main/framebuffer.h"
43#include "main/state.h"
44
45#include "swrast/swrast.h"
46#include "swrast_setup/swrast_setup.h"
47#include "vbo/vbo.h"
48
49#include "tnl/tnl.h"
50#include "tnl/t_pipeline.h"
51
52#include "drivers/common/driverfuncs.h"
53
54#include "r200_context.h"
55#include "r200_ioctl.h"
56#include "r200_state.h"
57#include "r200_pixel.h"
58#include "r200_tex.h"
59#include "r200_swtcl.h"
60#include "r200_tcl.h"
61#include "r200_maos.h"
62#include "r200_vertprog.h"
63
64#include "radeon_span.h"
65
66#define need_GL_ARB_vertex_program
67#define need_GL_ATI_fragment_shader
68#define need_GL_EXT_blend_minmax
69#define need_GL_EXT_fog_coord
70#define need_GL_EXT_secondary_color
71#define need_GL_EXT_blend_equation_separate
72#define need_GL_EXT_blend_func_separate
73#define need_GL_NV_vertex_program
74#define need_GL_ARB_point_parameters
75#include "extension_helper.h"
76
77#define DRIVER_DATE	"20060602"
78
79#include "vblank.h"
80#include "utils.h"
81#include "xmlpool.h" /* for symbolic values of enum-type options */
82
83/* Return various strings for glGetString().
84 */
85static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
86{
87   r200ContextPtr rmesa = R200_CONTEXT(ctx);
88   static char buffer[128];
89   unsigned   offset;
90   GLuint agp_mode = (rmesa->radeon.radeonScreen->card_type == RADEON_CARD_PCI)? 0 :
91      rmesa->radeon.radeonScreen->AGPMode;
92
93   switch ( name ) {
94   case GL_VENDOR:
95      return (GLubyte *)"Tungsten Graphics, Inc.";
96
97   case GL_RENDERER:
98      offset = driGetRendererString( buffer, "R200", DRIVER_DATE,
99				     agp_mode );
100
101      sprintf( & buffer[ offset ], " %sTCL",
102	       !(rmesa->radeon.TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
103	       ? "" : "NO-" );
104
105      return (GLubyte *)buffer;
106
107   default:
108      return NULL;
109   }
110}
111
112
113/* Extension strings exported by the R200 driver.
114 */
115const struct dri_extension card_extensions[] =
116{
117    { "GL_ARB_multitexture",               NULL },
118    { "GL_ARB_texture_border_clamp",       NULL },
119    { "GL_ARB_texture_env_add",            NULL },
120    { "GL_ARB_texture_env_combine",        NULL },
121    { "GL_ARB_texture_env_dot3",           NULL },
122    { "GL_ARB_texture_env_crossbar",       NULL },
123    { "GL_ARB_texture_mirrored_repeat",    NULL },
124    { "GL_EXT_blend_minmax",               GL_EXT_blend_minmax_functions },
125    { "GL_EXT_blend_subtract",             NULL },
126    { "GL_EXT_fog_coord",                  GL_EXT_fog_coord_functions },
127    { "GL_EXT_secondary_color",            GL_EXT_secondary_color_functions },
128    { "GL_EXT_stencil_wrap",               NULL },
129    { "GL_EXT_texture_edge_clamp",         NULL },
130    { "GL_EXT_texture_env_combine",        NULL },
131    { "GL_EXT_texture_env_dot3",           NULL },
132    { "GL_EXT_texture_filter_anisotropic", NULL },
133    { "GL_EXT_texture_lod_bias",           NULL },
134    { "GL_EXT_texture_mirror_clamp",       NULL },
135    { "GL_EXT_texture_rectangle",          NULL },
136    { "GL_ATI_texture_env_combine3",       NULL },
137    { "GL_ATI_texture_mirror_once",        NULL },
138    { "GL_MESA_pack_invert",               NULL },
139    { "GL_NV_blend_square",                NULL },
140    { "GL_SGIS_generate_mipmap",           NULL },
141    { NULL,                                NULL }
142};
143
144const struct dri_extension blend_extensions[] = {
145    { "GL_EXT_blend_equation_separate",    GL_EXT_blend_equation_separate_functions },
146    { "GL_EXT_blend_func_separate",        GL_EXT_blend_func_separate_functions },
147    { NULL,                                NULL }
148};
149
150const struct dri_extension ARB_vp_extension[] = {
151    { "GL_ARB_vertex_program",             GL_ARB_vertex_program_functions }
152};
153
154const struct dri_extension NV_vp_extension[] = {
155    { "GL_NV_vertex_program",              GL_NV_vertex_program_functions }
156};
157
158const struct dri_extension ATI_fs_extension[] = {
159    { "GL_ATI_fragment_shader",            GL_ATI_fragment_shader_functions }
160};
161
162const struct dri_extension point_extensions[] = {
163    { "GL_ARB_point_sprite",               NULL },
164    { "GL_ARB_point_parameters",           GL_ARB_point_parameters_functions },
165    { NULL,                                NULL }
166};
167
168extern const struct tnl_pipeline_stage _r200_render_stage;
169extern const struct tnl_pipeline_stage _r200_tcl_stage;
170
171static const struct tnl_pipeline_stage *r200_pipeline[] = {
172
173   /* Try and go straight to t&l
174    */
175   &_r200_tcl_stage,
176
177   /* Catch any t&l fallbacks
178    */
179   &_tnl_vertex_transform_stage,
180   &_tnl_normal_transform_stage,
181   &_tnl_lighting_stage,
182   &_tnl_fog_coordinate_stage,
183   &_tnl_texgen_stage,
184   &_tnl_texture_transform_stage,
185   &_tnl_point_attenuation_stage,
186   &_tnl_vertex_program_stage,
187   /* Try again to go to tcl?
188    *     - no good for asymmetric-twoside (do with multipass)
189    *     - no good for asymmetric-unfilled (do with multipass)
190    *     - good for material
191    *     - good for texgen
192    *     - need to manipulate a bit of state
193    *
194    * - worth it/not worth it?
195    */
196
197   /* Else do them here.
198    */
199/*    &_r200_render_stage,  */ /* FIXME: bugs with ut2003 */
200   &_tnl_render_stage,		/* FALLBACK:  */
201   NULL,
202};
203
204
205
206/* Initialize the driver's misc functions.
207 */
208static void r200InitDriverFuncs( struct dd_function_table *functions )
209{
210    functions->GetBufferSize		= NULL; /* OBSOLETE */
211    functions->GetString		= r200GetString;
212}
213
214static const struct dri_debug_control debug_control[] =
215{
216    { "fall",  DEBUG_FALLBACKS },
217    { "tex",   DEBUG_TEXTURE },
218    { "ioctl", DEBUG_IOCTL },
219    { "prim",  DEBUG_PRIMS },
220    { "vert",  DEBUG_VERTS },
221    { "state", DEBUG_STATE },
222    { "code",  DEBUG_CODEGEN },
223    { "vfmt",  DEBUG_VFMT },
224    { "vtxf",  DEBUG_VFMT },
225    { "verb",  DEBUG_VERBOSE },
226    { "dri",   DEBUG_DRI },
227    { "dma",   DEBUG_DMA },
228    { "san",   DEBUG_SANITY },
229    { "sync",  DEBUG_SYNC },
230    { "pix",   DEBUG_PIXEL },
231    { "mem",   DEBUG_MEMORY },
232    { NULL,    0 }
233};
234
235static void r200_get_lock(radeonContextPtr radeon)
236{
237   r200ContextPtr rmesa = (r200ContextPtr)radeon;
238   drm_radeon_sarea_t *sarea = radeon->sarea;
239   int i;
240
241   R200_STATECHANGE( rmesa, ctx );
242   if (rmesa->radeon.sarea->tiling_enabled) {
243      rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
244   }
245   else rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &= ~R200_COLOR_TILE_ENABLE;
246
247   if ( sarea->ctx_owner != rmesa->radeon.dri.hwContext ) {
248      sarea->ctx_owner = rmesa->radeon.dri.hwContext;
249      if (!radeon->radeonScreen->kernel_mm)
250         radeon_bo_legacy_texture_age(radeon->radeonScreen->bom);
251   }
252
253}
254
255static void r200_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
256{
257}
258
259
260static void r200_init_vtbl(radeonContextPtr radeon)
261{
262   radeon->vtbl.get_lock = r200_get_lock;
263   radeon->vtbl.update_viewport_offset = r200UpdateViewportOffset;
264   radeon->vtbl.emit_cs_header = r200_vtbl_emit_cs_header;
265   radeon->vtbl.swtcl_flush = r200_swtcl_flush;
266   radeon->vtbl.fallback = r200Fallback;
267}
268
269
270/* Create the device specific rendering context.
271 */
272GLboolean r200CreateContext( const __GLcontextModes *glVisual,
273			     __DRIcontextPrivate *driContextPriv,
274			     void *sharedContextPrivate)
275{
276   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
277   radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
278   struct dd_function_table functions;
279   r200ContextPtr rmesa;
280   GLcontext *ctx;
281   int i;
282   int tcl_mode;
283
284   assert(glVisual);
285   assert(driContextPriv);
286   assert(screen);
287
288   /* Allocate the R200 context */
289   rmesa = (r200ContextPtr) CALLOC( sizeof(*rmesa) );
290   if ( !rmesa )
291      return GL_FALSE;
292
293   r200_init_vtbl(&rmesa->radeon);
294   /* init exp fog table data */
295   r200InitStaticFogData();
296
297   /* Parse configuration files.
298    * Do this here so that initialMaxAnisotropy is set before we create
299    * the default textures.
300    */
301   driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache,
302			screen->driScreen->myNum, "r200");
303   rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache,
304							"def_max_anisotropy");
305
306   if ( driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) {
307      if ( sPriv->drm_version.minor < 13 )
308	 fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
309			  "disabling.\n", sPriv->drm_version.minor );
310      else
311	 rmesa->using_hyperz = GL_TRUE;
312   }
313
314   if ( sPriv->drm_version.minor >= 15 )
315      rmesa->texmicrotile = GL_TRUE;
316
317   /* Init default driver functions then plug in our R200-specific functions
318    * (the texture functions are especially important)
319    */
320   _mesa_init_driver_functions(&functions);
321   r200InitDriverFuncs(&functions);
322   r200InitIoctlFuncs(&functions);
323   r200InitStateFuncs(&functions);
324   r200InitTextureFuncs(&functions);
325   r200InitShaderFuncs(&functions);
326
327   if (!radeonInitContext(&rmesa->radeon, &functions,
328			  glVisual, driContextPriv,
329			  sharedContextPrivate)) {
330     FREE(rmesa);
331     return GL_FALSE;
332   }
333
334   rmesa->radeon.texture_depth = driQueryOptioni (&rmesa->radeon.optionCache,
335					   "texture_depth");
336   if (rmesa->radeon.texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
337      rmesa->radeon.texture_depth = ( screen->cpp == 4 ) ?
338	 DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
339
340   rmesa->radeon.swtcl.RenderIndex = ~0;
341   rmesa->radeon.hw.all_dirty = 1;
342
343   /* Set the maximum texture size small enough that we can guarentee that
344    * all texture units can bind a maximal texture and have all of them in
345    * texturable memory at once. Depending on the allow_large_textures driconf
346    * setting allow larger textures.
347    */
348
349   ctx = rmesa->radeon.glCtx;
350   ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache,
351						 "texture_units");
352   ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
353   ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
354
355   i = driQueryOptioni( &rmesa->radeon.optionCache, "allow_large_textures");
356
357   ctx->Const.MaxTextureMaxAnisotropy = 16.0;
358
359   /* No wide AA points.
360    */
361   ctx->Const.MinPointSize = 1.0;
362   ctx->Const.MinPointSizeAA = 1.0;
363   ctx->Const.MaxPointSizeAA = 1.0;
364   ctx->Const.PointSizeGranularity = 0.0625;
365   if (rmesa->radeon.radeonScreen->drmSupportsPointSprites)
366      ctx->Const.MaxPointSize = 2047.0;
367   else
368      ctx->Const.MaxPointSize = 1.0;
369
370   /* mesa initialization problem - _mesa_init_point was already called */
371   ctx->Point.MaxSize = ctx->Const.MaxPointSize;
372
373   ctx->Const.MinLineWidth = 1.0;
374   ctx->Const.MinLineWidthAA = 1.0;
375   ctx->Const.MaxLineWidth = 10.0;
376   ctx->Const.MaxLineWidthAA = 10.0;
377   ctx->Const.LineWidthGranularity = 0.0625;
378
379   ctx->Const.VertexProgram.MaxNativeInstructions = R200_VSF_MAX_INST;
380   ctx->Const.VertexProgram.MaxNativeAttribs = 12;
381   ctx->Const.VertexProgram.MaxNativeTemps = R200_VSF_MAX_TEMPS;
382   ctx->Const.VertexProgram.MaxNativeParameters = R200_VSF_MAX_PARAM;
383   ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
384
385   ctx->Const.MaxDrawBuffers = 1;
386
387   /* Initialize the software rasterizer and helper modules.
388    */
389   _swrast_CreateContext( ctx );
390   _vbo_CreateContext( ctx );
391   _tnl_CreateContext( ctx );
392   _swsetup_CreateContext( ctx );
393   _ae_create_context( ctx );
394
395   /* Install the customized pipeline:
396    */
397   _tnl_destroy_pipeline( ctx );
398   _tnl_install_pipeline( ctx, r200_pipeline );
399
400   /* Try and keep materials and vertices separate:
401    */
402/*    _tnl_isolate_materials( ctx, GL_TRUE ); */
403
404
405   /* Configure swrast and TNL to match hardware characteristics:
406    */
407   _swrast_allow_pixel_fog( ctx, GL_FALSE );
408   _swrast_allow_vertex_fog( ctx, GL_TRUE );
409   _tnl_allow_pixel_fog( ctx, GL_FALSE );
410   _tnl_allow_vertex_fog( ctx, GL_TRUE );
411
412
413   for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
414      _math_matrix_ctr( &rmesa->TexGenMatrix[i] );
415      _math_matrix_set_identity( &rmesa->TexGenMatrix[i] );
416   }
417   _math_matrix_ctr( &rmesa->tmpmat );
418   _math_matrix_set_identity( &rmesa->tmpmat );
419
420   driInitExtensions( ctx, card_extensions, GL_TRUE );
421   if (!(rmesa->radeon.radeonScreen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) {
422     /* yuv textures don't work with some chips - R200 / rv280 okay so far
423	others get the bit ordering right but don't actually do YUV-RGB conversion */
424      _mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" );
425   }
426   if (rmesa->radeon.glCtx->Mesa_DXTn) {
427      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
428      _mesa_enable_extension( ctx, "GL_S3_s3tc" );
429   }
430   else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) {
431      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
432   }
433
434   if (rmesa->radeon.radeonScreen->drmSupportsCubeMapsR200)
435      _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" );
436   if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) {
437       driInitExtensions( ctx, blend_extensions, GL_FALSE );
438   }
439   if(rmesa->radeon.radeonScreen->drmSupportsVertexProgram)
440      driInitSingleExtension( ctx, ARB_vp_extension );
441   if(driQueryOptionb(&rmesa->radeon.optionCache, "nv_vertex_program"))
442      driInitSingleExtension( ctx, NV_vp_extension );
443
444   if ((ctx->Const.MaxTextureUnits == 6) && rmesa->radeon.radeonScreen->drmSupportsFragShader)
445      driInitSingleExtension( ctx, ATI_fs_extension );
446   if (rmesa->radeon.radeonScreen->drmSupportsPointSprites)
447      driInitExtensions( ctx, point_extensions, GL_FALSE );
448#if 0
449   r200InitDriverFuncs( ctx );
450   r200InitIoctlFuncs( ctx );
451   r200InitStateFuncs( ctx );
452   r200InitTextureFuncs( ctx );
453#endif
454   /* plug in a few more device driver functions */
455   /* XXX these should really go right after _mesa_init_driver_functions() */
456   radeon_fbo_init(&rmesa->radeon);
457   radeonInitSpanFuncs( ctx );
458   r200InitPixelFuncs( ctx );
459   r200InitTnlFuncs( ctx );
460   r200InitState( rmesa );
461   r200InitSwtcl( ctx );
462
463   rmesa->prefer_gart_client_texturing =
464      (getenv("R200_GART_CLIENT_TEXTURES") != 0);
465
466#if DO_DEBUG
467   R200_DEBUG  = driParseDebugString( getenv( "R200_DEBUG" ),
468				      debug_control );
469   R200_DEBUG |= driParseDebugString( getenv( "RADEON_DEBUG" ),
470				      debug_control );
471#endif
472
473   tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode");
474   if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) {
475      fprintf(stderr, "disabling 3D acceleration\n");
476      FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
477   }
478   else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") ||
479	    !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
480      if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
481	 rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
482	 fprintf(stderr, "Disabling HW TCL support\n");
483      }
484      TCL_FALLBACK(rmesa->radeon.glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
485   }
486
487   return GL_TRUE;
488}
489
490
491/* Destroy the device specific context.
492 */
493/* Destroy the Mesa and driver specific context data.
494 */
495void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
496{
497   GET_CURRENT_CONTEXT(ctx);
498   r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
499   r200ContextPtr current = ctx ? R200_CONTEXT(ctx) : NULL;
500
501   /* check if we're deleting the currently bound context */
502   if (rmesa == current) {
503      radeon_firevertices(&rmesa->radeon);
504      _mesa_make_current(NULL, NULL, NULL);
505   }
506
507   /* Free r200 context resources */
508   assert(rmesa); /* should never be null */
509   if ( rmesa ) {
510
511      _swsetup_DestroyContext( rmesa->radeon.glCtx );
512      _tnl_DestroyContext( rmesa->radeon.glCtx );
513      _vbo_DestroyContext( rmesa->radeon.glCtx );
514      _swrast_DestroyContext( rmesa->radeon.glCtx );
515
516      r200DestroySwtcl( rmesa->radeon.glCtx );
517      r200ReleaseArrays( rmesa->radeon.glCtx, ~0 );
518
519      if (rmesa->radeon.dma.current) {
520	 radeonReleaseDmaRegion( &rmesa->radeon );
521	 rcommonFlushCmdBuf( &rmesa->radeon, __FUNCTION__ );
522      }
523
524      if (rmesa->radeon.state.scissor.pClipRects) {
525	 FREE(rmesa->radeon.state.scissor.pClipRects);
526	 rmesa->radeon.state.scissor.pClipRects = NULL;
527      }
528
529      radeonCleanupContext(&rmesa->radeon);
530
531      FREE( rmesa );
532   }
533}
534
535
536
537/* Force the context `c' to be unbound from its buffer.
538 */
539GLboolean
540r200UnbindContext( __DRIcontextPrivate *driContextPriv )
541{
542   r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate;
543
544   if (R200_DEBUG & DEBUG_DRI)
545      fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)rmesa->radeon.glCtx);
546
547   return GL_TRUE;
548}
549