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 **************************************************************************/
33 * \author Keith Whitwell <keith@tungstengraphics.com>
35 * \author Nicolai Haehnle <prefect_@gmx.net>
38 #include "main/glheader.h"
39 #include "main/api_arrayelt.h"
40 #include "main/context.h"
41 #include "main/simple_list.h"
42 #include "main/imports.h"
43 #include "main/matrix.h"
44 #include "main/extensions.h"
45 #include "main/state.h"
46 #include "main/bufferobj.h"
48 #include "swrast/swrast.h"
49 #include "swrast_setup/swrast_setup.h"
53 #include "tnl/t_pipeline.h"
54 #include "tnl/t_vp_build.h"
56 #include "drivers/common/driverfuncs.h"
58 #include "radeon_ioctl.h"
59 #include "radeon_span.h"
60 #include "r300_context.h"
61 #include "r300_cmdbuf.h"
62 #include "r300_state.h"
63 #include "r300_ioctl.h"
65 #include "r300_emit.h"
66 #include "r300_swtcl.h"
74 #include "xmlpool.h" /* for symbolic values of enum-type options */
76 /* hw_tcl_on derives from future_hw_tcl_on when its safe to change it. */
77 int future_hw_tcl_on
= 1;
80 #define need_GL_EXT_stencil_two_side
81 #define need_GL_ARB_multisample
82 #define need_GL_ARB_point_parameters
83 #define need_GL_ARB_texture_compression
84 #define need_GL_ARB_vertex_buffer_object
85 #define need_GL_ARB_vertex_program
86 #define need_GL_EXT_blend_minmax
87 //#define need_GL_EXT_fog_coord
88 #define need_GL_EXT_multi_draw_arrays
89 #define need_GL_EXT_secondary_color
90 #define need_GL_EXT_blend_equation_separate
91 #define need_GL_EXT_blend_func_separate
92 #define need_GL_EXT_gpu_program_parameters
93 #define need_GL_NV_vertex_program
94 #include "extension_helper.h"
96 const struct dri_extension card_extensions
[] = {
98 {"GL_ARB_depth_texture", NULL
},
99 {"GL_ARB_fragment_program", NULL
},
100 {"GL_ARB_multisample", GL_ARB_multisample_functions
},
101 {"GL_ARB_multitexture", NULL
},
102 {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions
},
103 {"GL_ARB_shadow", NULL
},
104 {"GL_ARB_shadow_ambient", NULL
},
105 {"GL_ARB_texture_border_clamp", NULL
},
106 {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions
},
107 {"GL_ARB_texture_cube_map", NULL
},
108 {"GL_ARB_texture_env_add", NULL
},
109 {"GL_ARB_texture_env_combine", NULL
},
110 {"GL_ARB_texture_env_crossbar", NULL
},
111 {"GL_ARB_texture_env_dot3", NULL
},
112 {"GL_ARB_texture_mirrored_repeat", NULL
},
113 {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions
},
114 {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions
},
115 {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions
},
116 {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions
},
117 {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions
},
118 {"GL_EXT_blend_subtract", NULL
},
119 // {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
120 {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions
},
121 {"GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions
},
122 {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions
},
123 {"GL_EXT_shadow_funcs", NULL
},
124 {"GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions
},
125 {"GL_EXT_stencil_wrap", NULL
},
126 {"GL_EXT_texture_edge_clamp", NULL
},
127 {"GL_EXT_texture_env_combine", NULL
},
128 {"GL_EXT_texture_env_dot3", NULL
},
129 {"GL_EXT_texture_filter_anisotropic", NULL
},
130 {"GL_EXT_texture_lod_bias", NULL
},
131 {"GL_EXT_texture_mirror_clamp", NULL
},
132 {"GL_EXT_texture_rectangle", NULL
},
133 {"GL_ATI_texture_env_combine3", NULL
},
134 {"GL_ATI_texture_mirror_once", NULL
},
135 {"GL_MESA_pack_invert", NULL
},
136 {"GL_MESA_ycbcr_texture", NULL
},
137 {"GL_MESAX_texture_float", NULL
},
138 {"GL_NV_blend_square", NULL
},
139 {"GL_NV_vertex_program", GL_NV_vertex_program_functions
},
140 {"GL_SGIS_generate_mipmap", NULL
},
145 extern struct tnl_pipeline_stage _r300_render_stage
;
146 extern const struct tnl_pipeline_stage _r300_tcl_stage
;
148 static const struct tnl_pipeline_stage
*r300_pipeline
[] = {
150 /* Try and go straight to t&l
154 /* Catch any t&l fallbacks
156 &_tnl_vertex_transform_stage
,
157 &_tnl_normal_transform_stage
,
158 &_tnl_lighting_stage
,
159 &_tnl_fog_coordinate_stage
,
161 &_tnl_texture_transform_stage
,
162 &_tnl_vertex_program_stage
,
164 /* Try again to go to tcl?
165 * - no good for asymmetric-twoside (do with multipass)
166 * - no good for asymmetric-unfilled (do with multipass)
167 * - good for material
169 * - need to manipulate a bit of state
171 * - worth it/not worth it?
174 /* Else do them here.
177 &_tnl_render_stage
, /* FALLBACK */
181 /* Create the device specific rendering context.
183 GLboolean
r300CreateContext(const __GLcontextModes
* glVisual
,
184 __DRIcontextPrivate
* driContextPriv
,
185 void *sharedContextPrivate
)
187 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
188 radeonScreenPtr screen
= (radeonScreenPtr
) (sPriv
->private);
189 struct dd_function_table functions
;
195 assert(driContextPriv
);
198 /* Allocate the R300 context */
199 r300
= (r300ContextPtr
) CALLOC(sizeof(*r300
));
203 if (!(screen
->chip_flags
& RADEON_CHIPSET_TCL
))
204 hw_tcl_on
= future_hw_tcl_on
= 0;
206 /* Parse configuration files.
207 * Do this here so that initialMaxAnisotropy is set before we create
208 * the default textures.
210 driParseConfigFiles(&r300
->radeon
.optionCache
, &screen
->optionCache
,
211 screen
->driScreen
->myNum
, "r300");
212 r300
->initialMaxAnisotropy
= driQueryOptionf(&r300
->radeon
.optionCache
,
213 "def_max_anisotropy");
215 /* Init default driver functions then plug in our R300-specific functions
216 * (the texture functions are especially important)
218 _mesa_init_driver_functions(&functions
);
219 r300InitIoctlFuncs(&functions
);
220 r300InitStateFuncs(&functions
);
221 r300InitTextureFuncs(&functions
);
222 r300InitShaderFuncs(&functions
);
228 if (!radeonInitContext(&r300
->radeon
, &functions
,
229 glVisual
, driContextPriv
,
230 sharedContextPrivate
)) {
235 /* Init r300 context data */
236 r300
->dma
.buf0_address
=
237 r300
->radeon
.radeonScreen
->buffers
->list
[0].address
;
239 (void)memset(r300
->texture_heaps
, 0, sizeof(r300
->texture_heaps
));
240 make_empty_list(&r300
->swapped
);
242 r300
->nr_heaps
= 1 /* screen->numTexHeaps */ ;
243 assert(r300
->nr_heaps
< RADEON_NR_TEX_HEAPS
);
244 for (i
= 0; i
< r300
->nr_heaps
; i
++) {
246 r300
->texture_heaps
[i
] = driCreateTextureHeap(i
, r300
,
249 RADEON_NR_TEX_REGIONS
,
250 (drmTextureRegionPtr
)
253 &r300
->radeon
.sarea
->
258 (destroy_texture_object_t
263 r300
->texture_depth
= driQueryOptioni(&r300
->radeon
.optionCache
,
265 if (r300
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FB
)
266 r300
->texture_depth
= (screen
->cpp
== 4) ?
267 DRI_CONF_TEXTURE_DEPTH_32
: DRI_CONF_TEXTURE_DEPTH_16
;
269 /* Set the maximum texture size small enough that we can guarentee that
270 * all texture units can bind a maximal texture and have them both in
271 * texturable memory at once.
274 ctx
= r300
->radeon
.glCtx
;
276 ctx
->Const
.MaxTextureImageUnits
=
277 driQueryOptioni(&r300
->radeon
.optionCache
, "texture_image_units");
278 ctx
->Const
.MaxTextureCoordUnits
=
279 driQueryOptioni(&r300
->radeon
.optionCache
, "texture_coord_units");
280 ctx
->Const
.MaxTextureUnits
=
281 MIN2(ctx
->Const
.MaxTextureImageUnits
,
282 ctx
->Const
.MaxTextureCoordUnits
);
283 ctx
->Const
.MaxTextureMaxAnisotropy
= 16.0;
284 ctx
->Const
.MaxTextureLodBias
= 16.0;
286 if (screen
->chip_family
>= CHIP_FAMILY_RV515
) {
287 ctx
->Const
.MaxTextureLevels
= 13;
288 ctx
->Const
.MaxTextureRectSize
= 4096;
291 ctx
->Const
.MinPointSize
= 1.0;
292 ctx
->Const
.MinPointSizeAA
= 1.0;
293 ctx
->Const
.MaxPointSize
= R300_POINTSIZE_MAX
;
294 ctx
->Const
.MaxPointSizeAA
= R300_POINTSIZE_MAX
;
296 ctx
->Const
.MinLineWidth
= 1.0;
297 ctx
->Const
.MinLineWidthAA
= 1.0;
298 ctx
->Const
.MaxLineWidth
= R300_LINESIZE_MAX
;
299 ctx
->Const
.MaxLineWidthAA
= R300_LINESIZE_MAX
;
302 /* Needs further modifications */
304 ctx
->Const
.MaxArrayLockSize
=
305 ( /*512 */ RADEON_BUFFER_SIZE
* 16 * 1024) / (4 * 4);
309 /* Initialize the software rasterizer and helper modules.
311 _swrast_CreateContext(ctx
);
312 _vbo_CreateContext(ctx
);
313 _tnl_CreateContext(ctx
);
314 _swsetup_CreateContext(ctx
);
315 _swsetup_Wakeup(ctx
);
316 _ae_create_context(ctx
);
318 /* Install the customized pipeline:
320 _tnl_destroy_pipeline(ctx
);
321 _tnl_install_pipeline(ctx
, r300_pipeline
);
323 /* Try and keep materials and vertices separate:
325 /* _tnl_isolate_materials(ctx, GL_TRUE); */
327 /* Configure swrast and TNL to match hardware characteristics:
329 _swrast_allow_pixel_fog(ctx
, GL_FALSE
);
330 _swrast_allow_vertex_fog(ctx
, GL_TRUE
);
331 _tnl_allow_pixel_fog(ctx
, GL_FALSE
);
332 _tnl_allow_vertex_fog(ctx
, GL_TRUE
);
334 /* currently bogus data */
335 if (screen
->chip_flags
& RADEON_CHIPSET_TCL
) {
336 ctx
->Const
.VertexProgram
.MaxInstructions
= VSF_MAX_FRAGMENT_LENGTH
/ 4;
337 ctx
->Const
.VertexProgram
.MaxNativeInstructions
=
338 VSF_MAX_FRAGMENT_LENGTH
/ 4;
339 ctx
->Const
.VertexProgram
.MaxNativeAttribs
= 16; /* r420 */
340 ctx
->Const
.VertexProgram
.MaxTemps
= 32;
341 ctx
->Const
.VertexProgram
.MaxNativeTemps
=
342 /*VSF_MAX_FRAGMENT_TEMPS */ 32;
343 ctx
->Const
.VertexProgram
.MaxNativeParameters
= 256; /* r420 */
344 ctx
->Const
.VertexProgram
.MaxNativeAddressRegs
= 1;
347 ctx
->Const
.FragmentProgram
.MaxNativeTemps
= PFS_NUM_TEMP_REGS
;
348 ctx
->Const
.FragmentProgram
.MaxNativeAttribs
= 11; /* copy i915... */
349 ctx
->Const
.FragmentProgram
.MaxNativeParameters
= PFS_NUM_CONST_REGS
;
350 ctx
->Const
.FragmentProgram
.MaxNativeAluInstructions
= PFS_MAX_ALU_INST
;
351 ctx
->Const
.FragmentProgram
.MaxNativeTexInstructions
= PFS_MAX_TEX_INST
;
352 ctx
->Const
.FragmentProgram
.MaxNativeInstructions
=
353 PFS_MAX_ALU_INST
+ PFS_MAX_TEX_INST
;
354 ctx
->Const
.FragmentProgram
.MaxNativeTexIndirections
=
355 PFS_MAX_TEX_INDIRECT
;
356 ctx
->Const
.FragmentProgram
.MaxNativeAddressRegs
= 0; /* and these are?? */
357 ctx
->VertexProgram
._MaintainTnlProgram
= GL_TRUE
;
358 ctx
->FragmentProgram
._MaintainTexEnvProgram
= GL_TRUE
;
360 driInitExtensions(ctx
, card_extensions
, GL_TRUE
);
363 (&r300
->radeon
.optionCache
, "disable_stencil_two_side"))
364 _mesa_disable_extension(ctx
, "GL_EXT_stencil_two_side");
366 if (r300
->radeon
.glCtx
->Mesa_DXTn
367 && !driQueryOptionb(&r300
->radeon
.optionCache
, "disable_s3tc")) {
368 _mesa_enable_extension(ctx
, "GL_EXT_texture_compression_s3tc");
369 _mesa_enable_extension(ctx
, "GL_S3_s3tc");
371 if (driQueryOptionb(&r300
->radeon
.optionCache
, "force_s3tc_enable"))
373 _mesa_enable_extension(ctx
, "GL_EXT_texture_compression_s3tc");
376 r300
->disable_lowimpact_fallback
=
377 driQueryOptionb(&r300
->radeon
.optionCache
,
378 "disable_lowimpact_fallback");
380 radeonInitSpanFuncs(ctx
);
381 r300InitCmdBuf(r300
);
383 if (!(screen
->chip_flags
& RADEON_CHIPSET_TCL
))
386 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= _tnl_run_pipeline
;
388 tcl_mode
= driQueryOptioni(&r300
->radeon
.optionCache
, "tcl_mode");
389 if (driQueryOptionb(&r300
->radeon
.optionCache
, "no_rast")) {
390 fprintf(stderr
, "disabling 3D acceleration\n");
392 FALLBACK(&r300
->radeon
, RADEON_FALLBACK_DISABLE
, 1);
395 if (tcl_mode
== DRI_CONF_TCL_SW
||
396 !(r300
->radeon
.radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
)) {
397 if (r300
->radeon
.radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
) {
398 r300
->radeon
.radeonScreen
->chip_flags
&=
400 fprintf(stderr
, "Disabling HW TCL support\n");
402 TCL_FALLBACK(r300
->radeon
.glCtx
,
403 RADEON_TCL_FALLBACK_TCL_DISABLE
, 1);
409 static void r300FreeGartAllocations(r300ContextPtr r300
)
411 int i
, ret
, tries
= 0, done_age
, in_use
= 0;
412 drm_radeon_mem_free_t memfree
;
414 memfree
.region
= RADEON_MEM_REGION_GART
;
417 for (i
= r300
->rmm
->u_last
; i
> 0; i
--) {
418 if (r300
->rmm
->u_list
[i
].ptr
== NULL
) {
422 /* check whether this buffer is still in use */
423 if (r300
->rmm
->u_list
[i
].pending
) {
427 /* Cannot flush/lock if no context exists. */
429 r300FlushCmdBuf(r300
, __FUNCTION__
);
431 done_age
= radeonGetAge((radeonContextPtr
) r300
);
433 for (i
= r300
->rmm
->u_last
; i
> 0; i
--) {
434 if (r300
->rmm
->u_list
[i
].ptr
== NULL
) {
438 /* check whether this buffer is still in use */
439 if (!r300
->rmm
->u_list
[i
].pending
) {
443 assert(r300
->rmm
->u_list
[i
].h_pending
== 0);
446 while (r300
->rmm
->u_list
[i
].age
> done_age
&& tries
++ < 1000) {
448 done_age
= radeonGetAge((radeonContextPtr
) r300
);
451 WARN_ONCE("Failed to idle region!");
454 memfree
.region_offset
= (char *)r300
->rmm
->u_list
[i
].ptr
-
455 (char *)r300
->radeon
.radeonScreen
->gartTextures
.map
;
457 ret
= drmCommandWrite(r300
->radeon
.radeonScreen
->driScreen
->fd
,
458 DRM_RADEON_FREE
, &memfree
,
461 fprintf(stderr
, "Failed to free at %p\nret = %s\n",
462 r300
->rmm
->u_list
[i
].ptr
, strerror(-ret
));
464 if (i
== r300
->rmm
->u_last
)
467 r300
->rmm
->u_list
[i
].pending
= 0;
468 r300
->rmm
->u_list
[i
].ptr
= NULL
;
471 r300
->rmm
->u_head
= i
;
472 #endif /* USER_BUFFERS */
475 /* Destroy the device specific context.
477 void r300DestroyContext(__DRIcontextPrivate
* driContextPriv
)
479 GET_CURRENT_CONTEXT(ctx
);
480 r300ContextPtr r300
= (r300ContextPtr
) driContextPriv
->driverPrivate
;
481 radeonContextPtr radeon
= (radeonContextPtr
) r300
;
482 radeonContextPtr current
= ctx
? RADEON_CONTEXT(ctx
) : NULL
;
484 if (RADEON_DEBUG
& DEBUG_DRI
) {
485 fprintf(stderr
, "Destroying context !\n");
488 /* check if we're deleting the currently bound context */
489 if (&r300
->radeon
== current
) {
490 radeonFlush(r300
->radeon
.glCtx
);
491 _mesa_make_current(NULL
, NULL
, NULL
);
494 /* Free r300 context resources */
495 assert(r300
); /* should never be null */
498 GLboolean release_texture_heaps
;
500 release_texture_heaps
=
501 (r300
->radeon
.glCtx
->Shared
->RefCount
== 1);
502 _swsetup_DestroyContext(r300
->radeon
.glCtx
);
503 _tnl_DestroyContext(r300
->radeon
.glCtx
);
504 _vbo_DestroyContext(r300
->radeon
.glCtx
);
505 _swrast_DestroyContext(r300
->radeon
.glCtx
);
507 if (r300
->dma
.current
.buf
) {
508 r300ReleaseDmaRegion(r300
, &r300
->dma
.current
,
511 r300FlushCmdBuf(r300
, __FUNCTION__
);
514 r300FreeGartAllocations(r300
);
515 r300DestroyCmdBuf(r300
);
517 if (radeon
->state
.scissor
.pClipRects
) {
518 FREE(radeon
->state
.scissor
.pClipRects
);
519 radeon
->state
.scissor
.pClipRects
= NULL
;
522 if (release_texture_heaps
) {
523 /* This share group is about to go away, free our private
524 * texture object data.
528 for (i
= 0; i
< r300
->nr_heaps
; i
++) {
529 driDestroyTextureHeap(r300
->texture_heaps
[i
]);
530 r300
->texture_heaps
[i
] = NULL
;
533 assert(is_empty_list(&r300
->swapped
));
536 radeonCleanupContext(&r300
->radeon
);
539 /* the memory manager might be accessed when Mesa frees the shared
540 * state, so don't destroy it earlier
542 r300_mem_destroy(r300
);
545 /* free the option cache */
546 driDestroyOptionCache(&r300
->radeon
.optionCache
);