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 "main/imports.h"
41#include "main/extensions.h"
42#include "main/version.h"
43#include "main/vtxfmt.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 */
72static 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 *)"Mesa Project";
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
99extern const struct tnl_pipeline_stage _r200_render_stage;
100extern const struct tnl_pipeline_stage _r200_tcl_stage;
101
102static 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 */
139static void r200InitDriverFuncs( struct dd_function_table *functions )
140{
141    functions->GetString		= r200GetString;
142}
143
144
145static void r200_emit_query_finish(radeonContextPtr radeon)
146{
147   BATCH_LOCALS(radeon);
148   struct radeon_query_object *query = radeon->query.current;
149
150   BEGIN_BATCH(4);
151   OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0));
152   OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
153   END_BATCH();
154   query->curr_offset += sizeof(uint32_t);
155   assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
156   query->emitted_begin = GL_FALSE;
157}
158
159static void r200_init_vtbl(radeonContextPtr radeon)
160{
161   radeon->vtbl.swtcl_flush = r200_swtcl_flush;
162   radeon->vtbl.fallback = r200Fallback;
163   radeon->vtbl.update_scissor = r200_vtbl_update_scissor;
164   radeon->vtbl.emit_query_finish = r200_emit_query_finish;
165   radeon->vtbl.check_blit = r200_check_blit;
166   radeon->vtbl.blit = r200_blit;
167   radeon->vtbl.is_format_renderable = radeonIsFormatRenderable;
168   radeon->vtbl.revalidate_all_buffers = r200ValidateBuffers;
169}
170
171
172/* Create the device specific rendering context.
173 */
174GLboolean r200CreateContext( gl_api api,
175			     const struct gl_config *glVisual,
176			     __DRIcontext *driContextPriv,
177			     unsigned major_version,
178			     unsigned minor_version,
179			     uint32_t flags,
180                             bool notify_reset,
181			     unsigned *error,
182			     void *sharedContextPrivate)
183{
184   __DRIscreen *sPriv = driContextPriv->driScreenPriv;
185   radeonScreenPtr screen = (radeonScreenPtr)(sPriv->driverPrivate);
186   struct dd_function_table functions;
187   r200ContextPtr rmesa;
188   struct gl_context *ctx;
189   int i;
190   int tcl_mode;
191
192   if (flags & ~__DRI_CTX_FLAG_DEBUG) {
193      *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
194      return false;
195   }
196
197   if (notify_reset) {
198      *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
199      return false;
200   }
201
202   assert(glVisual);
203   assert(driContextPriv);
204   assert(screen);
205
206   /* Allocate the R200 context */
207   rmesa = calloc(1, sizeof(*rmesa));
208   if ( !rmesa ) {
209      *error = __DRI_CTX_ERROR_NO_MEMORY;
210      return GL_FALSE;
211   }
212
213   rmesa->radeon.radeonScreen = screen;
214   r200_init_vtbl(&rmesa->radeon);
215   /* init exp fog table data */
216   radeonInitStaticFogData();
217
218   /* Parse configuration files.
219    * Do this here so that initialMaxAnisotropy is set before we create
220    * the default textures.
221    */
222   driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache,
223			screen->driScreen->myNum, "r200");
224   rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache,
225							"def_max_anisotropy");
226
227   if (driQueryOptionb( &rmesa->radeon.optionCache, "hyperz"))
228      rmesa->using_hyperz = GL_TRUE;
229
230   /* Init default driver functions then plug in our R200-specific functions
231    * (the texture functions are especially important)
232    */
233   _mesa_init_driver_functions(&functions);
234   r200InitDriverFuncs(&functions);
235   r200InitIoctlFuncs(&functions);
236   r200InitStateFuncs(&rmesa->radeon, &functions);
237   r200InitTextureFuncs(&rmesa->radeon, &functions);
238   r200InitShaderFuncs(&functions);
239   radeonInitQueryObjFunctions(&functions);
240
241   if (!radeonInitContext(&rmesa->radeon, api, &functions,
242			  glVisual, driContextPriv,
243			  sharedContextPrivate)) {
244     free(rmesa);
245     *error = __DRI_CTX_ERROR_NO_MEMORY;
246     return GL_FALSE;
247   }
248
249   rmesa->radeon.swtcl.RenderIndex = ~0;
250   rmesa->radeon.hw.all_dirty = 1;
251
252   ctx = &rmesa->radeon.glCtx;
253
254   driContextSetFlags(ctx, flags);
255
256   /* Initialize the software rasterizer and helper modules.
257    */
258   _swrast_CreateContext( ctx );
259   _vbo_CreateContext( ctx );
260   _tnl_CreateContext( ctx );
261   _swsetup_CreateContext( ctx );
262   _ae_create_context( ctx );
263
264   ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache,
265						 "texture_units");
266   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
267   ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
268
269   ctx->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxTextureUnits;
270
271   ctx->Const.StripTextureBorder = GL_TRUE;
272
273   /* FIXME: When no memory manager is available we should set this
274    * to some reasonable value based on texture memory pool size */
275   ctx->Const.MaxTextureLevels = 12;
276   ctx->Const.Max3DTextureLevels = 9;
277   ctx->Const.MaxCubeTextureLevels = 12;
278   ctx->Const.MaxTextureRectSize = 2048;
279   ctx->Const.MaxRenderbufferSize = 2048;
280
281   ctx->Const.MaxTextureMaxAnisotropy = 16.0;
282
283   /* No wide AA points.
284    */
285   ctx->Const.MinPointSize = 1.0;
286   ctx->Const.MinPointSizeAA = 1.0;
287   ctx->Const.MaxPointSizeAA = 1.0;
288   ctx->Const.PointSizeGranularity = 0.0625;
289   ctx->Const.MaxPointSize = 2047.0;
290
291   /* mesa initialization problem - _mesa_init_point was already called */
292   ctx->Point.MaxSize = ctx->Const.MaxPointSize;
293
294   ctx->Const.MinLineWidth = 1.0;
295   ctx->Const.MinLineWidthAA = 1.0;
296   ctx->Const.MaxLineWidth = 10.0;
297   ctx->Const.MaxLineWidthAA = 10.0;
298   ctx->Const.LineWidthGranularity = 0.0625;
299
300   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeInstructions = R200_VSF_MAX_INST;
301   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeAttribs = 12;
302   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeTemps = R200_VSF_MAX_TEMPS;
303   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeParameters = R200_VSF_MAX_PARAM;
304   ctx->Const.Program[MESA_SHADER_VERTEX].MaxNativeAddressRegs = 1;
305
306   ctx->Const.MaxDrawBuffers = 1;
307   ctx->Const.MaxColorAttachments = 1;
308
309   ctx->Const.ShaderCompilerOptions[MESA_SHADER_VERTEX].OptimizeForAOS = GL_TRUE;
310
311   /* Install the customized pipeline:
312    */
313   _tnl_destroy_pipeline( ctx );
314   _tnl_install_pipeline( ctx, r200_pipeline );
315
316   /* Try and keep materials and vertices separate:
317    */
318/*    _tnl_isolate_materials( ctx, GL_TRUE ); */
319
320
321   /* Configure swrast and TNL to match hardware characteristics:
322    */
323   _swrast_allow_pixel_fog( ctx, GL_FALSE );
324   _swrast_allow_vertex_fog( ctx, GL_TRUE );
325   _tnl_allow_pixel_fog( ctx, GL_FALSE );
326   _tnl_allow_vertex_fog( ctx, GL_TRUE );
327
328
329   for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
330      _math_matrix_ctr( &rmesa->TexGenMatrix[i] );
331      _math_matrix_set_identity( &rmesa->TexGenMatrix[i] );
332   }
333   _math_matrix_ctr( &rmesa->tmpmat );
334   _math_matrix_set_identity( &rmesa->tmpmat );
335
336   ctx->Extensions.ARB_occlusion_query = true;
337   ctx->Extensions.ARB_point_sprite = true;
338   ctx->Extensions.ARB_texture_border_clamp = true;
339   ctx->Extensions.ARB_texture_cube_map = true;
340   ctx->Extensions.ARB_texture_env_combine = true;
341   ctx->Extensions.ARB_texture_env_dot3 = true;
342   ctx->Extensions.ARB_texture_env_crossbar = true;
343   ctx->Extensions.ARB_texture_mirror_clamp_to_edge = true;
344   ctx->Extensions.ARB_vertex_program = true;
345   ctx->Extensions.ATI_fragment_shader = (ctx->Const.MaxTextureUnits == 6);
346   ctx->Extensions.ATI_texture_env_combine3 = true;
347   ctx->Extensions.ATI_texture_mirror_once = true;
348   ctx->Extensions.EXT_blend_color = true;
349   ctx->Extensions.EXT_blend_equation_separate = true;
350   ctx->Extensions.EXT_blend_func_separate = true;
351   ctx->Extensions.EXT_blend_minmax = true;
352   ctx->Extensions.EXT_gpu_program_parameters = true;
353   ctx->Extensions.EXT_point_parameters = true;
354   ctx->Extensions.EXT_texture_env_dot3 = true;
355   ctx->Extensions.EXT_texture_filter_anisotropic = true;
356   ctx->Extensions.EXT_texture_mirror_clamp = true;
357   ctx->Extensions.MESA_pack_invert = true;
358   ctx->Extensions.NV_texture_rectangle = true;
359   ctx->Extensions.OES_EGL_image = true;
360
361   if (!(rmesa->radeon.radeonScreen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) {
362     /* yuv textures don't work with some chips - R200 / rv280 okay so far
363	others get the bit ordering right but don't actually do YUV-RGB conversion */
364      ctx->Extensions.MESA_ycbcr_texture = true;
365   }
366   if (rmesa->radeon.glCtx.Mesa_DXTn) {
367      ctx->Extensions.EXT_texture_compression_s3tc = true;
368      ctx->Extensions.ANGLE_texture_compression_dxt = true;
369   }
370   else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) {
371      ctx->Extensions.EXT_texture_compression_s3tc = true;
372      ctx->Extensions.ANGLE_texture_compression_dxt = true;
373   }
374
375#if 0
376   r200InitDriverFuncs( ctx );
377   r200InitIoctlFuncs( ctx );
378   r200InitStateFuncs( ctx );
379   r200InitTextureFuncs( ctx );
380#endif
381   /* plug in a few more device driver functions */
382   /* XXX these should really go right after _mesa_init_driver_functions() */
383   radeon_fbo_init(&rmesa->radeon);
384   radeonInitSpanFuncs( ctx );
385   r200InitTnlFuncs( ctx );
386   r200InitState( rmesa );
387   r200InitSwtcl( ctx );
388
389   rmesa->prefer_gart_client_texturing =
390      (getenv("R200_GART_CLIENT_TEXTURES") != 0);
391
392   tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode");
393   if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) {
394      fprintf(stderr, "disabling 3D acceleration\n");
395      FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1);
396   }
397   else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") ||
398	    !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) {
399      if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) {
400	 rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL;
401	 fprintf(stderr, "Disabling HW TCL support\n");
402      }
403      TCL_FALLBACK(&rmesa->radeon.glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1);
404   }
405
406   _mesa_compute_version(ctx);
407
408   /* Exec table initialization requires the version to be computed */
409   _mesa_initialize_dispatch_tables(ctx);
410   _mesa_initialize_vbo_vtxfmt(ctx);
411
412   *error = __DRI_CTX_ERROR_SUCCESS;
413   return GL_TRUE;
414}
415
416
417void r200DestroyContext( __DRIcontext *driContextPriv )
418{
419	int i;
420	r200ContextPtr rmesa = (r200ContextPtr)driContextPriv->driverPrivate;
421	if (rmesa)
422	{
423		for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) {
424			_math_matrix_dtr( &rmesa->TexGenMatrix[i] );
425		}
426	}
427	radeonDestroyContext(driContextPriv);
428}
429