radeon_screen.c revision c39bf5e273a4995a279ae2af59fc29e06ab47e29
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#include "mtypes.h"
42#include "framebuffer.h"
43#include "renderbuffer.h"
44
45#define STANDALONE_MMIO
46#include "radeon_context.h"
47#include "radeon_screen.h"
48#include "radeon_macros.h"
49#include "radeon_span.h"
50
51#include "utils.h"
52#include "context.h"
53#include "vblank.h"
54#include "drirenderbuffer.h"
55
56#include "GL/internal/dri_interface.h"
57
58/* Radeon configuration
59 */
60#include "xmlpool.h"
61
62PUBLIC const char __driConfigOptions[] =
63DRI_CONF_BEGIN
64    DRI_CONF_SECTION_PERFORMANCE
65        DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN)
66        DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
67        DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
68        DRI_CONF_HYPERZ(false)
69    DRI_CONF_SECTION_END
70    DRI_CONF_SECTION_QUALITY
71        DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
72        DRI_CONF_DEF_MAX_ANISOTROPY(1.0,"1.0,2.0,4.0,8.0,16.0")
73        DRI_CONF_NO_NEG_LOD_BIAS(false)
74        DRI_CONF_FORCE_S3TC_ENABLE(false)
75        DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
76        DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC)
77        DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF)
78        DRI_CONF_TEXTURE_LEVEL_HACK(false)
79    DRI_CONF_SECTION_END
80    DRI_CONF_SECTION_DEBUG
81        DRI_CONF_NO_RAST(false)
82    DRI_CONF_SECTION_END
83DRI_CONF_END;
84static const GLuint __driNConfigOptions = 13;
85
86#if 1
87/* Including xf86PciInfo.h introduces a bunch of errors...
88 */
89#define PCI_CHIP_RADEON_QD	0x5144
90#define PCI_CHIP_RADEON_QE	0x5145
91#define PCI_CHIP_RADEON_QF	0x5146
92#define PCI_CHIP_RADEON_QG	0x5147
93
94#define PCI_CHIP_RADEON_QY	0x5159
95#define PCI_CHIP_RADEON_QZ	0x515A
96
97#define PCI_CHIP_RN50_515E	0x515E
98#define PCI_CHIP_RN50_5969	0x5969
99
100#define PCI_CHIP_RADEON_LW	0x4C57 /* mobility 7 - has tcl */
101#define PCI_CHIP_RADEON_LX	0x4C58 /* mobility FireGL 7800 m7 */
102
103#define PCI_CHIP_RADEON_LY	0x4C59
104#define PCI_CHIP_RADEON_LZ	0x4C5A
105
106#define PCI_CHIP_RV200_QW	0x5157 /* Radeon 7500 - not an R200 at all */
107#define PCI_CHIP_RV200_QX	0x5158
108
109/* IGP Chipsets */
110#define PCI_CHIP_RS100_4136     0x4136
111#define PCI_CHIP_RS200_4137     0x4137
112#define PCI_CHIP_RS250_4237     0x4237
113#define PCI_CHIP_RS100_4336     0x4336
114#define PCI_CHIP_RS200_4337     0x4337
115#define PCI_CHIP_RS250_4437     0x4437
116#endif
117
118static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
119
120static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
121
122static __GLcontextModes *
123radeonFillInModes( unsigned pixel_bits, unsigned depth_bits,
124		 unsigned stencil_bits, GLboolean have_back_buffer )
125{
126    __GLcontextModes * modes;
127    __GLcontextModes * m;
128    unsigned num_modes;
129    unsigned depth_buffer_factor;
130    unsigned back_buffer_factor;
131    GLenum fb_format;
132    GLenum fb_type;
133
134    /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
135     * enough to add support.  Basically, if a context is created with an
136     * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
137     * will never be used.
138     */
139    static const GLenum back_buffer_modes[] = {
140	GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
141    };
142
143    u_int8_t depth_bits_array[2];
144    u_int8_t stencil_bits_array[2];
145
146
147    depth_bits_array[0] = depth_bits;
148    depth_bits_array[1] = depth_bits;
149
150    /* Just like with the accumulation buffer, always provide some modes
151     * with a stencil buffer.  It will be a sw fallback, but some apps won't
152     * care about that.
153     */
154    stencil_bits_array[0] = 0;
155    stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
156
157    depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
158    back_buffer_factor  = (have_back_buffer) ? 2 : 1;
159
160    num_modes = depth_buffer_factor * back_buffer_factor * 4;
161
162    if ( pixel_bits == 16 ) {
163        fb_format = GL_RGB;
164        fb_type = GL_UNSIGNED_SHORT_5_6_5;
165    }
166    else {
167        fb_format = GL_BGRA;
168        fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
169    }
170
171    modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
172    m = modes;
173    if ( ! driFillInModes( & m, fb_format, fb_type,
174			   depth_bits_array, stencil_bits_array, depth_buffer_factor,
175			   back_buffer_modes, back_buffer_factor,
176			   GLX_TRUE_COLOR ) ) {
177	fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
178		 __func__, __LINE__ );
179	return NULL;
180    }
181
182    if ( ! driFillInModes( & m, fb_format, fb_type,
183			   depth_bits_array, stencil_bits_array, depth_buffer_factor,
184			   back_buffer_modes, back_buffer_factor,
185			   GLX_DIRECT_COLOR ) ) {
186	fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
187		 __func__, __LINE__ );
188	return NULL;
189    }
190
191    /* Mark the visual as slow if there are "fake" stencil bits.
192     */
193    for ( m = modes ; m != NULL ; m = m->next ) {
194	if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
195	    m->visualRating = GLX_SLOW_CONFIG;
196	}
197    }
198
199    return modes;
200}
201
202
203/* Create the device specific screen private data struct.
204 */
205radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv )
206{
207   radeonScreenPtr screen;
208   RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
209   unsigned char *RADEONMMIO;
210   PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
211     (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
212   void * const psc = sPriv->psc->screenConfigs;
213
214
215   if ( glx_enable_extension == NULL ) {
216      return NULL;
217   }
218
219   /* Allocate the private area */
220   screen = (radeonScreenPtr) CALLOC( sizeof(*screen) );
221   if ( !screen ) {
222      __driUtilMessage("%s: Could not allocate memory for screen structure",
223		       __FUNCTION__);
224      return NULL;
225   }
226
227   /* parse information in __driConfigOptions */
228   driParseOptionInfo (&screen->optionCache,
229		       __driConfigOptions, __driNConfigOptions);
230
231   /* This is first since which regions we map depends on whether or
232    * not we are using a PCI card.
233    */
234   screen->IsPCI = dri_priv->IsPCI;
235
236   {
237      int ret;
238      drm_radeon_getparam_t gp;
239
240      gp.param = RADEON_PARAM_GART_BUFFER_OFFSET;
241      gp.value = &screen->gart_buffer_offset;
242
243      ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
244				 &gp, sizeof(gp));
245      if (ret) {
246	 FREE( screen );
247	 fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret);
248	 return NULL;
249      }
250
251      if (sPriv->drmMinor >= 6) {
252	 gp.param = RADEON_PARAM_IRQ_NR;
253	 gp.value = &screen->irq;
254
255	 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
256				    &gp, sizeof(gp));
257	 if (ret) {
258	    FREE( screen );
259	    fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_IRQ_NR): %d\n", ret);
260	    return NULL;
261	 }
262      }
263   }
264
265   screen->mmio.handle = dri_priv->registerHandle;
266   screen->mmio.size   = dri_priv->registerSize;
267   if ( drmMap( sPriv->fd,
268		screen->mmio.handle,
269		screen->mmio.size,
270		&screen->mmio.map ) ) {
271      FREE( screen );
272      __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ );
273      return NULL;
274   }
275
276   RADEONMMIO = screen->mmio.map;
277
278   screen->status.handle = dri_priv->statusHandle;
279   screen->status.size   = dri_priv->statusSize;
280   if ( drmMap( sPriv->fd,
281		screen->status.handle,
282		screen->status.size,
283		&screen->status.map ) ) {
284      drmUnmap( screen->mmio.map, screen->mmio.size );
285      FREE( screen );
286      __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
287      return NULL;
288   }
289   screen->scratch = (__volatile__ u_int32_t *)
290      ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
291
292   screen->buffers = drmMapBufs( sPriv->fd );
293   if ( !screen->buffers ) {
294      drmUnmap( screen->status.map, screen->status.size );
295      drmUnmap( screen->mmio.map, screen->mmio.size );
296      FREE( screen );
297      __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__ );
298      return NULL;
299   }
300
301   if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
302      screen->gartTextures.handle = dri_priv->gartTexHandle;
303      screen->gartTextures.size   = dri_priv->gartTexMapSize;
304      if ( drmMap( sPriv->fd,
305		   screen->gartTextures.handle,
306		   screen->gartTextures.size,
307		   (drmAddressPtr)&screen->gartTextures.map ) ) {
308	 drmUnmapBufs( screen->buffers );
309	 drmUnmap( screen->status.map, screen->status.size );
310	 drmUnmap( screen->mmio.map, screen->mmio.size );
311	 FREE( screen );
312	 __driUtilMessage("%s: drmMap failed for GART texture area\n", __FUNCTION__);
313	 return NULL;
314      }
315
316      screen->gart_texture_offset = dri_priv->gartTexOffset + ( screen->IsPCI
317		? INREG( RADEON_AIC_LO_ADDR )
318		: ( ( INREG( RADEON_MC_AGP_LOCATION ) & 0x0ffffU ) << 16 ) );
319   }
320
321   screen->chipset = 0;
322   switch ( dri_priv->deviceID ) {
323   default:
324      fprintf(stderr, "unknown chip id, assuming full radeon support\n");
325   case PCI_CHIP_RADEON_QD:
326   case PCI_CHIP_RADEON_QE:
327   case PCI_CHIP_RADEON_QF:
328   case PCI_CHIP_RADEON_QG:
329      /* all original radeons (7200) presumably have a stencil op bug */
330      screen->chipset |= RADEON_CHIPSET_BROKEN_STENCIL;
331   case PCI_CHIP_RV200_QW:
332   case PCI_CHIP_RV200_QX:
333   case PCI_CHIP_RADEON_LW:
334   case PCI_CHIP_RADEON_LX:
335      screen->chipset |= RADEON_CHIPSET_TCL;
336   case PCI_CHIP_RADEON_QY:
337   case PCI_CHIP_RADEON_QZ:
338   case PCI_CHIP_RN50_515E:
339   case PCI_CHIP_RN50_5969:
340   case PCI_CHIP_RADEON_LY:
341   case PCI_CHIP_RADEON_LZ:
342   case PCI_CHIP_RS100_4136: /* IGPs don't have TCL */
343   case PCI_CHIP_RS200_4137:
344   case PCI_CHIP_RS250_4237:
345   case PCI_CHIP_RS100_4336:
346   case PCI_CHIP_RS200_4337:
347   case PCI_CHIP_RS250_4437:
348      break;
349   }
350
351   screen->cpp = dri_priv->bpp / 8;
352   screen->AGPMode = dri_priv->AGPMode;
353
354   screen->fbLocation	= ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff ) << 16;
355
356   if ( sPriv->drmMinor >= 10 ) {
357      drm_radeon_setparam_t sp;
358
359      sp.param = RADEON_SETPARAM_FB_LOCATION;
360      sp.value = screen->fbLocation;
361
362      drmCommandWrite( sPriv->fd, DRM_RADEON_SETPARAM,
363		       &sp, sizeof( sp ) );
364   }
365
366   screen->frontOffset	= dri_priv->frontOffset;
367   screen->frontPitch	= dri_priv->frontPitch;
368   screen->backOffset	= dri_priv->backOffset;
369   screen->backPitch	= dri_priv->backPitch;
370   screen->depthOffset	= dri_priv->depthOffset;
371   screen->depthPitch	= dri_priv->depthPitch;
372
373   /* Check if ddx has set up a surface reg to cover depth buffer */
374   screen->depthHasSurface = ((sPriv->ddxMajor > 4) &&
375      (screen->chipset & RADEON_CHIPSET_TCL));
376
377   screen->texOffset[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureOffset
378				       + screen->fbLocation;
379   screen->texSize[RADEON_LOCAL_TEX_HEAP] = dri_priv->textureSize;
380   screen->logTexGranularity[RADEON_LOCAL_TEX_HEAP] =
381      dri_priv->log2TexGran;
382
383   if ( !screen->gartTextures.map
384	|| getenv( "RADEON_GARTTEXTURING_FORCE_DISABLE" ) ) {
385      screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1;
386      screen->texOffset[RADEON_GART_TEX_HEAP] = 0;
387      screen->texSize[RADEON_GART_TEX_HEAP] = 0;
388      screen->logTexGranularity[RADEON_GART_TEX_HEAP] = 0;
389   } else {
390      screen->numTexHeaps = RADEON_NR_TEX_HEAPS;
391      screen->texOffset[RADEON_GART_TEX_HEAP] = screen->gart_texture_offset;
392      screen->texSize[RADEON_GART_TEX_HEAP] = dri_priv->gartTexMapSize;
393      screen->logTexGranularity[RADEON_GART_TEX_HEAP] =
394	 dri_priv->log2GARTTexGran;
395   }
396
397   if ( screen->irq != 0 ) {
398      (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
399      (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
400      (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
401   }
402
403   (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
404
405   screen->driScreen = sPriv;
406   screen->sarea_priv_offset = dri_priv->sarea_priv_offset;
407   return screen;
408}
409
410/* Destroy the device specific screen private data struct.
411 */
412void radeonDestroyScreen( __DRIscreenPrivate *sPriv )
413{
414   radeonScreenPtr screen = (radeonScreenPtr)sPriv->private;
415
416   if (!screen)
417      return;
418
419   if ( screen->gartTextures.map ) {
420      drmUnmap( screen->gartTextures.map, screen->gartTextures.size );
421   }
422   drmUnmapBufs( screen->buffers );
423   drmUnmap( screen->status.map, screen->status.size );
424   drmUnmap( screen->mmio.map, screen->mmio.size );
425
426   /* free all option information */
427   driDestroyOptionInfo (&screen->optionCache);
428
429   FREE( screen );
430   sPriv->private = NULL;
431}
432
433
434/* Initialize the driver specific screen private data.
435 */
436static GLboolean
437radeonInitDriver( __DRIscreenPrivate *sPriv )
438{
439   sPriv->private = (void *) radeonCreateScreen( sPriv );
440   if ( !sPriv->private ) {
441      radeonDestroyScreen( sPriv );
442      return GL_FALSE;
443   }
444
445   return GL_TRUE;
446}
447
448
449/**
450 * Create the Mesa framebuffer and renderbuffers for a given window/drawable.
451 *
452 * \todo This function (and its interface) will need to be updated to support
453 * pbuffers.
454 */
455static GLboolean
456radeonCreateBuffer( __DRIscreenPrivate *driScrnPriv,
457                    __DRIdrawablePrivate *driDrawPriv,
458                    const __GLcontextModes *mesaVis,
459                    GLboolean isPixmap )
460{
461   radeonScreenPtr screen = (radeonScreenPtr) driScrnPriv->private;
462
463   if (isPixmap) {
464      return GL_FALSE; /* not implemented */
465   }
466   else {
467      const GLboolean swDepth = GL_FALSE;
468      const GLboolean swAlpha = GL_FALSE;
469      const GLboolean swAccum = mesaVis->accumRedBits > 0;
470      const GLboolean swStencil = mesaVis->stencilBits > 0 &&
471         mesaVis->depthBits != 24;
472#if 0
473      driDrawPriv->driverPrivate = (void *)
474         _mesa_create_framebuffer( mesaVis,
475                                   swDepth,
476                                   swStencil,
477                                   swAccum,
478                                   swAlpha );
479#else
480      struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
481
482      {
483         driRenderbuffer *frontRb
484            = driNewRenderbuffer(GL_RGBA, screen->cpp,
485                                 screen->frontOffset, screen->frontPitch);
486         radeonSetSpanFunctions(frontRb, mesaVis);
487         _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
488      }
489
490      if (mesaVis->doubleBufferMode) {
491         driRenderbuffer *backRb
492            = driNewRenderbuffer(GL_RGBA, screen->cpp,
493                                 screen->backOffset, screen->backPitch);
494         radeonSetSpanFunctions(backRb, mesaVis);
495         _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
496      }
497
498      if (mesaVis->depthBits == 16) {
499         driRenderbuffer *depthRb
500            = driNewRenderbuffer(GL_DEPTH_COMPONENT16, screen->cpp,
501                                 screen->depthOffset, screen->depthPitch);
502         radeonSetSpanFunctions(depthRb, mesaVis);
503         _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
504      }
505      else if (mesaVis->depthBits == 24) {
506         driRenderbuffer *depthRb
507            = driNewRenderbuffer(GL_DEPTH_COMPONENT24, screen->cpp,
508                                 screen->depthOffset, screen->depthPitch);
509         radeonSetSpanFunctions(depthRb, mesaVis);
510         _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
511      }
512
513      if (mesaVis->stencilBits > 0 && !swStencil) {
514         driRenderbuffer *stencilRb
515            = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, screen->cpp,
516                                 screen->depthOffset, screen->depthPitch);
517         radeonSetSpanFunctions(stencilRb, mesaVis);
518         _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
519      }
520
521      _mesa_add_soft_renderbuffers(fb,
522                                   GL_FALSE, /* color */
523                                   swDepth,
524                                   swStencil,
525                                   swAccum,
526                                   swAlpha,
527                                   GL_FALSE /* aux */);
528      driDrawPriv->driverPrivate = (void *) fb;
529#endif
530      return (driDrawPriv->driverPrivate != NULL);
531   }
532}
533
534
535static void
536radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
537{
538   _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
539}
540
541static struct __DriverAPIRec radeonAPI = {
542   .InitDriver      = radeonInitDriver,
543   .DestroyScreen   = radeonDestroyScreen,
544   .CreateContext   = radeonCreateContext,
545   .DestroyContext  = radeonDestroyContext,
546   .CreateBuffer    = radeonCreateBuffer,
547   .DestroyBuffer   = radeonDestroyBuffer,
548   .SwapBuffers     = radeonSwapBuffers,
549   .MakeCurrent     = radeonMakeCurrent,
550   .UnbindContext   = radeonUnbindContext,
551   .GetSwapInfo     = getSwapInfo,
552   .GetMSC          = driGetMSC32,
553   .WaitForMSC      = driWaitForMSC32,
554   .WaitForSBC      = NULL,
555   .SwapBuffersMSC  = NULL
556};
557
558
559/**
560 * This is the bootstrap function for the driver.  libGL supplies all of the
561 * requisite information about the system, and the driver initializes itself.
562 * This routine also fills in the linked list pointed to by \c driver_modes
563 * with the \c __GLcontextModes that the driver can support for windows or
564 * pbuffers.
565 *
566 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
567 *         failure.
568 */
569PUBLIC
570void * __driCreateNewScreen_20050722( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
571			     const __GLcontextModes * modes,
572			     const __DRIversion * ddx_version,
573			     const __DRIversion * dri_version,
574			     const __DRIversion * drm_version,
575			     const __DRIframebuffer * frame_buffer,
576			     drmAddress pSAREA, int fd,
577			     int internal_api_version,
578			     __GLcontextModes ** driver_modes )
579
580{
581   __DRIscreenPrivate *psp;
582   static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 };
583   static const __DRIversion dri_expected = { 4, 0, 0 };
584   static const __DRIversion drm_expected = { 1, 3, 0 };
585
586   if ( ! driCheckDriDdxDrmVersions3( "Radeon",
587				      dri_version, & dri_expected,
588				      ddx_version, & ddx_expected,
589				      drm_version, & drm_expected ) ) {
590      return NULL;
591   }
592
593   psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
594				  ddx_version, dri_version, drm_version,
595				  frame_buffer, pSAREA, fd,
596				  internal_api_version, &radeonAPI);
597   if ( psp != NULL ) {
598      create_context_modes = (PFNGLXCREATECONTEXTMODES)
599	  glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
600      if ( create_context_modes != NULL ) {
601	 RADEONDRIPtr dri_priv = (RADEONDRIPtr) psp->pDevPriv;
602	 *driver_modes = radeonFillInModes( dri_priv->bpp,
603					    (dri_priv->bpp == 16) ? 16 : 24,
604					    (dri_priv->bpp == 16) ? 0  : 8,
605					    (dri_priv->backOffset != dri_priv->depthOffset) );
606      }
607   }
608
609   return (void *) psp;
610}
611
612
613/**
614 * Get information about previous buffer swaps.
615 */
616static int
617getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
618{
619   radeonContextPtr  rmesa;
620
621   if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
622	|| (dPriv->driContextPriv->driverPrivate == NULL)
623	|| (sInfo == NULL) ) {
624      return -1;
625   }
626
627   rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
628   sInfo->swap_count = rmesa->swap_count;
629   sInfo->swap_ust = rmesa->swap_ust;
630   sInfo->swap_missed_count = rmesa->swap_missed_count;
631
632   sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
633       ? driCalculateSwapUsage( dPriv, 0, rmesa->swap_missed_ust )
634       : 0.0;
635
636   return 0;
637}
638