r200_context.c revision 8ab6759cef6dc5101be3badce10a52d1d046f2ea
1/*
2Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3
4The Weather Channel (TM) funded Tungsten Graphics to develop the
5initial release of the Radeon 8500 driver under the XFree86 license.
6This notice must be preserved.
7
8Permission is hereby granted, free of charge, to any person obtaining
9a copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial
18portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28**************************************************************************/
29
30/*
31 * Authors:
32 *   Keith Whitwell <keithw@vmware.com>
33 */
34
35#include <stdbool.h>
36#include "main/glheader.h"
37#include "main/api_arrayelt.h"
38#include "main/api_exec.h"
39#include "main/context.h"
40#include "util/simple_list.h"
41#include "main/imports.h"
42#include "main/extensions.h"
43#include "main/version.h"
44#include "main/vtxfmt.h"
45
46#include "swrast/swrast.h"
47#include "swrast_setup/swrast_setup.h"
48#include "vbo/vbo.h"
49
50#include "tnl/tnl.h"
51#include "tnl/t_pipeline.h"
52
53#include "drivers/common/driverfuncs.h"
54
55#include "r200_context.h"
56#include "r200_ioctl.h"
57#include "r200_state.h"
58#include "r200_tex.h"
59#include "r200_swtcl.h"
60#include "r200_tcl.h"
61#include "r200_vertprog.h"
62#include "radeon_queryobj.h"
63#include "r200_blit.h"
64#include "radeon_fog.h"
65
66#include "radeon_span.h"
67
68#include "utils.h"
69#include "xmlpool.h" /* for symbolic values of enum-type options */
70
71/* Return various strings for glGetString().
72 */
73static const GLubyte *r200GetString( struct gl_context *ctx, GLenum name )
74{
75   r200ContextPtr rmesa = R200_CONTEXT(ctx);
76   static char buffer[128];
77   unsigned   offset;
78   GLuint agp_mode = (rmesa->radeon.radeonScreen->card_type == RADEON_CARD_PCI)? 0 :
79      rmesa->radeon.radeonScreen->AGPMode;
80
81   switch ( name ) {
82   case GL_VENDOR:
83      return (GLubyte *)"Mesa Project";
84
85   case GL_RENDERER:
86      offset = driGetRendererString( buffer, "R200", agp_mode );
87
88      sprintf( & buffer[ offset ], " %sTCL",
89	       !(rmesa->radeon.TclFallback & R200_TCL_FALLBACK_TCL_DISABLE)
90	       ? "" : "NO-" );
91
92      return (GLubyte *)buffer;
93
94   default:
95      return NULL;
96   }
97}
98
99
100extern const struct tnl_pipeline_stage _r200_render_stage;
101extern const struct tnl_pipeline_stage _r200_tcl_stage;
102
103static const struct tnl_pipeline_stage *r200_pipeline[] = {
104
105   /* Try and go straight to t&l
106    */
107   &_r200_tcl_stage,
108
109   /* Catch any t&l fallbacks
110    */
111   &_tnl_vertex_transform_stage,
112   &_tnl_normal_transform_stage,
113   &_tnl_lighting_stage,
114   &_tnl_fog_coordinate_stage,
115   &_tnl_texgen_stage,
116   &_tnl_texture_transform_stage,
117   &_tnl_point_attenuation_stage,
118   &_tnl_vertex_program_stage,
119   /* Try again to go to tcl?
120    *     - no good for asymmetric-twoside (do with multipass)
121    *     - no good for asymmetric-unfilled (do with multipass)
122    *     - good for material
123    *     - good for texgen
124    *     - need to manipulate a bit of state
125    *
126    * - worth it/not worth it?
127    */
128
129   /* Else do them here.
130    */
131/*    &_r200_render_stage,  */ /* FIXME: bugs with ut2003 */
132   &_tnl_render_stage,		/* FALLBACK:  */
133   NULL,
134};
135
136
137
138/* Initialize the driver's misc functions.
139 */
140static void r200InitDriverFuncs( struct dd_function_table *functions )
141{
142    functions->GetString		= r200GetString;
143}
144
145
146static void r200_emit_query_finish(radeonContextPtr radeon)
147{
148   BATCH_LOCALS(radeon);
149   struct radeon_query_object *query = radeon->query.current;
150
151   BEGIN_BATCH(4);
152   OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0));
153   OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
154   END_BATCH();
155   query->curr_offset += sizeof(uint32_t);
156   assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
157   query->emitted_begin = GL_FALSE;
158}
159
160static void r200_init_vtbl(radeonContextPtr radeon)
161{
162   radeon->vtbl.swtcl_flush = r200_swtcl_flush;
163   radeon->vtbl.fallback = r200Fallback;
164   radeon->vtbl.update_scissor = r200_vtbl_update_scissor;
165   radeon->vtbl.emit_query_finish = r200_emit_query_finish;
166   radeon->vtbl.check_blit = r200_check_blit;
167   radeon->vtbl.blit = r200_blit;
168   radeon->vtbl.is_format_renderable = radeonIsFormatRenderable;
169   radeon->vtbl.revalidate_all_buffers = r200ValidateBuffers;
170}
171
172
173/* Create the device specific rendering context.
174 */
175GLboolean r200CreateContext( gl_api api,
176			     const struct gl_config *glVisual,
177			     __DRIcontext *driContextPriv,
178			     unsigned major_version,
179			     unsigned minor_version,
180			     uint32_t flags,
181                             bool notify_reset,
182			     unsigned *error,
183			     void *sharedContextPrivate)
184{
185   __DRIscreen *sPriv = driContextPriv->driScreenPriv;
186   radeonScreenPtr screen = (radeonScreenPtr)(sPriv->driverPrivate);
187   struct dd_function_table functions;
188   r200ContextPtr rmesa;
189   struct gl_context *ctx;
190   int i;
191   int tcl_mode;
192
193   if (flags & ~__DRI_CTX_FLAG_DEBUG) {
194      *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
195      return false;
196   }
197
198   if (notify_reset) {
199      *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
200      return false;
201   }
202
203   assert(glVisual);
204   assert(driContextPriv);
205   assert(screen);
206
207   /* Allocate the R200 context */
208   rmesa = calloc(1, sizeof(*rmesa));
209   if ( !rmesa ) {
210      *error = __DRI_CTX_ERROR_NO_MEMORY;
211      return GL_FALSE;
212   }
213
214   rmesa->radeon.radeonScreen = screen;
215   r200_init_vtbl(&rmesa->radeon);
216   /* init exp fog table data */
217   radeonInitStaticFogData();
218
219   /* Parse configuration files.
220    * Do this here so that initialMaxAnisotropy is set before we create
221    * the default textures.
222    */
223   driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache,
224			screen->driScreen->myNum, "r200");
225   rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache,
226							"def_max_anisotropy");
227
228   if ( sPriv->drm_version.major == 1
229       && driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) {
230      if ( sPriv->drm_version.minor < 13 )
231	 fprintf( stderr, "DRM version 1.%d too old to support HyperZ, "
232			  "disabling.\n", sPriv->drm_version.minor );
233      else
234	 rmesa->using_hyperz = GL_TRUE;
235   }
236
237   if ( sPriv->drm_version.minor >= 15 )
238      rmesa->texmicrotile = GL_TRUE;
239
240   /* Init default driver functions then plug in our R200-specific functions
241    * (the texture functions are especially important)
242    */
243   _mesa_init_driver_functions(&functions);
244   r200InitDriverFuncs(&functions);
245   r200InitIoctlFuncs(&functions);
246   r200InitStateFuncs(&rmesa->radeon, &functions);
247   r200InitTextureFuncs(&rmesa->radeon, &functions);
248   r200InitShaderFuncs(&functions);
249   radeonInitQueryObjFunctions(&functions);
250
251   if (!radeonInitContext(&rmesa->radeon, api, &functions,
252			  glVisual, driContextPriv,
253			  sharedContextPrivate)) {
254     free(rmesa);
255     *error = __DRI_CTX_ERROR_NO_MEMORY;
256     return GL_FALSE;
257   }
258
259   rmesa->radeon.swtcl.RenderIndex = ~0;
260   rmesa->radeon.hw.all_dirty = 1;
261
262   ctx = &rmesa->radeon.glCtx;
263
264   driContextSetFlags(ctx, flags);
265
266   /* Initialize the software rasterizer and helper modules.
267    */
268   _swrast_CreateContext( ctx );
269   _vbo_CreateContext( ctx );
270   _tnl_CreateContext( ctx );
271   _swsetup_CreateContext( ctx );
272   _ae_create_context( ctx );
273
274   ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache,
275						 "texture_units");
276   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
277   ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
278
279   ctx->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxTextureUnits;
280
281   ctx->Const.StripTextureBorder = GL_TRUE;
282
283   /* FIXME: When no memory manager is available we should set this
284    * to some reasonable value based on texture memory pool size */
285   ctx->Const.MaxTextureLevels = 12;
286   ctx->Const.Max3DTextureLevels = 9;
287   ctx->Const.MaxCubeTextureLevels = 12;
288   ctx->Const.MaxTextureRectSize = 2048;
289   ctx->Const.MaxRenderbufferSize = 2048;
290
291   ctx->Const.MaxTextureMaxAnisotropy = 16.0;
292
293   /* No wide AA points.
294    */
295   ctx->Const.MinPointSize = 1.0;
296   ctx->Const.MinPointSizeAA = 1.0;
297   ctx->Const.MaxPointSizeAA = 1.0;
298   ctx->Const.PointSizeGranularity = 0.0625;
299   ctx->Const.MaxPointSize = 2047.0;
300
301   /* mesa initialization problem - _mesa_init_point was already called */
302   ctx->Point.MaxSize = ctx->Const.MaxPointSize;
303
304   ctx->Const.MinLineWidth = 1.0;
305   ctx->Const.MinLineWidthAA = 1.0;
306   ctx->Const.MaxLineWidth = 10.0;
307   ctx->Const.MaxLineWidthAA = 10.0;
308   ctx->Const.LineWidthGranularity = 0.0625;
309
310   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeInstructions = R200_VSF_MAX_INST;
311   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeAttribs = 12;
312   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeTemps = R200_VSF_MAX_TEMPS;
313   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeParameters = R200_VSF_MAX_PARAM;
314   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeAddressRegs = 1;
315
316   ctx->Const.MaxDrawBuffers = 1;
317   ctx->Const.MaxColorAttachments = 1;
318
319   ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS = GL_TRUE;
320
321   /* Install the customized pipeline:
322    */
323   _tnl_destroy_pipeline( ctx );
324   _tnl_install_pipeline( ctx, r200_pipeline );
325
326   /* Try and keep materials and vertices separate:
327    */
328/*    _tnl_isolate_materials( ctx, GL_TRUE ); */
329
330
331   /* Configure swrast and TNL to match hardware characteristics:
332    */
333   _swrast_allow_pixel_fog( ctx, GL_FALSE );
334   _swrast_allow_vertex_fog( ctx, GL_TRUE );
335   _tnl_allow_pixel_fog( ctx, GL_FALSE );
336   _tnl_allow_vertex_fog( ctx, GL_TRUE );
337
338
339   for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
340      _math_matrix_ctr( &rmesa->TexGenMatrix[i] );
341      _math_matrix_set_identity( &rmesa->TexGenMatrix[i] );
342   }
343   _math_matrix_ctr( &rmesa->tmpmat );
344   _math_matrix_set_identity( &rmesa->tmpmat );
345
346   ctx->Extensions.ARB_occlusion_query = true;
347   ctx->Extensions.ARB_point_sprite = true;
348   ctx->Extensions.ARB_texture_border_clamp = true;
349   ctx->Extensions.ARB_texture_cube_map = true;
350   ctx->Extensions.ARB_texture_env_combine = true;
351   ctx->Extensions.ARB_texture_env_dot3 = true;
352   ctx->Extensions.ARB_texture_env_crossbar = true;
353   ctx->Extensions.ARB_texture_mirror_clamp_to_edge = true;
354   ctx->Extensions.ARB_vertex_program = true;
355   ctx->Extensions.ATI_fragment_shader = (ctx->Const.MaxTextureUnits == 6);
356   ctx->Extensions.ATI_texture_env_combine3 = true;
357   ctx->Extensions.ATI_texture_mirror_once = true;
358   ctx->Extensions.EXT_blend_color = true;
359   ctx->Extensions.EXT_blend_equation_separate = true;
360   ctx->Extensions.EXT_blend_func_separate = true;
361   ctx->Extensions.EXT_blend_minmax = true;
362   ctx->Extensions.EXT_gpu_program_parameters = true;
363   ctx->Extensions.EXT_point_parameters = true;
364   ctx->Extensions.EXT_texture_env_dot3 = true;
365   ctx->Extensions.EXT_texture_filter_anisotropic = true;
366   ctx->Extensions.EXT_texture_mirror_clamp = true;
367   ctx->Extensions.MESA_pack_invert = true;
368   ctx->Extensions.NV_texture_rectangle = true;
369   ctx->Extensions.OES_EGL_image = true;
370
371   if (!(rmesa->radeon.radeonScreen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) {
372     /* yuv textures don't work with some chips - R200 / rv280 okay so far
373	others get the bit ordering right but don't actually do YUV-RGB conversion */
374      ctx->Extensions.MESA_ycbcr_texture = true;
375   }
376   if (rmesa->radeon.glCtx.Mesa_DXTn) {
377      ctx->Extensions.EXT_texture_compression_s3tc = true;
378      ctx->Extensions.ANGLE_texture_compression_dxt = true;
379   }
380   else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) {
381      ctx->Extensions.EXT_texture_compression_s3tc = true;
382      ctx->Extensions.ANGLE_texture_compression_dxt = true;
383   }
384
385#if 0
386   r200InitDriverFuncs( ctx );
387   r200InitIoctlFuncs( ctx );
388   r200InitStateFuncs( ctx );
389   r200InitTextureFuncs( ctx );
390#endif
391   /* plug in a few more device driver functions */
392   /* XXX these should really go right after _mesa_init_driver_functions() */
393   radeon_fbo_init(&rmesa->radeon);
394   radeonInitSpanFuncs( ctx );
395   r200InitTnlFuncs( ctx );
396   r200InitState( rmesa );
397   r200InitSwtcl( ctx );
398
399   rmesa->prefer_gart_client_texturing =
400      (getenv("R200_GART_CLIENT_TEXTURES") != 0);
401
402   tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode");
403   if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) {
404      fprintf(stderr, "disabling 3D acceleration\n");
405      FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
406   }
407   else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") ||
408	    !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
409      if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
410	 rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
411	 fprintf(stderr, "Disabling HW TCL support\n");
412      }
413      TCL_FALLBACK(&rmesa->radeon.glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
414   }
415
416   _mesa_compute_version(ctx);
417
418   /* Exec table initialization requires the version to be computed */
419   _mesa_initialize_dispatch_tables(ctx);
420   _mesa_initialize_vbo_vtxfmt(ctx);
421
422   *error = __DRI_CTX_ERROR_SUCCESS;
423   return GL_TRUE;
424}
425
426
427void r200DestroyContext( __DRIcontext *driContextPriv )
428{
429	int i;
430	r200ContextPtr rmesa = (r200ContextPtr)driContextPriv->driverPrivate;
431	if (rmesa)
432	{
433		for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
434			_math_matrix_dtr( &rmesa->TexGenMatrix[i] );
435		}
436	}
437	radeonDestroyContext(driContextPriv);
438}
439