applied Felix's patch for configuration system
[mesa.git] / src / mesa / drivers / dri / r200 / r200_screen.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_screen.c,v 1.4 2003/05/08 09:25:35 herrb Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include <dlfcn.h>
37
38 #include "glheader.h"
39 #include "imports.h"
40 #include "context.h"
41
42 #include "r200_screen.h"
43 #include "r200_context.h"
44 #include "r200_ioctl.h"
45 #include "radeon_macros.h"
46 #include "radeon_reg.h"
47
48 #include "utils.h"
49 #include "vblank.h"
50 #ifndef _SOLO
51 #include "glxextensions.h"
52 #endif
53
54 /* R200 configuration
55 */
56 #include "xmlpool.h"
57
58 const char __driConfigOptions[] =
59 DRI_CONF_BEGIN
60 DRI_CONF_SECTION_PERFORMANCE
61 DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN)
62 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
63 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
64 DRI_CONF_SECTION_END
65 DRI_CONF_SECTION_QUALITY
66 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
67 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
68 DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC)
69 DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF)
70 DRI_CONF_SECTION_END
71 DRI_CONF_SECTION_DEBUG
72 DRI_CONF_NO_RAST(false)
73 DRI_CONF_SECTION_END
74 DRI_CONF_END;
75 static const GLuint __driNConfigOptions = 8;
76
77 #if 1
78 /* Including xf86PciInfo.h introduces a bunch of errors...
79 */
80 #define PCI_CHIP_R200_QD 0x5144
81 #define PCI_CHIP_R200_QE 0x5145
82 #define PCI_CHIP_R200_QF 0x5146
83 #define PCI_CHIP_R200_QG 0x5147
84 #define PCI_CHIP_R200_QY 0x5159
85 #define PCI_CHIP_R200_QZ 0x515A
86 #define PCI_CHIP_R200_LW 0x4C57
87 #define PCI_CHIP_R200_LY 0x4C59
88 #define PCI_CHIP_R200_LZ 0x4C5A
89 #define PCI_CHIP_RV200_QW 0x5157 /* Radeon 7500 - not an R200 at all */
90 #endif
91
92 static r200ScreenPtr __r200Screen;
93
94 static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
95
96 /* Create the device specific screen private data struct.
97 */
98 static r200ScreenPtr
99 r200CreateScreen( __DRIscreenPrivate *sPriv )
100 {
101 r200ScreenPtr screen;
102 RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
103 unsigned char *RADEONMMIO;
104
105 if ( ! driCheckDriDdxDrmVersions( sPriv, "R200", 4, 0, 4, 0, 1, 5 ) )
106 return NULL;
107
108 /* Allocate the private area */
109 screen = (r200ScreenPtr) CALLOC( sizeof(*screen) );
110 if ( !screen ) {
111 __driUtilMessage("%s: Could not allocate memory for screen structure",
112 __FUNCTION__);
113 return NULL;
114 }
115
116 switch ( dri_priv->deviceID ) {
117 case PCI_CHIP_R200_QD:
118 case PCI_CHIP_R200_QE:
119 case PCI_CHIP_R200_QF:
120 case PCI_CHIP_R200_QG:
121 case PCI_CHIP_R200_QY:
122 case PCI_CHIP_R200_QZ:
123 case PCI_CHIP_RV200_QW:
124 case PCI_CHIP_R200_LW:
125 case PCI_CHIP_R200_LY:
126 case PCI_CHIP_R200_LZ:
127 __driUtilMessage("r200CreateScreen(): Device isn't an r200!\n");
128 FREE( screen );
129 return NULL;
130 default:
131 screen->chipset = R200_CHIPSET_R200;
132 break;
133 }
134
135 /* parse information in __driConfigOptions */
136 driParseOptionInfo (&screen->optionCache,
137 __driConfigOptions, __driNConfigOptions);
138
139 /* This is first since which regions we map depends on whether or
140 * not we are using a PCI card.
141 */
142 screen->IsPCI = dri_priv->IsPCI;
143
144 {
145 int ret;
146 drmRadeonGetParam gp;
147
148 gp.param = RADEON_PARAM_GART_BUFFER_OFFSET;
149 gp.value = &screen->gart_buffer_offset;
150
151 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
152 &gp, sizeof(gp));
153 if (ret) {
154 FREE( screen );
155 fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret);
156 return NULL;
157 }
158
159 if (sPriv->drmMinor >= 6) {
160 gp.param = RADEON_PARAM_GART_BASE;
161 gp.value = &screen->gart_base;
162
163 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
164 &gp, sizeof(gp));
165 if (ret) {
166 FREE( screen );
167 fprintf(stderr, "drmR200GetParam (RADEON_PARAM_GART_BASE): %d\n", ret);
168 return NULL;
169 }
170
171
172 gp.param = RADEON_PARAM_IRQ_NR;
173 gp.value = &screen->irq;
174
175 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
176 &gp, sizeof(gp));
177 if (ret) {
178 FREE( screen );
179 fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret);
180 return NULL;
181 }
182
183 /* Check if kernel module is new enough to support cube maps */
184 screen->drmSupportsCubeMaps = (sPriv->drmMinor >= 7);
185 }
186 }
187
188 screen->mmio.handle = dri_priv->registerHandle;
189 screen->mmio.size = dri_priv->registerSize;
190 if ( drmMap( sPriv->fd,
191 screen->mmio.handle,
192 screen->mmio.size,
193 &screen->mmio.map ) ) {
194 FREE( screen );
195 __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ );
196 return NULL;
197 }
198
199 screen->status.handle = dri_priv->statusHandle;
200 screen->status.size = dri_priv->statusSize;
201 if ( drmMap( sPriv->fd,
202 screen->status.handle,
203 screen->status.size,
204 &screen->status.map ) ) {
205 drmUnmap( screen->mmio.map, screen->mmio.size );
206 FREE( screen );
207 __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
208 return NULL;
209 }
210 screen->scratch = (__volatile__ CARD32 *)
211 ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
212
213 screen->buffers = drmMapBufs( sPriv->fd );
214 if ( !screen->buffers ) {
215 drmUnmap( screen->status.map, screen->status.size );
216 drmUnmap( screen->mmio.map, screen->mmio.size );
217 FREE( screen );
218 __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__ );
219 return NULL;
220 }
221
222 RADEONMMIO = screen->mmio.map;
223
224 if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
225
226 screen->gartTextures.handle = dri_priv->gartTexHandle;
227 screen->gartTextures.size = dri_priv->gartTexMapSize;
228 if ( drmMap( sPriv->fd,
229 screen->gartTextures.handle,
230 screen->gartTextures.size,
231 (drmAddressPtr)&screen->gartTextures.map ) ) {
232 drmUnmapBufs( screen->buffers );
233 drmUnmap( screen->status.map, screen->status.size );
234 drmUnmap( screen->mmio.map, screen->mmio.size );
235 FREE( screen );
236 __driUtilMessage("%s: drmMAP failed for GART texture area\n", __FUNCTION__);
237 return NULL;
238 }
239
240 screen->gart_texture_offset = dri_priv->gartTexOffset + ( screen->IsPCI
241 ? INREG( RADEON_AIC_LO_ADDR )
242 : ( ( INREG( RADEON_MC_AGP_LOCATION ) & 0x0ffffU ) << 16 ) );
243 }
244
245 screen->cpp = dri_priv->bpp / 8;
246 screen->AGPMode = dri_priv->AGPMode;
247
248 screen->fbLocation = ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff ) << 16;
249
250 if ( sPriv->drmMinor >= 10 ) {
251 drmRadeonSetParam sp;
252
253 sp.param = RADEON_SETPARAM_FB_LOCATION;
254 sp.value = screen->fbLocation;
255
256 drmCommandWrite( sPriv->fd, DRM_RADEON_SETPARAM,
257 &sp, sizeof( sp ) );
258 }
259
260 screen->frontOffset = dri_priv->frontOffset;
261 screen->frontPitch = dri_priv->frontPitch;
262 screen->backOffset = dri_priv->backOffset;
263 screen->backPitch = dri_priv->backPitch;
264 screen->depthOffset = dri_priv->depthOffset;
265 screen->depthPitch = dri_priv->depthPitch;
266
267 screen->texOffset[RADEON_CARD_HEAP] = dri_priv->textureOffset
268 + screen->fbLocation;
269 screen->texSize[RADEON_CARD_HEAP] = dri_priv->textureSize;
270 screen->logTexGranularity[RADEON_CARD_HEAP] =
271 dri_priv->log2TexGran;
272
273 if ( !screen->gartTextures.map ) {
274 screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1;
275 screen->texOffset[RADEON_GART_HEAP] = 0;
276 screen->texSize[RADEON_GART_HEAP] = 0;
277 screen->logTexGranularity[RADEON_GART_HEAP] = 0;
278 } else {
279 screen->numTexHeaps = RADEON_NR_TEX_HEAPS;
280 screen->texOffset[RADEON_GART_HEAP] = screen->gart_texture_offset;
281 screen->texSize[RADEON_GART_HEAP] = dri_priv->gartTexMapSize;
282 screen->logTexGranularity[RADEON_GART_HEAP] =
283 dri_priv->log2GARTTexGran;
284 }
285
286 screen->driScreen = sPriv;
287 screen->sarea_priv_offset = dri_priv->sarea_priv_offset;
288 #ifndef _SOLO
289 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
290 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
291 (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
292 void * const psc = sPriv->psc->screenConfigs;
293
294 if ( glx_enable_extension != NULL ) {
295 if ( screen->irq != 0 ) {
296 (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
297 (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
298 (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
299 }
300
301 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
302
303 if ( driCompareGLXAPIVersion( 20030818 ) >= 0 ) {
304 sPriv->psc->allocateMemory = r200AllocateMemoryMESA;
305 sPriv->psc->freeMemory = r200FreeMemoryMESA;
306 sPriv->psc->memoryOffset = r200GetMemoryOffsetMESA;
307
308 (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
309 }
310 }
311 }
312 #endif
313 return screen;
314 }
315
316 /* Destroy the device specific screen private data struct.
317 */
318 static void
319 r200DestroyScreen( __DRIscreenPrivate *sPriv )
320 {
321 r200ScreenPtr screen = (r200ScreenPtr)sPriv->private;
322
323 if (!screen)
324 return;
325
326 if ( screen->gartTextures.map ) {
327 drmUnmap( screen->gartTextures.map, screen->gartTextures.size );
328 }
329 drmUnmapBufs( screen->buffers );
330 drmUnmap( screen->status.map, screen->status.size );
331 drmUnmap( screen->mmio.map, screen->mmio.size );
332
333 /* free all option information */
334 driDestroyOptionInfo (&screen->optionCache);
335
336 FREE( screen );
337 sPriv->private = NULL;
338 }
339
340
341 /* Initialize the driver specific screen private data.
342 */
343 static GLboolean
344 r200InitDriver( __DRIscreenPrivate *sPriv )
345 {
346 __r200Screen = r200CreateScreen( sPriv );
347
348 sPriv->private = (void *) __r200Screen;
349
350 return sPriv->private ? GL_TRUE : GL_FALSE;
351 }
352
353
354
355 /* Create and initialize the Mesa and driver specific pixmap buffer
356 * data.
357 */
358 static GLboolean
359 r200CreateBuffer( __DRIscreenPrivate *driScrnPriv,
360 __DRIdrawablePrivate *driDrawPriv,
361 const __GLcontextModes *mesaVis,
362 GLboolean isPixmap )
363 {
364 if (isPixmap) {
365 return GL_FALSE; /* not implemented */
366 }
367 else {
368 const GLboolean swDepth = GL_FALSE;
369 const GLboolean swAlpha = GL_FALSE;
370 const GLboolean swAccum = mesaVis->accumRedBits > 0;
371 const GLboolean swStencil = mesaVis->stencilBits > 0 &&
372 mesaVis->depthBits != 24;
373 driDrawPriv->driverPrivate = (void *)
374 _mesa_create_framebuffer( mesaVis,
375 swDepth,
376 swStencil,
377 swAccum,
378 swAlpha );
379 return (driDrawPriv->driverPrivate != NULL);
380 }
381 }
382
383
384 static void
385 r200DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
386 {
387 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
388 }
389
390
391
392
393 /* Fullscreen mode isn't used for much -- could be a way to shrink
394 * front/back buffers & get more texture memory if the client has
395 * changed the video resolution.
396 *
397 * Pageflipping is now done automatically whenever there is a single
398 * 3d client.
399 */
400 static GLboolean
401 r200OpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
402 {
403 return GL_TRUE;
404 }
405
406 static struct __DriverAPIRec r200API = {
407 .InitDriver = r200InitDriver,
408 .DestroyScreen = r200DestroyScreen,
409 .CreateContext = r200CreateContext,
410 .DestroyContext = r200DestroyContext,
411 .CreateBuffer = r200CreateBuffer,
412 .DestroyBuffer = r200DestroyBuffer,
413 .SwapBuffers = r200SwapBuffers,
414 .MakeCurrent = r200MakeCurrent,
415 .UnbindContext = r200UnbindContext,
416 .OpenFullScreen = r200OpenCloseFullScreen,
417 .CloseFullScreen = r200OpenCloseFullScreen,
418 .GetSwapInfo = getSwapInfo,
419 .GetMSC = driGetMSC32,
420 .WaitForMSC = driWaitForMSC32,
421 .WaitForSBC = NULL,
422 .SwapBuffersMSC = NULL
423 };
424
425
426 /*
427 * This is the bootstrap function for the driver.
428 * The __driCreateScreen name is the symbol that libGL.so fetches.
429 * Return: pointer to a __DRIscreenPrivate.
430 *
431 */
432 #ifndef _SOLO
433 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
434 int numConfigs, __GLXvisualConfig *config)
435 {
436 __DRIscreenPrivate *psp;
437 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &r200API);
438 return (void *) psp;
439 }
440 #else
441 void *__driCreateScreen(struct DRIDriverRec *driver,
442 struct DRIDriverContextRec *driverContext)
443 {
444 __DRIscreenPrivate *psp;
445 psp = __driUtilCreateScreen(driver, driverContext, &r200API);
446 return (void *) psp;
447 }
448 #endif
449
450 #ifndef _SOLO
451 /**
452 * This function is called by libGL.so to allow the driver to dynamically
453 * extend libGL. We can add new GLX functions and/or new GL functions.
454 * Note that _mesa_create_context() will probably add most of the newer
455 * OpenGL extension functions into the dispatcher.
456 *
457 * \todo This interface has been deprecated, so we should probably remove
458 * this function before the next XFree86 release.
459 */
460 void
461 __driRegisterExtensions( void )
462 {
463 PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
464
465
466 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
467 glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
468 glXGetProcAddress( (const GLubyte *) "__glXEnableExtension" );
469
470 if ( glx_enable_extension != NULL ) {
471 (*glx_enable_extension)( "GLX_SGI_swap_control", GL_FALSE );
472 (*glx_enable_extension)( "GLX_SGI_video_sync", GL_FALSE );
473 (*glx_enable_extension)( "GLX_MESA_swap_control", GL_FALSE );
474 (*glx_enable_extension)( "GLX_MESA_swap_frame_usage", GL_FALSE );
475 }
476 }
477 }
478 #endif
479
480 /**
481 * Get information about previous buffer swaps.
482 */
483 static int
484 getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
485 {
486 r200ContextPtr rmesa;
487
488 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
489 || (dPriv->driContextPriv->driverPrivate == NULL)
490 || (sInfo == NULL) ) {
491 return -1;
492 }
493
494 rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate;
495 sInfo->swap_count = rmesa->swap_count;
496 sInfo->swap_ust = rmesa->swap_ust;
497 sInfo->swap_missed_count = rmesa->swap_missed_count;
498
499 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
500 ? driCalculateSwapUsage( dPriv, 0, rmesa->swap_missed_ust )
501 : 0.0;
502
503 return 0;
504 }