1 /*
2 Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3 
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.
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  *   Keith Whitwell <keith@tungstengraphics.com>
33  */
34 
35 #include <stdbool.h>
36 #include "main/glheader.h"
37 #include "main/api_arrayelt.h"
38 #include "main/context.h"
39 #include "main/simple_list.h"
40 #include "main/imports.h"
41 #include "main/extensions.h"
42 #include "main/mfeatures.h"
43 #include "main/version.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_tex.h"
58 #include "r200_swtcl.h"
59 #include "r200_tcl.h"
60 #include "r200_vertprog.h"
61 #include "radeon_queryobj.h"
62 #include "r200_blit.h"
63 #include "radeon_fog.h"
64 
65 #include "radeon_span.h"
66 
67 #include "utils.h"
68 #include "xmlpool.h" /* for symbolic values of enum-type options */
69 
70 /* Return various strings for glGetString().
71  */
r200GetString(struct gl_context * ctx,GLenum name)72 static const GLubyte *r200GetString( struct gl_context *ctx, GLenum name )
73 {
74    r200ContextPtr rmesa = R200_CONTEXT(ctx);
75    static char buffer[128];
76    unsigned   offset;
77    GLuint agp_mode = (rmesa->radeon.radeonScreen->card_type == RADEON_CARD_PCI)? 0 :
78       rmesa->radeon.radeonScreen->AGPMode;
79 
80    switch ( name ) {
81    case GL_VENDOR:
82       return (GLubyte *)"Tungsten Graphics, Inc.";
83 
84    case GL_RENDERER:
85       offset = driGetRendererString( buffer, "R200", agp_mode );
86 
87       sprintf( & buffer[ offset ], " %sTCL",
88 	       !(rmesa->radeon.TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
89 	       ? "" : "NO-" );
90 
91       return (GLubyte *)buffer;
92 
93    default:
94       return NULL;
95    }
96 }
97 
98 
99 extern const struct tnl_pipeline_stage _r200_render_stage;
100 extern const struct tnl_pipeline_stage _r200_tcl_stage;
101 
102 static const struct tnl_pipeline_stage *r200_pipeline[] = {
103 
104    /* Try and go straight to t&l
105     */
106    &_r200_tcl_stage,
107 
108    /* Catch any t&l fallbacks
109     */
110    &_tnl_vertex_transform_stage,
111    &_tnl_normal_transform_stage,
112    &_tnl_lighting_stage,
113    &_tnl_fog_coordinate_stage,
114    &_tnl_texgen_stage,
115    &_tnl_texture_transform_stage,
116    &_tnl_point_attenuation_stage,
117    &_tnl_vertex_program_stage,
118    /* Try again to go to tcl?
119     *     - no good for asymmetric-twoside (do with multipass)
120     *     - no good for asymmetric-unfilled (do with multipass)
121     *     - good for material
122     *     - good for texgen
123     *     - need to manipulate a bit of state
124     *
125     * - worth it/not worth it?
126     */
127 
128    /* Else do them here.
129     */
130 /*    &_r200_render_stage,  */ /* FIXME: bugs with ut2003 */
131    &_tnl_render_stage,		/* FALLBACK:  */
132    NULL,
133 };
134 
135 
136 
137 /* Initialize the driver's misc functions.
138  */
r200InitDriverFuncs(struct dd_function_table * functions)139 static void r200InitDriverFuncs( struct dd_function_table *functions )
140 {
141     functions->GetBufferSize		= NULL; /* OBSOLETE */
142     functions->GetString		= r200GetString;
143 }
144 
145 
r200_get_lock(radeonContextPtr radeon)146 static void r200_get_lock(radeonContextPtr radeon)
147 {
148    r200ContextPtr rmesa = (r200ContextPtr)radeon;
149    drm_radeon_sarea_t *sarea = radeon->sarea;
150 
151    R200_STATECHANGE( rmesa, ctx );
152    if (rmesa->radeon.sarea->tiling_enabled) {
153       rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
154    }
155    else rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &= ~R200_COLOR_TILE_ENABLE;
156 
157    if ( sarea->ctx_owner != rmesa->radeon.dri.hwContext ) {
158       sarea->ctx_owner = rmesa->radeon.dri.hwContext;
159    }
160 
161 }
162 
r200_vtbl_emit_cs_header(struct radeon_cs * cs,radeonContextPtr rmesa)163 static void r200_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa)
164 {
165 }
166 
r200_emit_query_finish(radeonContextPtr radeon)167 static void r200_emit_query_finish(radeonContextPtr radeon)
168 {
169    BATCH_LOCALS(radeon);
170    struct radeon_query_object *query = radeon->query.current;
171 
172    BEGIN_BATCH_NO_AUTOSTATE(4);
173    OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0));
174    OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
175    END_BATCH();
176    query->curr_offset += sizeof(uint32_t);
177    assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
178    query->emitted_begin = GL_FALSE;
179 }
180 
r200_init_vtbl(radeonContextPtr radeon)181 static void r200_init_vtbl(radeonContextPtr radeon)
182 {
183    radeon->vtbl.get_lock = r200_get_lock;
184    radeon->vtbl.update_viewport_offset = r200UpdateViewportOffset;
185    radeon->vtbl.emit_cs_header = r200_vtbl_emit_cs_header;
186    radeon->vtbl.swtcl_flush = r200_swtcl_flush;
187    radeon->vtbl.fallback = r200Fallback;
188    radeon->vtbl.update_scissor = r200_vtbl_update_scissor;
189    radeon->vtbl.emit_query_finish = r200_emit_query_finish;
190    radeon->vtbl.check_blit = r200_check_blit;
191    radeon->vtbl.blit = r200_blit;
192    radeon->vtbl.is_format_renderable = radeonIsFormatRenderable;
193 }
194 
195 
196 /* Create the device specific rendering context.
197  */
r200CreateContext(gl_api api,const struct gl_config * glVisual,__DRIcontext * driContextPriv,unsigned major_version,unsigned minor_version,uint32_t flags,unsigned * error,void * sharedContextPrivate)198 GLboolean r200CreateContext( gl_api api,
199 			     const struct gl_config *glVisual,
200 			     __DRIcontext *driContextPriv,
201 			     unsigned major_version,
202 			     unsigned minor_version,
203 			     uint32_t flags,
204 			     unsigned *error,
205 			     void *sharedContextPrivate)
206 {
207    __DRIscreen *sPriv = driContextPriv->driScreenPriv;
208    radeonScreenPtr screen = (radeonScreenPtr)(sPriv->driverPrivate);
209    struct dd_function_table functions;
210    r200ContextPtr rmesa;
211    struct gl_context *ctx;
212    int i;
213    int tcl_mode;
214 
215    switch (api) {
216    case API_OPENGL:
217       if (major_version > 1 || minor_version > 3) {
218          *error = __DRI_CTX_ERROR_BAD_VERSION;
219          return GL_FALSE;
220       }
221       break;
222    case API_OPENGLES:
223       break;
224    default:
225       *error = __DRI_CTX_ERROR_BAD_API;
226       return GL_FALSE;
227    }
228 
229    /* Flag filtering is handled in dri2CreateContextAttribs.
230     */
231    (void) flags;
232 
233    assert(glVisual);
234    assert(driContextPriv);
235    assert(screen);
236 
237    /* Allocate the R200 context */
238    rmesa = (r200ContextPtr) CALLOC( sizeof(*rmesa) );
239    if ( !rmesa ) {
240       *error = __DRI_CTX_ERROR_NO_MEMORY;
241       return GL_FALSE;
242    }
243 
244    rmesa->radeon.radeonScreen = screen;
245    r200_init_vtbl(&rmesa->radeon);
246    /* init exp fog table data */
247    radeonInitStaticFogData();
248 
249    /* Parse configuration files.
250     * Do this here so that initialMaxAnisotropy is set before we create
251     * the default textures.
252     */
253    driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache,
254 			screen->driScreen->myNum, "r200");
255    rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache,
256 							"def_max_anisotropy");
257 
258    if ( sPriv->drm_version.major == 1
259        && driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) {
260       if ( sPriv->drm_version.minor < 13 )
261 	 fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
262 			  "disabling.\n", sPriv->drm_version.minor );
263       else
264 	 rmesa->using_hyperz = GL_TRUE;
265    }
266 
267    if ( sPriv->drm_version.minor >= 15 )
268       rmesa->texmicrotile = GL_TRUE;
269 
270    /* Init default driver functions then plug in our R200-specific functions
271     * (the texture functions are especially important)
272     */
273    _mesa_init_driver_functions(&functions);
274    r200InitDriverFuncs(&functions);
275    r200InitIoctlFuncs(&functions);
276    r200InitStateFuncs(&rmesa->radeon, &functions);
277    r200InitTextureFuncs(&rmesa->radeon, &functions);
278    r200InitShaderFuncs(&functions);
279    radeonInitQueryObjFunctions(&functions);
280 
281    if (!radeonInitContext(&rmesa->radeon, &functions,
282 			  glVisual, driContextPriv,
283 			  sharedContextPrivate)) {
284      FREE(rmesa);
285      *error = __DRI_CTX_ERROR_NO_MEMORY;
286      return GL_FALSE;
287    }
288 
289    rmesa->radeon.swtcl.RenderIndex = ~0;
290    rmesa->radeon.hw.all_dirty = 1;
291 
292    ctx = rmesa->radeon.glCtx;
293    /* Initialize the software rasterizer and helper modules.
294     */
295    _swrast_CreateContext( ctx );
296    _vbo_CreateContext( ctx );
297    _tnl_CreateContext( ctx );
298    _swsetup_CreateContext( ctx );
299    _ae_create_context( ctx );
300 
301    /* Set the maximum texture size small enough that we can guarentee that
302     * all texture units can bind a maximal texture and have all of them in
303     * texturable memory at once. Depending on the allow_large_textures driconf
304     * setting allow larger textures.
305     */
306    ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache,
307 						 "texture_units");
308    ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
309    ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
310 
311    ctx->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxTextureUnits;
312 
313    ctx->Const.StripTextureBorder = GL_TRUE;
314 
315    i = driQueryOptioni( &rmesa->radeon.optionCache, "allow_large_textures");
316 
317    /* FIXME: When no memory manager is available we should set this
318     * to some reasonable value based on texture memory pool size */
319    ctx->Const.MaxTextureLevels = 12;
320    ctx->Const.Max3DTextureLevels = 9;
321    ctx->Const.MaxCubeTextureLevels = 12;
322    ctx->Const.MaxTextureRectSize = 2048;
323    ctx->Const.MaxRenderbufferSize = 2048;
324 
325    ctx->Const.MaxTextureMaxAnisotropy = 16.0;
326 
327    /* No wide AA points.
328     */
329    ctx->Const.MinPointSize = 1.0;
330    ctx->Const.MinPointSizeAA = 1.0;
331    ctx->Const.MaxPointSizeAA = 1.0;
332    ctx->Const.PointSizeGranularity = 0.0625;
333    ctx->Const.MaxPointSize = 2047.0;
334 
335    /* mesa initialization problem - _mesa_init_point was already called */
336    ctx->Point.MaxSize = ctx->Const.MaxPointSize;
337 
338    ctx->Const.MinLineWidth = 1.0;
339    ctx->Const.MinLineWidthAA = 1.0;
340    ctx->Const.MaxLineWidth = 10.0;
341    ctx->Const.MaxLineWidthAA = 10.0;
342    ctx->Const.LineWidthGranularity = 0.0625;
343 
344    ctx->Const.VertexProgram.MaxNativeInstructions = R200_VSF_MAX_INST;
345    ctx->Const.VertexProgram.MaxNativeAttribs = 12;
346    ctx->Const.VertexProgram.MaxNativeTemps = R200_VSF_MAX_TEMPS;
347    ctx->Const.VertexProgram.MaxNativeParameters = R200_VSF_MAX_PARAM;
348    ctx->Const.VertexProgram.MaxNativeAddressRegs = 1;
349 
350    ctx->Const.MaxDrawBuffers = 1;
351    ctx->Const.MaxColorAttachments = 1;
352 
353    _mesa_set_mvp_with_dp4( ctx, GL_TRUE );
354 
355    /* Install the customized pipeline:
356     */
357    _tnl_destroy_pipeline( ctx );
358    _tnl_install_pipeline( ctx, r200_pipeline );
359 
360    /* Try and keep materials and vertices separate:
361     */
362 /*    _tnl_isolate_materials( ctx, GL_TRUE ); */
363 
364 
365    /* Configure swrast and TNL to match hardware characteristics:
366     */
367    _swrast_allow_pixel_fog( ctx, GL_FALSE );
368    _swrast_allow_vertex_fog( ctx, GL_TRUE );
369    _tnl_allow_pixel_fog( ctx, GL_FALSE );
370    _tnl_allow_vertex_fog( ctx, GL_TRUE );
371 
372 
373    for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
374       _math_matrix_ctr( &rmesa->TexGenMatrix[i] );
375       _math_matrix_set_identity( &rmesa->TexGenMatrix[i] );
376    }
377    _math_matrix_ctr( &rmesa->tmpmat );
378    _math_matrix_set_identity( &rmesa->tmpmat );
379 
380    ctx->Extensions.ARB_half_float_pixel = true;
381    ctx->Extensions.ARB_occlusion_query = true;
382    ctx->Extensions.ARB_texture_border_clamp = true;
383    ctx->Extensions.ARB_texture_env_combine = true;
384    ctx->Extensions.ARB_texture_env_dot3 = true;
385    ctx->Extensions.ARB_texture_env_crossbar = true;
386    ctx->Extensions.EXT_blend_color = true;
387    ctx->Extensions.EXT_blend_minmax = true;
388    ctx->Extensions.EXT_fog_coord = true;
389    ctx->Extensions.EXT_packed_depth_stencil = true;
390    ctx->Extensions.EXT_secondary_color = true;
391    ctx->Extensions.EXT_texture_env_dot3 = true;
392    ctx->Extensions.EXT_texture_filter_anisotropic = true;
393    ctx->Extensions.EXT_texture_mirror_clamp = true;
394    ctx->Extensions.ATI_texture_env_combine3 = true;
395    ctx->Extensions.ATI_texture_mirror_once = true;
396    ctx->Extensions.MESA_pack_invert = true;
397    ctx->Extensions.NV_blend_square = true;
398    ctx->Extensions.NV_texture_rectangle = true;
399 #if FEATURE_OES_EGL_image
400    ctx->Extensions.OES_EGL_image = true;
401 #endif
402 
403    ctx->Extensions.EXT_framebuffer_object = true;
404    ctx->Extensions.ARB_occlusion_query = true;
405 
406    if (!(rmesa->radeon.radeonScreen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) {
407      /* yuv textures don't work with some chips - R200 / rv280 okay so far
408 	others get the bit ordering right but don't actually do YUV-RGB conversion */
409       ctx->Extensions.MESA_ycbcr_texture = true;
410    }
411    if (rmesa->radeon.glCtx->Mesa_DXTn) {
412       ctx->Extensions.EXT_texture_compression_s3tc = true;
413       ctx->Extensions.S3_s3tc = true;
414    }
415    else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) {
416       ctx->Extensions.EXT_texture_compression_s3tc = true;
417    }
418 
419    ctx->Extensions.ARB_texture_cube_map = true;
420 
421    ctx->Extensions.EXT_blend_equation_separate = true;
422    ctx->Extensions.EXT_blend_func_separate = true;
423 
424    ctx->Extensions.ARB_vertex_program = true;
425    ctx->Extensions.EXT_gpu_program_parameters = true;
426 
427    ctx->Extensions.NV_vertex_program =
428       driQueryOptionb(&rmesa->radeon.optionCache, "nv_vertex_program");
429 
430    ctx->Extensions.ATI_fragment_shader = (ctx->Const.MaxTextureUnits == 6);
431 
432    ctx->Extensions.ARB_point_sprite = true;
433    ctx->Extensions.EXT_point_parameters = true;
434 
435 #if 0
436    r200InitDriverFuncs( ctx );
437    r200InitIoctlFuncs( ctx );
438    r200InitStateFuncs( ctx );
439    r200InitTextureFuncs( ctx );
440 #endif
441    /* plug in a few more device driver functions */
442    /* XXX these should really go right after _mesa_init_driver_functions() */
443    radeon_fbo_init(&rmesa->radeon);
444    radeonInitSpanFuncs( ctx );
445    r200InitTnlFuncs( ctx );
446    r200InitState( rmesa );
447    r200InitSwtcl( ctx );
448 
449    rmesa->prefer_gart_client_texturing =
450       (getenv("R200_GART_CLIENT_TEXTURES") != 0);
451 
452    tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode");
453    if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) {
454       fprintf(stderr, "disabling 3D acceleration\n");
455       FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
456    }
457    else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") ||
458 	    !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
459       if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
460 	 rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
461 	 fprintf(stderr, "Disabling HW TCL support\n");
462       }
463       TCL_FALLBACK(rmesa->radeon.glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
464    }
465 
466    _mesa_compute_version(ctx);
467 
468    *error = __DRI_CTX_ERROR_SUCCESS;
469    return GL_TRUE;
470 }
471 
472 
r200DestroyContext(__DRIcontext * driContextPriv)473 void r200DestroyContext( __DRIcontext *driContextPriv )
474 {
475 	int i;
476 	r200ContextPtr rmesa = (r200ContextPtr)driContextPriv->driverPrivate;
477 	if (rmesa)
478 	{
479 		for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
480 			_math_matrix_dtr( &rmesa->TexGenMatrix[i] );
481 		}
482 	}
483 	radeonDestroyContext(driContextPriv);
484 }
485