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>
39 #include "api_arrayelt.h"
41 #include "simple_list.h"
44 #include "extensions.h"
46 #include "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"
73 #include "xmlpool.h" /* for symbolic values of enum-type options */
75 /* hw_tcl_on derives from future_hw_tcl_on when its safe to change it. */
76 int future_hw_tcl_on
= 1;
79 #define need_GL_EXT_stencil_two_side
80 #define need_GL_ARB_multisample
81 #define need_GL_ARB_texture_compression
82 #define need_GL_ARB_vertex_buffer_object
83 #define need_GL_ARB_vertex_program
84 #define need_GL_EXT_blend_minmax
85 //#define need_GL_EXT_fog_coord
86 #define need_GL_EXT_secondary_color
87 #define need_GL_EXT_blend_equation_separate
88 #define need_GL_EXT_blend_func_separate
89 #define need_GL_EXT_gpu_program_parameters
90 #define need_GL_NV_vertex_program
91 #include "extension_helper.h"
93 const struct dri_extension card_extensions
[] = {
95 {"GL_ARB_multisample", GL_ARB_multisample_functions
},
96 {"GL_ARB_multitexture", NULL
},
97 {"GL_ARB_texture_border_clamp", NULL
},
98 {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions
},
99 {"GL_ARB_texture_cube_map", NULL
},
100 {"GL_ARB_texture_env_add", NULL
},
101 {"GL_ARB_texture_env_combine", NULL
},
102 {"GL_ARB_texture_env_crossbar", NULL
},
103 {"GL_ARB_texture_env_dot3", NULL
},
104 {"GL_ARB_texture_mirrored_repeat", NULL
},
105 {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions
},
106 {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions
},
107 {"GL_ARB_fragment_program", NULL
},
108 {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions
},
109 {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions
},
110 {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions
},
111 {"GL_EXT_blend_subtract", NULL
},
112 // {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
113 {"GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions
},
114 {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions
},
115 {"GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions
},
116 {"GL_EXT_stencil_wrap", NULL
},
117 {"GL_EXT_texture_edge_clamp", NULL
},
118 {"GL_EXT_texture_env_combine", NULL
},
119 {"GL_EXT_texture_env_dot3", NULL
},
120 {"GL_EXT_texture_filter_anisotropic", NULL
},
121 {"GL_EXT_texture_lod_bias", NULL
},
122 {"GL_EXT_texture_mirror_clamp", NULL
},
123 {"GL_EXT_texture_rectangle", NULL
},
124 {"GL_ATI_texture_env_combine3", NULL
},
125 {"GL_ATI_texture_mirror_once", NULL
},
126 {"GL_MESA_pack_invert", NULL
},
127 {"GL_MESA_ycbcr_texture", NULL
},
128 {"GL_MESAX_texture_float", NULL
},
129 {"GL_NV_blend_square", NULL
},
130 {"GL_NV_vertex_program", GL_NV_vertex_program_functions
},
131 {"GL_SGIS_generate_mipmap", NULL
},
136 extern struct tnl_pipeline_stage _r300_render_stage
;
137 extern const struct tnl_pipeline_stage _r300_tcl_stage
;
139 static const struct tnl_pipeline_stage
*r300_pipeline
[] = {
141 /* Try and go straight to t&l
145 /* Catch any t&l fallbacks
147 &_tnl_vertex_transform_stage
,
148 &_tnl_normal_transform_stage
,
149 &_tnl_lighting_stage
,
150 &_tnl_fog_coordinate_stage
,
152 &_tnl_texture_transform_stage
,
153 &_tnl_vertex_program_stage
,
155 /* Try again to go to tcl?
156 * - no good for asymmetric-twoside (do with multipass)
157 * - no good for asymmetric-unfilled (do with multipass)
158 * - good for material
160 * - need to manipulate a bit of state
162 * - worth it/not worth it?
165 /* Else do them here.
168 &_tnl_render_stage
, /* FALLBACK */
172 /* Create the device specific rendering context.
174 GLboolean
r300CreateContext(const __GLcontextModes
* glVisual
,
175 __DRIcontextPrivate
* driContextPriv
,
176 void *sharedContextPrivate
)
178 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
179 radeonScreenPtr screen
= (radeonScreenPtr
) (sPriv
->private);
180 struct dd_function_table functions
;
186 assert(driContextPriv
);
189 /* Allocate the R300 context */
190 r300
= (r300ContextPtr
) CALLOC(sizeof(*r300
));
194 if (!(screen
->chip_flags
& RADEON_CHIPSET_TCL
))
195 hw_tcl_on
= future_hw_tcl_on
= 0;
197 /* Parse configuration files.
198 * Do this here so that initialMaxAnisotropy is set before we create
199 * the default textures.
201 driParseConfigFiles(&r300
->radeon
.optionCache
, &screen
->optionCache
,
202 screen
->driScreen
->myNum
, "r300");
203 r300
->initialMaxAnisotropy
= driQueryOptionf(&r300
->radeon
.optionCache
,
204 "def_max_anisotropy");
206 /* Init default driver functions then plug in our R300-specific functions
207 * (the texture functions are especially important)
209 _mesa_init_driver_functions(&functions
);
210 r300InitIoctlFuncs(&functions
);
211 r300InitStateFuncs(&functions
);
212 r300InitTextureFuncs(&functions
);
213 r300InitShaderFuncs(&functions
);
219 if (!radeonInitContext(&r300
->radeon
, &functions
,
220 glVisual
, driContextPriv
,
221 sharedContextPrivate
)) {
226 /* Init r300 context data */
227 r300
->dma
.buf0_address
=
228 r300
->radeon
.radeonScreen
->buffers
->list
[0].address
;
230 (void)memset(r300
->texture_heaps
, 0, sizeof(r300
->texture_heaps
));
231 make_empty_list(&r300
->swapped
);
233 r300
->nr_heaps
= 1 /* screen->numTexHeaps */ ;
234 assert(r300
->nr_heaps
< RADEON_NR_TEX_HEAPS
);
235 for (i
= 0; i
< r300
->nr_heaps
; i
++) {
237 r300
->texture_heaps
[i
] = driCreateTextureHeap(i
, r300
,
240 RADEON_NR_TEX_REGIONS
,
241 (drmTextureRegionPtr
)
244 &r300
->radeon
.sarea
->
249 (destroy_texture_object_t
254 r300
->texture_depth
= driQueryOptioni(&r300
->radeon
.optionCache
,
256 if (r300
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FB
)
257 r300
->texture_depth
= (screen
->cpp
== 4) ?
258 DRI_CONF_TEXTURE_DEPTH_32
: DRI_CONF_TEXTURE_DEPTH_16
;
260 /* Set the maximum texture size small enough that we can guarentee that
261 * all texture units can bind a maximal texture and have them both in
262 * texturable memory at once.
265 ctx
= r300
->radeon
.glCtx
;
267 ctx
->Const
.MaxTextureImageUnits
=
268 driQueryOptioni(&r300
->radeon
.optionCache
, "texture_image_units");
269 ctx
->Const
.MaxTextureCoordUnits
=
270 driQueryOptioni(&r300
->radeon
.optionCache
, "texture_coord_units");
271 ctx
->Const
.MaxTextureUnits
=
272 MIN2(ctx
->Const
.MaxTextureImageUnits
,
273 ctx
->Const
.MaxTextureCoordUnits
);
274 ctx
->Const
.MaxTextureMaxAnisotropy
= 16.0;
276 ctx
->Const
.MinPointSize
= 1.0;
277 ctx
->Const
.MinPointSizeAA
= 1.0;
278 ctx
->Const
.MaxPointSize
= R300_POINTSIZE_MAX
;
279 ctx
->Const
.MaxPointSizeAA
= R300_POINTSIZE_MAX
;
281 ctx
->Const
.MinLineWidth
= 1.0;
282 ctx
->Const
.MinLineWidthAA
= 1.0;
283 ctx
->Const
.MaxLineWidth
= R300_LINESIZE_MAX
;
284 ctx
->Const
.MaxLineWidthAA
= R300_LINESIZE_MAX
;
287 /* Needs further modifications */
289 ctx
->Const
.MaxArrayLockSize
=
290 ( /*512 */ RADEON_BUFFER_SIZE
* 16 * 1024) / (4 * 4);
294 /* Initialize the software rasterizer and helper modules.
296 _swrast_CreateContext(ctx
);
297 _vbo_CreateContext(ctx
);
298 _tnl_CreateContext(ctx
);
299 _swsetup_CreateContext(ctx
);
300 _swsetup_Wakeup(ctx
);
301 _ae_create_context(ctx
);
303 /* Install the customized pipeline:
305 _tnl_destroy_pipeline(ctx
);
306 _tnl_install_pipeline(ctx
, r300_pipeline
);
308 /* Try and keep materials and vertices separate:
310 /* _tnl_isolate_materials(ctx, GL_TRUE); */
312 /* Configure swrast and TNL to match hardware characteristics:
314 _swrast_allow_pixel_fog(ctx
, GL_FALSE
);
315 _swrast_allow_vertex_fog(ctx
, GL_TRUE
);
316 _tnl_allow_pixel_fog(ctx
, GL_FALSE
);
317 _tnl_allow_vertex_fog(ctx
, GL_TRUE
);
319 /* currently bogus data */
320 ctx
->Const
.VertexProgram
.MaxInstructions
= VSF_MAX_FRAGMENT_LENGTH
/ 4;
321 ctx
->Const
.VertexProgram
.MaxNativeInstructions
=
322 VSF_MAX_FRAGMENT_LENGTH
/ 4;
323 ctx
->Const
.VertexProgram
.MaxNativeAttribs
= 16; /* r420 */
324 ctx
->Const
.VertexProgram
.MaxTemps
= 32;
325 ctx
->Const
.VertexProgram
.MaxNativeTemps
=
326 /*VSF_MAX_FRAGMENT_TEMPS */ 32;
327 ctx
->Const
.VertexProgram
.MaxNativeParameters
= 256; /* r420 */
328 ctx
->Const
.VertexProgram
.MaxNativeAddressRegs
= 1;
330 ctx
->Const
.FragmentProgram
.MaxNativeTemps
= PFS_NUM_TEMP_REGS
;
331 ctx
->Const
.FragmentProgram
.MaxNativeAttribs
= 11; /* copy i915... */
332 ctx
->Const
.FragmentProgram
.MaxNativeParameters
= PFS_NUM_CONST_REGS
;
333 ctx
->Const
.FragmentProgram
.MaxNativeAluInstructions
= PFS_MAX_ALU_INST
;
334 ctx
->Const
.FragmentProgram
.MaxNativeTexInstructions
= PFS_MAX_TEX_INST
;
335 ctx
->Const
.FragmentProgram
.MaxNativeInstructions
=
336 PFS_MAX_ALU_INST
+ PFS_MAX_TEX_INST
;
337 ctx
->Const
.FragmentProgram
.MaxNativeTexIndirections
=
338 PFS_MAX_TEX_INDIRECT
;
339 ctx
->Const
.FragmentProgram
.MaxNativeAddressRegs
= 0; /* and these are?? */
340 _tnl_ProgramCacheInit(ctx
);
341 ctx
->FragmentProgram
._MaintainTexEnvProgram
= GL_TRUE
;
343 driInitExtensions(ctx
, card_extensions
, GL_TRUE
);
346 (&r300
->radeon
.optionCache
, "disable_stencil_two_side"))
347 _mesa_disable_extension(ctx
, "GL_EXT_stencil_two_side");
349 if (r300
->radeon
.glCtx
->Mesa_DXTn
350 && !driQueryOptionb(&r300
->radeon
.optionCache
, "disable_s3tc")) {
351 _mesa_enable_extension(ctx
, "GL_EXT_texture_compression_s3tc");
352 _mesa_enable_extension(ctx
, "GL_S3_s3tc");
354 if (driQueryOptionb(&r300
->radeon
.optionCache
, "force_s3tc_enable"))
356 _mesa_enable_extension(ctx
, "GL_EXT_texture_compression_s3tc");
359 r300
->disable_lowimpact_fallback
=
360 driQueryOptionb(&r300
->radeon
.optionCache
,
361 "disable_lowimpact_fallback");
363 radeonInitSpanFuncs(ctx
);
364 r300InitCmdBuf(r300
);
367 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= _tnl_run_pipeline
;
369 tcl_mode
= driQueryOptioni(&r300
->radeon
.optionCache
, "tcl_mode");
370 if (driQueryOptionb(&r300
->radeon
.optionCache
, "no_rast")) {
371 fprintf(stderr
, "disabling 3D acceleration\n");
373 FALLBACK(&r300
->radeon
, RADEON_FALLBACK_DISABLE
, 1);
376 if (tcl_mode
== DRI_CONF_TCL_SW
||
377 !(r300
->radeon
.radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
)) {
378 if (r300
->radeon
.radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
) {
379 r300
->radeon
.radeonScreen
->chip_flags
&=
381 fprintf(stderr
, "Disabling HW TCL support\n");
383 TCL_FALLBACK(r300
->radeon
.glCtx
,
384 RADEON_TCL_FALLBACK_TCL_DISABLE
, 1);
390 static void r300FreeGartAllocations(r300ContextPtr r300
)
392 int i
, ret
, tries
= 0, done_age
, in_use
= 0;
393 drm_radeon_mem_free_t memfree
;
395 memfree
.region
= RADEON_MEM_REGION_GART
;
398 for (i
= r300
->rmm
->u_last
; i
> 0; i
--) {
399 if (r300
->rmm
->u_list
[i
].ptr
== NULL
) {
403 /* check whether this buffer is still in use */
404 if (r300
->rmm
->u_list
[i
].pending
) {
408 /* Cannot flush/lock if no context exists. */
410 r300FlushCmdBuf(r300
, __FUNCTION__
);
412 done_age
= radeonGetAge((radeonContextPtr
) r300
);
414 for (i
= r300
->rmm
->u_last
; i
> 0; i
--) {
415 if (r300
->rmm
->u_list
[i
].ptr
== NULL
) {
419 /* check whether this buffer is still in use */
420 if (!r300
->rmm
->u_list
[i
].pending
) {
424 assert(r300
->rmm
->u_list
[i
].h_pending
== 0);
427 while (r300
->rmm
->u_list
[i
].age
> done_age
&& tries
++ < 1000) {
429 done_age
= radeonGetAge((radeonContextPtr
) r300
);
432 WARN_ONCE("Failed to idle region!");
435 memfree
.region_offset
= (char *)r300
->rmm
->u_list
[i
].ptr
-
436 (char *)r300
->radeon
.radeonScreen
->gartTextures
.map
;
438 ret
= drmCommandWrite(r300
->radeon
.radeonScreen
->driScreen
->fd
,
439 DRM_RADEON_FREE
, &memfree
,
442 fprintf(stderr
, "Failed to free at %p\nret = %s\n",
443 r300
->rmm
->u_list
[i
].ptr
, strerror(-ret
));
445 if (i
== r300
->rmm
->u_last
)
448 r300
->rmm
->u_list
[i
].pending
= 0;
449 r300
->rmm
->u_list
[i
].ptr
= NULL
;
452 r300
->rmm
->u_head
= i
;
453 #endif /* USER_BUFFERS */
456 /* Destroy the device specific context.
458 void r300DestroyContext(__DRIcontextPrivate
* driContextPriv
)
460 GET_CURRENT_CONTEXT(ctx
);
461 r300ContextPtr r300
= (r300ContextPtr
) driContextPriv
->driverPrivate
;
462 radeonContextPtr radeon
= (radeonContextPtr
) r300
;
463 radeonContextPtr current
= ctx
? RADEON_CONTEXT(ctx
) : NULL
;
465 if (RADEON_DEBUG
& DEBUG_DRI
) {
466 fprintf(stderr
, "Destroying context !\n");
469 /* check if we're deleting the currently bound context */
470 if (&r300
->radeon
== current
) {
471 radeonFlush(r300
->radeon
.glCtx
);
472 _mesa_make_current(NULL
, NULL
, NULL
);
475 /* Free r300 context resources */
476 assert(r300
); /* should never be null */
479 GLboolean release_texture_heaps
;
481 release_texture_heaps
=
482 (r300
->radeon
.glCtx
->Shared
->RefCount
== 1);
483 _swsetup_DestroyContext(r300
->radeon
.glCtx
);
484 _tnl_ProgramCacheDestroy(r300
->radeon
.glCtx
);
485 _tnl_DestroyContext(r300
->radeon
.glCtx
);
486 _vbo_DestroyContext(r300
->radeon
.glCtx
);
487 _swrast_DestroyContext(r300
->radeon
.glCtx
);
489 if (r300
->dma
.current
.buf
) {
490 r300ReleaseDmaRegion(r300
, &r300
->dma
.current
,
493 r300FlushCmdBuf(r300
, __FUNCTION__
);
496 r300FreeGartAllocations(r300
);
497 r300DestroyCmdBuf(r300
);
499 if (radeon
->state
.scissor
.pClipRects
) {
500 FREE(radeon
->state
.scissor
.pClipRects
);
501 radeon
->state
.scissor
.pClipRects
= NULL
;
504 if (release_texture_heaps
) {
505 /* This share group is about to go away, free our private
506 * texture object data.
510 for (i
= 0; i
< r300
->nr_heaps
; i
++) {
511 driDestroyTextureHeap(r300
->texture_heaps
[i
]);
512 r300
->texture_heaps
[i
] = NULL
;
515 assert(is_empty_list(&r300
->swapped
));
518 radeonCleanupContext(&r300
->radeon
);
521 /* the memory manager might be accessed when Mesa frees the shared
522 * state, so don't destroy it earlier
524 r300_mem_destroy(r300
);
527 /* free the option cache */
528 driDestroyOptionCache(&r300
->radeon
.optionCache
);