2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Keith Whitwell <keith@tungstengraphics.com>
36 #include "main/glheader.h"
37 #include "main/api_arrayelt.h"
38 #include "main/api_exec.h"
39 #include "main/context.h"
40 #include "main/simple_list.h"
41 #include "main/imports.h"
42 #include "main/extensions.h"
43 #include "main/mfeatures.h"
44 #include "main/version.h"
45 #include "main/vtxfmt.h"
47 #include "swrast/swrast.h"
48 #include "swrast_setup/swrast_setup.h"
52 #include "tnl/t_pipeline.h"
54 #include "drivers/common/driverfuncs.h"
56 #include "r200_context.h"
57 #include "r200_ioctl.h"
58 #include "r200_state.h"
60 #include "r200_swtcl.h"
62 #include "r200_vertprog.h"
63 #include "radeon_queryobj.h"
64 #include "r200_blit.h"
65 #include "radeon_fog.h"
67 #include "radeon_span.h"
70 #include "xmlpool.h" /* for symbolic values of enum-type options */
72 /* Return various strings for glGetString().
74 static const GLubyte *r200GetString( struct gl_context *ctx, GLenum name )
76 r200ContextPtr rmesa = R200_CONTEXT(ctx);
77 static char buffer[128];
79 GLuint agp_mode = (rmesa->radeon.radeonScreen->card_type == RADEON_CARD_PCI)? 0 :
80 rmesa->radeon.radeonScreen->AGPMode;
84 return (GLubyte *)"Tungsten Graphics, Inc.";
87 offset = driGetRendererString( buffer, "R200", agp_mode );
89 sprintf( & buffer[ offset ], " %sTCL",
90 !(rmesa->radeon.TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
93 return (GLubyte *)buffer;
101 extern const struct tnl_pipeline_stage _r200_render_stage;
102 extern const struct tnl_pipeline_stage _r200_tcl_stage;
104 static const struct tnl_pipeline_stage *r200_pipeline[] = {
106 /* Try and go straight to t&l
110 /* Catch any t&l fallbacks
112 &_tnl_vertex_transform_stage,
113 &_tnl_normal_transform_stage,
114 &_tnl_lighting_stage,
115 &_tnl_fog_coordinate_stage,
117 &_tnl_texture_transform_stage,
118 &_tnl_point_attenuation_stage,
119 &_tnl_vertex_program_stage,
120 /* Try again to go to tcl?
121 * - no good for asymmetric-twoside (do with multipass)
122 * - no good for asymmetric-unfilled (do with multipass)
123 * - good for material
125 * - need to manipulate a bit of state
127 * - worth it/not worth it?
130 /* Else do them here.
132 /* &_r200_render_stage, */ /* FIXME: bugs with ut2003 */
133 &_tnl_render_stage, /* FALLBACK: */
139 /* Initialize the driver's misc functions.
141 static void r200InitDriverFuncs( struct dd_function_table *functions )
143 functions->GetBufferSize = NULL; /* OBSOLETE */
144 functions->GetString = r200GetString;
148 static void r200_get_lock(radeonContextPtr radeon)
150 r200ContextPtr rmesa = (r200ContextPtr)radeon;
151 drm_radeon_sarea_t *sarea = radeon->sarea;
153 R200_STATECHANGE( rmesa, ctx );
154 if (rmesa->radeon.sarea->tiling_enabled) {
155 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
157 else rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &= ~R200_COLOR_TILE_ENABLE;
159 if ( sarea->ctx_owner != rmesa->radeon.dri.hwContext ) {
160 sarea->ctx_owner = rmesa->radeon.dri.hwContext;
165 static void r200_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
169 static void r200_emit_query_finish(radeonContextPtr radeon)
171 BATCH_LOCALS(radeon);
172 struct radeon_query_object *query = radeon->query.current;
174 BEGIN_BATCH_NO_AUTOSTATE(4);
175 OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0));
176 OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
178 query->curr_offset += sizeof(uint32_t);
179 assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
180 query->emitted_begin = GL_FALSE;
183 static void r200_init_vtbl(radeonContextPtr radeon)
185 radeon->vtbl.get_lock = r200_get_lock;
186 radeon->vtbl.update_viewport_offset = r200UpdateViewportOffset;
187 radeon->vtbl.emit_cs_header = r200_vtbl_emit_cs_header;
188 radeon->vtbl.swtcl_flush = r200_swtcl_flush;
189 radeon->vtbl.fallback = r200Fallback;
190 radeon->vtbl.update_scissor = r200_vtbl_update_scissor;
191 radeon->vtbl.emit_query_finish = r200_emit_query_finish;
192 radeon->vtbl.check_blit = r200_check_blit;
193 radeon->vtbl.blit = r200_blit;
194 radeon->vtbl.is_format_renderable = radeonIsFormatRenderable;
198 /* Create the device specific rendering context.
200 GLboolean r200CreateContext( gl_api api,
201 const struct gl_config *glVisual,
202 __DRIcontext *driContextPriv,
203 unsigned major_version,
204 unsigned minor_version,
207 void *sharedContextPrivate)
209 __DRIscreen *sPriv = driContextPriv->driScreenPriv;
210 radeonScreenPtr screen = (radeonScreenPtr)(sPriv->driverPrivate);
211 struct dd_function_table functions;
212 r200ContextPtr rmesa;
213 struct gl_context *ctx;
218 case API_OPENGL_COMPAT:
219 if (major_version > 1 || minor_version > 3) {
220 *error = __DRI_CTX_ERROR_BAD_VERSION;
227 *error = __DRI_CTX_ERROR_BAD_API;
231 /* Flag filtering is handled in dri2CreateContextAttribs.
236 assert(driContextPriv);
239 /* Allocate the R200 context */
240 rmesa = calloc(1, sizeof(*rmesa));
242 *error = __DRI_CTX_ERROR_NO_MEMORY;
246 rmesa->radeon.radeonScreen = screen;
247 r200_init_vtbl(&rmesa->radeon);
248 /* init exp fog table data */
249 radeonInitStaticFogData();
251 /* Parse configuration files.
252 * Do this here so that initialMaxAnisotropy is set before we create
253 * the default textures.
255 driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache,
256 screen->driScreen->myNum, "r200");
257 rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache,
258 "def_max_anisotropy");
260 if ( sPriv->drm_version.major == 1
261 && driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) {
262 if ( sPriv->drm_version.minor < 13 )
263 fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
264 "disabling.\n", sPriv->drm_version.minor );
266 rmesa->using_hyperz = GL_TRUE;
269 if ( sPriv->drm_version.minor >= 15 )
270 rmesa->texmicrotile = GL_TRUE;
272 /* Init default driver functions then plug in our R200-specific functions
273 * (the texture functions are especially important)
275 _mesa_init_driver_functions(&functions);
276 r200InitDriverFuncs(&functions);
277 r200InitIoctlFuncs(&functions);
278 r200InitStateFuncs(&rmesa->radeon, &functions);
279 r200InitTextureFuncs(&rmesa->radeon, &functions);
280 r200InitShaderFuncs(&functions);
281 radeonInitQueryObjFunctions(&functions);
283 if (!radeonInitContext(&rmesa->radeon, &functions,
284 glVisual, driContextPriv,
285 sharedContextPrivate)) {
287 *error = __DRI_CTX_ERROR_NO_MEMORY;
291 rmesa->radeon.swtcl.RenderIndex = ~0;
292 rmesa->radeon.hw.all_dirty = 1;
294 ctx = &rmesa->radeon.glCtx;
295 /* Initialize the software rasterizer and helper modules.
297 _swrast_CreateContext( ctx );
298 _vbo_CreateContext( ctx );
299 _tnl_CreateContext( ctx );
300 _swsetup_CreateContext( ctx );
301 _ae_create_context( ctx );
303 /* Set the maximum texture size small enough that we can guarentee that
304 * all texture units can bind a maximal texture and have all of them in
305 * texturable memory at once. Depending on the allow_large_textures driconf
306 * setting allow larger textures.
308 ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache,
310 ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
311 ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
313 ctx->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxTextureUnits;
315 ctx->Const.StripTextureBorder = GL_TRUE;
317 i = driQueryOptioni( &rmesa->radeon.optionCache, "allow_large_textures");
319 /* FIXME: When no memory manager is available we should set this
320 * to some reasonable value based on texture memory pool size */
321 ctx->Const.MaxTextureLevels = 12;
322 ctx->Const.Max3DTextureLevels = 9;
323 ctx->Const.MaxCubeTextureLevels = 12;
324 ctx->Const.MaxTextureRectSize = 2048;
325 ctx->Const.MaxRenderbufferSize = 2048;
327 ctx->Const.MaxTextureMaxAnisotropy = 16.0;
329 /* No wide AA points.
331 ctx->Const.MinPointSize = 1.0;
332 ctx->Const.MinPointSizeAA = 1.0;
333 ctx->Const.MaxPointSizeAA = 1.0;
334 ctx->Const.PointSizeGranularity = 0.0625;
335 ctx->Const.MaxPointSize = 2047.0;
337 /* mesa initialization problem - _mesa_init_point was already called */
338 ctx->Point.MaxSize = ctx->Const.MaxPointSize;
340 ctx->Const.MinLineWidth = 1.0;
341 ctx->Const.MinLineWidthAA = 1.0;
342 ctx->Const.MaxLineWidth = 10.0;
343 ctx->Const.MaxLineWidthAA = 10.0;
344 ctx->Const.LineWidthGranularity = 0.0625;
346 ctx->Const.VertexProgram.MaxNativeInstructions = R200_VSF_MAX_INST;
347 ctx->Const.VertexProgram.MaxNativeAttribs = 12;
348 ctx->Const.VertexProgram.MaxNativeTemps = R200_VSF_MAX_TEMPS;
349 ctx->Const.VertexProgram.MaxNativeParameters = R200_VSF_MAX_PARAM;
350 ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
352 ctx->Const.MaxDrawBuffers = 1;
353 ctx->Const.MaxColorAttachments = 1;
355 _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
357 /* Install the customized pipeline:
359 _tnl_destroy_pipeline( ctx );
360 _tnl_install_pipeline( ctx, r200_pipeline );
362 /* Try and keep materials and vertices separate:
364 /* _tnl_isolate_materials( ctx, GL_TRUE ); */
367 /* Configure swrast and TNL to match hardware characteristics:
369 _swrast_allow_pixel_fog( ctx, GL_FALSE );
370 _swrast_allow_vertex_fog( ctx, GL_TRUE );
371 _tnl_allow_pixel_fog( ctx, GL_FALSE );
372 _tnl_allow_vertex_fog( ctx, GL_TRUE );
375 for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
376 _math_matrix_ctr( &rmesa->TexGenMatrix[i] );
377 _math_matrix_set_identity( &rmesa->TexGenMatrix[i] );
379 _math_matrix_ctr( &rmesa->tmpmat );
380 _math_matrix_set_identity( &rmesa->tmpmat );
382 ctx->Extensions.ARB_half_float_pixel = true;
383 ctx->Extensions.ARB_occlusion_query = true;
384 ctx->Extensions.ARB_texture_border_clamp = true;
385 ctx->Extensions.ARB_texture_env_combine = true;
386 ctx->Extensions.ARB_texture_env_dot3 = true;
387 ctx->Extensions.ARB_texture_env_crossbar = true;
388 ctx->Extensions.EXT_blend_color = true;
389 ctx->Extensions.EXT_blend_minmax = true;
390 ctx->Extensions.EXT_fog_coord = true;
391 ctx->Extensions.EXT_packed_depth_stencil = true;
392 ctx->Extensions.EXT_secondary_color = true;
393 ctx->Extensions.EXT_texture_env_dot3 = true;
394 ctx->Extensions.EXT_texture_filter_anisotropic = true;
395 ctx->Extensions.EXT_texture_mirror_clamp = true;
396 ctx->Extensions.ATI_texture_env_combine3 = true;
397 ctx->Extensions.ATI_texture_mirror_once = true;
398 ctx->Extensions.MESA_pack_invert = true;
399 ctx->Extensions.NV_blend_square = true;
400 ctx->Extensions.NV_texture_rectangle = true;
401 ctx->Extensions.OES_EGL_image = true;
402 ctx->Extensions.EXT_framebuffer_object = true;
403 ctx->Extensions.ARB_occlusion_query = true;
405 if (!(rmesa->radeon.radeonScreen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) {
406 /* yuv textures don't work with some chips - R200 / rv280 okay so far
407 others get the bit ordering right but don't actually do YUV-RGB conversion */
408 ctx->Extensions.MESA_ycbcr_texture = true;
410 if (rmesa->radeon.glCtx.Mesa_DXTn) {
411 ctx->Extensions.EXT_texture_compression_s3tc = true;
412 ctx->Extensions.ANGLE_texture_compression_dxt = true;
414 else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) {
415 ctx->Extensions.EXT_texture_compression_s3tc = true;
416 ctx->Extensions.ANGLE_texture_compression_dxt = true;
419 ctx->Extensions.ARB_texture_cube_map = true;
421 ctx->Extensions.EXT_blend_equation_separate = true;
422 ctx->Extensions.EXT_blend_func_separate = true;
424 ctx->Extensions.ARB_vertex_program = true;
425 ctx->Extensions.EXT_gpu_program_parameters = true;
427 ctx->Extensions.ATI_fragment_shader = (ctx->Const.MaxTextureUnits == 6);
429 ctx->Extensions.ARB_point_sprite = true;
430 ctx->Extensions.EXT_point_parameters = true;
433 r200InitDriverFuncs( ctx );
434 r200InitIoctlFuncs( ctx );
435 r200InitStateFuncs( ctx );
436 r200InitTextureFuncs( ctx );
438 /* plug in a few more device driver functions */
439 /* XXX these should really go right after _mesa_init_driver_functions() */
440 radeon_fbo_init(&rmesa->radeon);
441 radeonInitSpanFuncs( ctx );
442 r200InitTnlFuncs( ctx );
443 r200InitState( rmesa );
444 r200InitSwtcl( ctx );
446 rmesa->prefer_gart_client_texturing =
447 (getenv("R200_GART_CLIENT_TEXTURES") != 0);
449 tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode");
450 if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) {
451 fprintf(stderr, "disabling 3D acceleration\n");
452 FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
454 else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") ||
455 !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
456 if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
457 rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
458 fprintf(stderr, "Disabling HW TCL support\n");
460 TCL_FALLBACK(&rmesa->radeon.glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
463 _mesa_compute_version(ctx);
465 /* Exec table initialization requires the version to be computed */
466 _mesa_initialize_dispatch_tables(ctx);
467 _mesa_initialize_vbo_vtxfmt(ctx);
469 *error = __DRI_CTX_ERROR_SUCCESS;
474 void r200DestroyContext( __DRIcontext *driContextPriv )
477 r200ContextPtr rmesa = (r200ContextPtr)driContextPriv->driverPrivate;
480 for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
481 _math_matrix_dtr( &rmesa->TexGenMatrix[i] );
484 radeonDestroyContext(driContextPriv);