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