1 /**************************************************************************
2 
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4                      VA Linux Systems Inc., Fremont, California.
5 
6 All Rights Reserved.
7 
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:
15 
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.
19 
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.
27 
28 **************************************************************************/
29 
30 /*
31  * Authors:
32  *   Kevin E. Martin <martin@valinux.com>
33  *   Gareth Hughes <gareth@valinux.com>
34  *   Keith Whitwell <keith@tungstengraphics.com>
35  */
36 
37 #include <stdbool.h>
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/extensions.h"
44 #include "main/mfeatures.h"
45 #include "main/version.h"
46 
47 #include "swrast/swrast.h"
48 #include "swrast_setup/swrast_setup.h"
49 #include "vbo/vbo.h"
50 
51 #include "tnl/tnl.h"
52 #include "tnl/t_pipeline.h"
53 
54 #include "drivers/common/driverfuncs.h"
55 
56 #include "radeon_common.h"
57 #include "radeon_context.h"
58 #include "radeon_ioctl.h"
59 #include "radeon_state.h"
60 #include "radeon_span.h"
61 #include "radeon_tex.h"
62 #include "radeon_swtcl.h"
63 #include "radeon_tcl.h"
64 #include "radeon_queryobj.h"
65 #include "radeon_blit.h"
66 #include "radeon_fog.h"
67 
68 #include "utils.h"
69 #include "xmlpool.h" /* for symbolic values of enum-type options */
70 
71 extern const struct tnl_pipeline_stage _radeon_render_stage;
72 extern const struct tnl_pipeline_stage _radeon_tcl_stage;
73 
74 static const struct tnl_pipeline_stage *radeon_pipeline[] = {
75 
76    /* Try and go straight to t&l
77     */
78    &_radeon_tcl_stage,
79 
80    /* Catch any t&l fallbacks
81     */
82    &_tnl_vertex_transform_stage,
83    &_tnl_normal_transform_stage,
84    &_tnl_lighting_stage,
85    &_tnl_fog_coordinate_stage,
86    &_tnl_texgen_stage,
87    &_tnl_texture_transform_stage,
88 
89    &_radeon_render_stage,
90    &_tnl_render_stage,		/* FALLBACK:  */
91    NULL,
92 };
93 
r100_get_lock(radeonContextPtr radeon)94 static void r100_get_lock(radeonContextPtr radeon)
95 {
96    r100ContextPtr rmesa = (r100ContextPtr)radeon;
97    drm_radeon_sarea_t *sarea = radeon->sarea;
98 
99    RADEON_STATECHANGE(rmesa, ctx);
100    if (rmesa->radeon.sarea->tiling_enabled) {
101       rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |=
102 	 RADEON_COLOR_TILE_ENABLE;
103    } else {
104       rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &=
105 	 ~RADEON_COLOR_TILE_ENABLE;
106    }
107 
108    if (sarea->ctx_owner != rmesa->radeon.dri.hwContext) {
109       sarea->ctx_owner = rmesa->radeon.dri.hwContext;
110    }
111 }
112 
r100_vtbl_emit_cs_header(struct radeon_cs * cs,radeonContextPtr rmesa)113 static void r100_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
114 {
115 }
116 
r100_vtbl_pre_emit_state(radeonContextPtr radeon)117 static void r100_vtbl_pre_emit_state(radeonContextPtr radeon)
118 {
119    r100ContextPtr rmesa = (r100ContextPtr)radeon;
120 
121    /* r100 always needs to emit ZBS to avoid TCL lockups */
122    rmesa->hw.zbs.dirty = 1;
123    radeon->hw.is_dirty = 1;
124 }
125 
r100_vtbl_free_context(struct gl_context * ctx)126 static void r100_vtbl_free_context(struct gl_context *ctx)
127 {
128    r100ContextPtr rmesa = R100_CONTEXT(ctx);
129    _mesa_vector4f_free( &rmesa->tcl.ObjClean );
130 }
131 
r100_emit_query_finish(radeonContextPtr radeon)132 static void r100_emit_query_finish(radeonContextPtr radeon)
133 {
134    BATCH_LOCALS(radeon);
135    struct radeon_query_object *query = radeon->query.current;
136 
137    BEGIN_BATCH_NO_AUTOSTATE(4);
138    OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0));
139    OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
140    END_BATCH();
141    query->curr_offset += sizeof(uint32_t);
142    assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
143    query->emitted_begin = GL_FALSE;
144 }
145 
r100_init_vtbl(radeonContextPtr radeon)146 static void r100_init_vtbl(radeonContextPtr radeon)
147 {
148    radeon->vtbl.get_lock = r100_get_lock;
149    radeon->vtbl.update_viewport_offset = radeonUpdateViewportOffset;
150    radeon->vtbl.emit_cs_header = r100_vtbl_emit_cs_header;
151    radeon->vtbl.swtcl_flush = r100_swtcl_flush;
152    radeon->vtbl.pre_emit_state = r100_vtbl_pre_emit_state;
153    radeon->vtbl.fallback = radeonFallback;
154    radeon->vtbl.free_context = r100_vtbl_free_context;
155    radeon->vtbl.emit_query_finish = r100_emit_query_finish;
156    radeon->vtbl.check_blit = r100_check_blit;
157    radeon->vtbl.blit = r100_blit;
158    radeon->vtbl.is_format_renderable = radeonIsFormatRenderable;
159 }
160 
161 /* Create the device specific context.
162  */
163 GLboolean
r100CreateContext(gl_api api,const struct gl_config * glVisual,__DRIcontext * driContextPriv,unsigned major_version,unsigned minor_version,uint32_t flags,unsigned * error,void * sharedContextPrivate)164 r100CreateContext( gl_api api,
165 		   const struct gl_config *glVisual,
166 		   __DRIcontext *driContextPriv,
167 		   unsigned major_version,
168 		   unsigned minor_version,
169 		   uint32_t flags,
170 		   unsigned *error,
171 		   void *sharedContextPrivate)
172 {
173    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
174    radeonScreenPtr screen = (radeonScreenPtr)(sPriv->driverPrivate);
175    struct dd_function_table functions;
176    r100ContextPtr rmesa;
177    struct gl_context *ctx;
178    int i;
179    int tcl_mode, fthrottle_mode;
180 
181    switch (api) {
182    case API_OPENGL:
183       if (major_version > 1 || minor_version > 3) {
184          *error = __DRI_CTX_ERROR_BAD_VERSION;
185          return GL_FALSE;
186       }
187       break;
188    case API_OPENGLES:
189       break;
190    default:
191       *error = __DRI_CTX_ERROR_BAD_API;
192       return GL_FALSE;
193    }
194 
195    /* Flag filtering is handled in dri2CreateContextAttribs.
196     */
197    (void) flags;
198 
199    assert(glVisual);
200    assert(driContextPriv);
201    assert(screen);
202 
203    /* Allocate the Radeon context */
204    rmesa = (r100ContextPtr) CALLOC( sizeof(*rmesa) );
205    if ( !rmesa ) {
206       *error = __DRI_CTX_ERROR_NO_MEMORY;
207       return GL_FALSE;
208    }
209 
210    rmesa->radeon.radeonScreen = screen;
211    r100_init_vtbl(&rmesa->radeon);
212 
213    /* init exp fog table data */
214    radeonInitStaticFogData();
215 
216    /* Parse configuration files.
217     * Do this here so that initialMaxAnisotropy is set before we create
218     * the default textures.
219     */
220    driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache,
221 			screen->driScreen->myNum, "radeon");
222    rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache,
223                                                  "def_max_anisotropy");
224 
225    if ( driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) {
226       if ( sPriv->drm_version.minor < 13 )
227 	 fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
228 			  "disabling.\n", sPriv->drm_version.minor );
229       else
230 	 rmesa->using_hyperz = GL_TRUE;
231    }
232 
233    if ( sPriv->drm_version.minor >= 15 )
234       rmesa->texmicrotile = GL_TRUE;
235 
236    /* Init default driver functions then plug in our Radeon-specific functions
237     * (the texture functions are especially important)
238     */
239    _mesa_init_driver_functions( &functions );
240    radeonInitTextureFuncs( &rmesa->radeon, &functions );
241    radeonInitQueryObjFunctions(&functions);
242 
243    if (!radeonInitContext(&rmesa->radeon, &functions,
244 			  glVisual, driContextPriv,
245 			  sharedContextPrivate)) {
246      FREE(rmesa);
247      *error = __DRI_CTX_ERROR_NO_MEMORY;
248      return GL_FALSE;
249    }
250 
251    rmesa->radeon.swtcl.RenderIndex = ~0;
252    rmesa->radeon.hw.all_dirty = GL_TRUE;
253 
254    ctx = rmesa->radeon.glCtx;
255    /* Initialize the software rasterizer and helper modules.
256     */
257    _swrast_CreateContext( ctx );
258    _vbo_CreateContext( ctx );
259    _tnl_CreateContext( ctx );
260    _swsetup_CreateContext( ctx );
261    _ae_create_context( ctx );
262 
263    /* Set the maximum texture size small enough that we can guarentee that
264     * all texture units can bind a maximal texture and have all of them in
265     * texturable memory at once. Depending on the allow_large_textures driconf
266     * setting allow larger textures.
267     */
268 
269    ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache,
270 						 "texture_units");
271    ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
272    ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
273    ctx->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxTextureUnits;
274 
275    ctx->Const.StripTextureBorder = GL_TRUE;
276 
277    i = driQueryOptioni( &rmesa->radeon.optionCache, "allow_large_textures");
278 
279    /* FIXME: When no memory manager is available we should set this
280     * to some reasonable value based on texture memory pool size */
281    ctx->Const.MaxTextureLevels = 12;
282    ctx->Const.Max3DTextureLevels = 9;
283    ctx->Const.MaxCubeTextureLevels = 12;
284    ctx->Const.MaxTextureRectSize = 2048;
285 
286    ctx->Const.MaxTextureMaxAnisotropy = 16.0;
287 
288    /* No wide points.
289     */
290    ctx->Const.MinPointSize = 1.0;
291    ctx->Const.MinPointSizeAA = 1.0;
292    ctx->Const.MaxPointSize = 1.0;
293    ctx->Const.MaxPointSizeAA = 1.0;
294 
295    ctx->Const.MinLineWidth = 1.0;
296    ctx->Const.MinLineWidthAA = 1.0;
297    ctx->Const.MaxLineWidth = 10.0;
298    ctx->Const.MaxLineWidthAA = 10.0;
299    ctx->Const.LineWidthGranularity = 0.0625;
300 
301    /* Set maxlocksize (and hence vb size) small enough to avoid
302     * fallbacks in radeon_tcl.c.  ie. guarentee that all vertices can
303     * fit in a single dma buffer for indexed rendering of quad strips,
304     * etc.
305     */
306    ctx->Const.MaxArrayLockSize =
307       MIN2( ctx->Const.MaxArrayLockSize,
308  	    RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE );
309 
310    rmesa->boxes = 0;
311 
312    ctx->Const.MaxDrawBuffers = 1;
313    ctx->Const.MaxColorAttachments = 1;
314    ctx->Const.MaxRenderbufferSize = 2048;
315 
316    _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
317 
318    /* Install the customized pipeline:
319     */
320    _tnl_destroy_pipeline( ctx );
321    _tnl_install_pipeline( ctx, radeon_pipeline );
322 
323    /* Try and keep materials and vertices separate:
324     */
325 /*    _tnl_isolate_materials( ctx, GL_TRUE ); */
326 
327    /* Configure swrast and T&L to match hardware characteristics:
328     */
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 );
333 
334 
335    for ( i = 0 ; i < RADEON_MAX_TEXTURE_UNITS ; i++ ) {
336       _math_matrix_ctr( &rmesa->TexGenMatrix[i] );
337       _math_matrix_ctr( &rmesa->tmpmat[i] );
338       _math_matrix_set_identity( &rmesa->TexGenMatrix[i] );
339       _math_matrix_set_identity( &rmesa->tmpmat[i] );
340    }
341 
342    ctx->Extensions.ARB_texture_border_clamp = true;
343    ctx->Extensions.ARB_texture_env_combine = true;
344    ctx->Extensions.ARB_texture_env_crossbar = true;
345    ctx->Extensions.ARB_texture_env_dot3 = true;
346    ctx->Extensions.EXT_fog_coord = true;
347    ctx->Extensions.EXT_packed_depth_stencil = true;
348    ctx->Extensions.EXT_secondary_color = true;
349    ctx->Extensions.EXT_texture_env_dot3 = true;
350    ctx->Extensions.EXT_texture_filter_anisotropic = true;
351    ctx->Extensions.EXT_texture_mirror_clamp = true;
352    ctx->Extensions.ATI_texture_env_combine3 = true;
353    ctx->Extensions.ATI_texture_mirror_once = true;
354    ctx->Extensions.MESA_ycbcr_texture = true;
355    ctx->Extensions.NV_blend_square = true;
356 #if FEATURE_OES_EGL_image
357    ctx->Extensions.OES_EGL_image = true;
358 #endif
359 
360    ctx->Extensions.EXT_framebuffer_object = true;
361 
362    ctx->Extensions.ARB_texture_cube_map = true;
363 
364    if (rmesa->radeon.glCtx->Mesa_DXTn) {
365       ctx->Extensions.EXT_texture_compression_s3tc = true;
366       ctx->Extensions.S3_s3tc = true;
367    }
368    else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) {
369       ctx->Extensions.EXT_texture_compression_s3tc = true;
370    }
371 
372    ctx->Extensions.NV_texture_rectangle = true;
373    ctx->Extensions.ARB_occlusion_query = true;
374 
375    /* XXX these should really go right after _mesa_init_driver_functions() */
376    radeon_fbo_init(&rmesa->radeon);
377    radeonInitSpanFuncs( ctx );
378    radeonInitIoctlFuncs( ctx );
379    radeonInitStateFuncs( ctx );
380    radeonInitState( rmesa );
381    radeonInitSwtcl( ctx );
382 
383    _mesa_vector4f_alloc( &rmesa->tcl.ObjClean, 0,
384 			 ctx->Const.MaxArrayLockSize, 32 );
385 
386    fthrottle_mode = driQueryOptioni(&rmesa->radeon.optionCache, "fthrottle_mode");
387    rmesa->radeon.iw.irq_seq = -1;
388    rmesa->radeon.irqsEmitted = 0;
389    rmesa->radeon.do_irqs = (rmesa->radeon.radeonScreen->irq != 0 &&
390 			    fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS);
391 
392    rmesa->radeon.do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
393 
394 
395 #if DO_DEBUG
396    RADEON_DEBUG = driParseDebugString( getenv( "RADEON_DEBUG" ),
397 				       debug_control );
398 #endif
399 
400    tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode");
401    if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) {
402       fprintf(stderr, "disabling 3D acceleration\n");
403       FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1);
404    } else if (tcl_mode == DRI_CONF_TCL_SW ||
405 	      !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
406       if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
407 	 rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
408 	 fprintf(stderr, "Disabling HW TCL support\n");
409       }
410       TCL_FALLBACK(rmesa->radeon.glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1);
411    }
412 
413    if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
414 /*       _tnl_need_dlist_norm_lengths( ctx, GL_FALSE ); */
415    }
416 
417    _mesa_compute_version(ctx);
418 
419    *error = __DRI_CTX_ERROR_SUCCESS;
420    return GL_TRUE;
421 }
422