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