radeon_screen.c revision aaebfc88c08c79cd70f1e0d1d262a25e9ded47d1
1/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c,v 1.7 2003/03/26 20:43:51 tsi Exp $ */
2/**************************************************************************
3
4Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5                     VA Linux Systems Inc., Fremont, California.
6
7All Rights Reserved.
8
9Permission is hereby granted, free of charge, to any person obtaining
10a copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice (including the
18next paragraph) shall be included in all copies or substantial
19portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29**************************************************************************/
30
31/**
32 * \file radeon_screen.c
33 * Screen initialization functions for the Radeon driver.
34 *
35 * \author Kevin E. Martin <martin@valinux.com>
36 * \author  Gareth Hughes <gareth@valinux.com>
37 */
38
39#include "glheader.h"
40#include "imports.h"
41
42#define STANDALONE_MMIO
43#include "radeon_context.h"
44#include "radeon_screen.h"
45#include "radeon_macros.h"
46
47#include "utils.h"
48#include "context.h"
49#include "vblank.h"
50
51#include "GL/internal/dri_interface.h"
52
53/* Radeon configuration
54 */
55#include "xmlpool.h"
56
57const char __driConfigOptions[] =
58DRI_CONF_BEGIN
59    DRI_CONF_SECTION_PERFORMANCE
60        DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN)
61        DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
62        DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
63    DRI_CONF_SECTION_END
64    DRI_CONF_SECTION_QUALITY
65        DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
66        DRI_CONF_DEF_MAX_ANISOTROPY(1.0,"1.0,2.0,4.0,8.0,16.0")
67        DRI_CONF_NO_NEG_LOD_BIAS(false)
68        DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
69        DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC)
70        DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF)
71    DRI_CONF_SECTION_END
72    DRI_CONF_SECTION_DEBUG
73        DRI_CONF_NO_RAST(false)
74    DRI_CONF_SECTION_END
75DRI_CONF_END;
76static const GLuint __driNConfigOptions = 10;
77
78#if 1
79/* Including xf86PciInfo.h introduces a bunch of errors...
80 */
81#define PCI_CHIP_RADEON_QD	0x5144
82#define PCI_CHIP_RADEON_QE	0x5145
83#define PCI_CHIP_RADEON_QF	0x5146
84#define PCI_CHIP_RADEON_QG	0x5147
85
86#define PCI_CHIP_RADEON_QY	0x5159
87#define PCI_CHIP_RADEON_QZ	0x515A
88
89#define PCI_CHIP_RADEON_LW	0x4C57 /* mobility 7 - has tcl */
90
91#define PCI_CHIP_RADEON_LY	0x4C59
92#define PCI_CHIP_RADEON_LZ	0x4C5A
93
94#define PCI_CHIP_RV200_QW	0x5157 /* Radeon 7500 - not an R200 at all */
95/* IGP Chipsets */
96#define PCI_CHIP_RS100_4136     0x4136
97#define PCI_CHIP_RS200_4137     0x4137
98#define PCI_CHIP_RS250_4237     0x4237
99#define PCI_CHIP_RS100_4336     0x4336
100#define PCI_CHIP_RS200_4337     0x4337
101#define PCI_CHIP_RS250_4437     0x4437
102#endif
103
104#ifdef USE_NEW_INTERFACE
105static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
106#endif /* USE_NEW_INTERFACE */
107
108static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
109
110#ifdef USE_NEW_INTERFACE
111static __GLcontextModes *
112radeonFillInModes( unsigned pixel_bits, unsigned depth_bits,
113		 unsigned stencil_bits, GLboolean have_back_buffer )
114{
115    __GLcontextModes * modes;
116    __GLcontextModes * m;
117    unsigned num_modes;
118    unsigned depth_buffer_factor;
119    unsigned back_buffer_factor;
120    GLenum fb_format;
121    GLenum fb_type;
122
123    /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
124     * enough to add support.  Basically, if a context is created with an
125     * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
126     * will never be used.
127     */
128    static const GLenum back_buffer_modes[] = {
129	GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
130    };
131
132    uint8_t depth_bits_array[2];
133    uint8_t stencil_bits_array[2];
134
135
136    depth_bits_array[0] = depth_bits;
137    depth_bits_array[1] = depth_bits;
138
139    /* Just like with the accumulation buffer, always provide some modes
140     * with a stencil buffer.  It will be a sw fallback, but some apps won't
141     * care about that.
142     */
143    stencil_bits_array[0] = 0;
144    stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
145
146    depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
147    back_buffer_factor  = (have_back_buffer) ? 2 : 1;
148
149    num_modes = depth_buffer_factor * back_buffer_factor * 4;
150
151    if ( pixel_bits == 16 ) {
152        fb_format = GL_RGB;
153        fb_type = GL_UNSIGNED_SHORT_5_6_5;
154    }
155    else {
156        fb_format = GL_BGRA;
157        fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
158    }
159
160    modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
161    m = modes;
162    if ( ! driFillInModes( & m, fb_format, fb_type,
163			   depth_bits_array, stencil_bits_array, depth_buffer_factor,
164			   back_buffer_modes, back_buffer_factor,
165			   GLX_TRUE_COLOR ) ) {
166	fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
167		 __func__, __LINE__ );
168	return NULL;
169    }
170
171    if ( ! driFillInModes( & m, fb_format, fb_type,
172			   depth_bits_array, stencil_bits_array, depth_buffer_factor,
173			   back_buffer_modes, back_buffer_factor,
174			   GLX_DIRECT_COLOR ) ) {
175	fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
176		 __func__, __LINE__ );
177	return NULL;
178    }
179
180    /* Mark the visual as slow if there are "fake" stencil bits.
181     */
182    for ( m = modes ; m != NULL ; m = m->next ) {
183	if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
184	    m->visualRating = GLX_SLOW_CONFIG;
185	}
186    }
187
188    return modes;
189}
190#endif /* USE_NEW_INTERFACE */
191
192/* Create the device specific screen private data struct.
193 */
194radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv )
195{
196   radeonScreenPtr screen;
197   RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
198   unsigned char *RADEONMMIO;
199
200
201   /* Allocate the private area */
202   screen = (radeonScreenPtr) CALLOC( sizeof(*screen) );
203   if ( !screen ) {
204      __driUtilMessage("%s: Could not allocate memory for screen structure",
205		       __FUNCTION__);
206      return NULL;
207   }
208
209   /* parse information in __driConfigOptions */
210   driParseOptionInfo (&screen->optionCache,
211		       __driConfigOptions, __driNConfigOptions);
212
213   /* This is first since which regions we map depends on whether or
214    * not we are using a PCI card.
215    */
216   screen->IsPCI = dri_priv->IsPCI;
217
218   {
219      int ret;
220      drm_radeon_getparam_t gp;
221
222      gp.param = RADEON_PARAM_GART_BUFFER_OFFSET;
223      gp.value = &screen->gart_buffer_offset;
224
225      ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
226				 &gp, sizeof(gp));
227      if (ret) {
228	 FREE( screen );
229	 fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret);
230	 return NULL;
231      }
232
233      if (sPriv->drmMinor >= 6) {
234	 gp.param = RADEON_PARAM_IRQ_NR;
235	 gp.value = &screen->irq;
236
237	 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
238				    &gp, sizeof(gp));
239	 if (ret) {
240	    FREE( screen );
241	    fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_IRQ_NR): %d\n", ret);
242	    return NULL;
243	 }
244      }
245   }
246
247   screen->mmio.handle = dri_priv->registerHandle;
248   screen->mmio.size   = dri_priv->registerSize;
249   if ( drmMap( sPriv->fd,
250		screen->mmio.handle,
251		screen->mmio.size,
252		&screen->mmio.map ) ) {
253      FREE( screen );
254      __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ );
255      return NULL;
256   }
257
258   RADEONMMIO = screen->mmio.map;
259
260   screen->status.handle = dri_priv->statusHandle;
261   screen->status.size   = dri_priv->statusSize;
262   if ( drmMap( sPriv->fd,
263		screen->status.handle,
264		screen->status.size,
265		&screen->status.map ) ) {
266      drmUnmap( screen->mmio.map, screen->mmio.size );
267      FREE( screen );
268      __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
269      return NULL;
270   }
271   screen->scratch = (__volatile__ uint32_t *)
272      ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
273
274   screen->buffers = drmMapBufs( sPriv->fd );
275   if ( !screen->buffers ) {
276      drmUnmap( screen->status.map, screen->status.size );
277      drmUnmap( screen->mmio.map, screen->mmio.size );
278      FREE( screen );
279      __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__ );
280      return NULL;
281   }
282
283   if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
284      screen->gartTextures.handle = dri_priv->gartTexHandle;
285      screen->gartTextures.size   = dri_priv->gartTexMapSize;
286      if ( drmMap( sPriv->fd,
287		   screen->gartTextures.handle,
288		   screen->gartTextures.size,
289		   (drmAddressPtr)&screen->gartTextures.map ) ) {
290	 drmUnmapBufs( screen->buffers );
291	 drmUnmap( screen->status.map, screen->status.size );
292	 drmUnmap( screen->mmio.map, screen->mmio.size );
293	 FREE( screen );
294	 __driUtilMessage("%s: drmMap failed for GART texture area\n", __FUNCTION__);
295	 return NULL;
296      }
297
298      screen->gart_texture_offset = dri_priv->gartTexOffset + ( screen->IsPCI
299		? INREG( RADEON_AIC_LO_ADDR )
300		: ( ( INREG( RADEON_MC_AGP_LOCATION ) & 0x0ffffU ) << 16 ) );
301   }
302
303   screen->chipset = 0;
304   switch ( dri_priv->deviceID ) {
305   default:
306      fprintf(stderr, "unknown chip id, assuming full radeon support\n");
307   case PCI_CHIP_RADEON_QD:
308   case PCI_CHIP_RADEON_QE:
309   case PCI_CHIP_RADEON_QF:
310   case PCI_CHIP_RADEON_QG:
311   case PCI_CHIP_RV200_QW:
312   case PCI_CHIP_RADEON_LW:
313      screen->chipset |= RADEON_CHIPSET_TCL;
314   case PCI_CHIP_RADEON_QY:
315   case PCI_CHIP_RADEON_QZ:
316   case PCI_CHIP_RADEON_LY:
317   case PCI_CHIP_RADEON_LZ:
318   case PCI_CHIP_RS100_4136: /* IGPs don't have TCL */
319   case PCI_CHIP_RS200_4137:
320   case PCI_CHIP_RS250_4237:
321   case PCI_CHIP_RS100_4336:
322   case PCI_CHIP_RS200_4337:
323   case PCI_CHIP_RS250_4437:
324      break;
325   }
326
327   screen->cpp = dri_priv->bpp / 8;
328   screen->AGPMode = dri_priv->AGPMode;
329
330   screen->fbLocation	= ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff ) << 16;
331
332   if ( sPriv->drmMinor >= 10 ) {
333      drm_radeon_setparam_t sp;
334
335      sp.param = RADEON_SETPARAM_FB_LOCATION;
336      sp.value = screen->fbLocation;
337
338      drmCommandWrite( sPriv->fd, DRM_RADEON_SETPARAM,
339		       &sp, sizeof( sp ) );
340   }
341
342   screen->frontOffset	= dri_priv->frontOffset;
343   screen->frontPitch	= dri_priv->frontPitch;
344   screen->backOffset	= dri_priv->backOffset;
345   screen->backPitch	= dri_priv->backPitch;
346   screen->depthOffset	= dri_priv->depthOffset;
347   screen->depthPitch	= dri_priv->depthPitch;
348
349   screen->texOffset[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureOffset
350				       + screen->fbLocation;
351   screen->texSize[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureSize;
352   screen->logTexGranularity[RADEON_LOCAL_TEX_HEAP] =
353      dri_priv->log2TexGran;
354
355   if ( !screen->gartTextures.map
356	|| getenv( "RADEON_GARTTEXTURING_FORCE_DISABLE" ) ) {
357      screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1;
358      screen->texOffset[RADEON_GART_TEX_HEAP] = 0;
359      screen->texSize[RADEON_GART_TEX_HEAP] = 0;
360      screen->logTexGranularity[RADEON_GART_TEX_HEAP] = 0;
361   } else {
362      screen->numTexHeaps = RADEON_NR_TEX_HEAPS;
363      screen->texOffset[RADEON_GART_TEX_HEAP] = screen->gart_texture_offset;
364      screen->texSize[RADEON_GART_TEX_HEAP] = dri_priv->gartTexMapSize;
365      screen->logTexGranularity[RADEON_GART_TEX_HEAP] =
366	 dri_priv->log2GARTTexGran;
367   }
368
369   if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
370      PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
371          (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
372      void * const psc = sPriv->psc->screenConfigs;
373
374      if ( glx_enable_extension != NULL ) {
375	 if ( screen->irq != 0 ) {
376	    (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
377	    (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
378	    (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
379	 }
380
381	 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
382
383         if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
384	    (*glx_enable_extension)( psc, "GLX_SGIX_fbconfig" );
385	    (*glx_enable_extension)( psc, "GLX_OML_swap_method" );
386	 }
387
388      }
389   }
390
391   screen->driScreen = sPriv;
392   screen->sarea_priv_offset = dri_priv->sarea_priv_offset;
393   return screen;
394}
395
396/* Destroy the device specific screen private data struct.
397 */
398void radeonDestroyScreen( __DRIscreenPrivate *sPriv )
399{
400   radeonScreenPtr screen = (radeonScreenPtr)sPriv->private;
401
402   if (!screen)
403      return;
404
405   if ( screen->gartTextures.map ) {
406      drmUnmap( screen->gartTextures.map, screen->gartTextures.size );
407   }
408   drmUnmapBufs( screen->buffers );
409   drmUnmap( screen->status.map, screen->status.size );
410   drmUnmap( screen->mmio.map, screen->mmio.size );
411
412   /* free all option information */
413   driDestroyOptionInfo (&screen->optionCache);
414
415   FREE( screen );
416   sPriv->private = NULL;
417}
418
419
420/* Initialize the driver specific screen private data.
421 */
422static GLboolean
423radeonInitDriver( __DRIscreenPrivate *sPriv )
424{
425   sPriv->private = (void *) radeonCreateScreen( sPriv );
426   if ( !sPriv->private ) {
427      radeonDestroyScreen( sPriv );
428      return GL_FALSE;
429   }
430
431   return GL_TRUE;
432}
433
434
435
436/**
437 * Create and initialize the Mesa and driver specific pixmap buffer
438 * data.
439 *
440 * \todo This function (and its interface) will need to be updated to support
441 * pbuffers.
442 */
443static GLboolean
444radeonCreateBuffer( __DRIscreenPrivate *driScrnPriv,
445                    __DRIdrawablePrivate *driDrawPriv,
446                    const __GLcontextModes *mesaVis,
447                    GLboolean isPixmap )
448{
449   if (isPixmap) {
450      return GL_FALSE; /* not implemented */
451   }
452   else {
453      const GLboolean swDepth = GL_FALSE;
454      const GLboolean swAlpha = GL_FALSE;
455      const GLboolean swAccum = mesaVis->accumRedBits > 0;
456      const GLboolean swStencil = mesaVis->stencilBits > 0 &&
457         mesaVis->depthBits != 24;
458      driDrawPriv->driverPrivate = (void *)
459         _mesa_create_framebuffer( mesaVis,
460                                   swDepth,
461                                   swStencil,
462                                   swAccum,
463                                   swAlpha );
464      return (driDrawPriv->driverPrivate != NULL);
465   }
466}
467
468
469static void
470radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
471{
472   _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
473}
474
475static struct __DriverAPIRec radeonAPI = {
476   .InitDriver      = radeonInitDriver,
477   .DestroyScreen   = radeonDestroyScreen,
478   .CreateContext   = radeonCreateContext,
479   .DestroyContext  = radeonDestroyContext,
480   .CreateBuffer    = radeonCreateBuffer,
481   .DestroyBuffer   = radeonDestroyBuffer,
482   .SwapBuffers     = radeonSwapBuffers,
483   .MakeCurrent     = radeonMakeCurrent,
484   .UnbindContext   = radeonUnbindContext,
485   .GetSwapInfo     = getSwapInfo,
486   .GetMSC          = driGetMSC32,
487   .WaitForMSC      = driWaitForMSC32,
488   .WaitForSBC      = NULL,
489   .SwapBuffersMSC  = NULL
490};
491
492
493/*
494 * This is the bootstrap function for the driver.
495 * The __driCreateScreen name is the symbol that libGL.so fetches.
496 * Return:  pointer to a __DRIscreenPrivate.
497 */
498#if !defined(DRI_NEW_INTERFACE_ONLY)
499void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
500                        int numConfigs, __GLXvisualConfig *config)
501{
502   __DRIscreenPrivate *psp;
503   psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &radeonAPI);
504   return (void *) psp;
505}
506#endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
507
508/**
509 * This is the bootstrap function for the driver.  libGL supplies all of the
510 * requisite information about the system, and the driver initializes itself.
511 * This routine also fills in the linked list pointed to by \c driver_modes
512 * with the \c __GLcontextModes that the driver can support for windows or
513 * pbuffers.
514 *
515 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
516 *         failure.
517 */
518#ifdef USE_NEW_INTERFACE
519void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
520			     const __GLcontextModes * modes,
521			     const __DRIversion * ddx_version,
522			     const __DRIversion * dri_version,
523			     const __DRIversion * drm_version,
524			     const __DRIframebuffer * frame_buffer,
525			     drmAddress pSAREA, int fd,
526			     int internal_api_version,
527			     __GLcontextModes ** driver_modes )
528
529{
530   __DRIscreenPrivate *psp;
531   static const __DRIversion ddx_expected = { 4, 0, 0 };
532   static const __DRIversion dri_expected = { 4, 0, 0 };
533   static const __DRIversion drm_expected = { 1, 3, 0 };
534
535   if ( ! driCheckDriDdxDrmVersions2( "Radeon",
536				      dri_version, & dri_expected,
537				      ddx_version, & ddx_expected,
538				      drm_version, & drm_expected ) ) {
539      return NULL;
540   }
541
542   psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
543				  ddx_version, dri_version, drm_version,
544				  frame_buffer, pSAREA, fd,
545				  internal_api_version, &radeonAPI);
546   if ( psp != NULL ) {
547      create_context_modes = (PFNGLXCREATECONTEXTMODES)
548	  glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
549      if ( create_context_modes != NULL ) {
550	 RADEONDRIPtr dri_priv = (RADEONDRIPtr) psp->pDevPriv;
551	 *driver_modes = radeonFillInModes( dri_priv->bpp,
552					    (dri_priv->bpp == 16) ? 16 : 24,
553					    (dri_priv->bpp == 16) ? 0  : 8,
554					    (dri_priv->backOffset != dri_priv->depthOffset) );
555      }
556   }
557
558   return (void *) psp;
559}
560#endif /* USE_NEW_INTERFACE */
561
562/**
563 * Get information about previous buffer swaps.
564 */
565static int
566getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
567{
568   radeonContextPtr  rmesa;
569
570   if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
571	|| (dPriv->driContextPriv->driverPrivate == NULL)
572	|| (sInfo == NULL) ) {
573      return -1;
574   }
575
576   rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
577   sInfo->swap_count = rmesa->swap_count;
578   sInfo->swap_ust = rmesa->swap_ust;
579   sInfo->swap_missed_count = rmesa->swap_missed_count;
580
581   sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
582       ? driCalculateSwapUsage( dPriv, 0, rmesa->swap_missed_ust )
583       : 0.0;
584
585   return 0;
586}
587