radeon_screen.c revision 99ef0a03292e7dc6aa2465aaaa620f394d2c286b
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 * Authors: 33 * Kevin E. Martin <martin@valinux.com> 34 * Gareth Hughes <gareth@valinux.com> 35 * 36 */ 37 38#include "glheader.h" 39#include "imports.h" 40 41#include "radeon_context.h" 42#include "radeon_screen.h" 43#include "radeon_macros.h" 44 45#include "utils.h" 46#include "context.h" 47#include "vblank.h" 48 49#ifndef _SOLO 50#include "glxextensions.h" 51#endif 52 53#if 1 54/* Including xf86PciInfo.h introduces a bunch of errors... 55 */ 56#define PCI_CHIP_RADEON_QD 0x5144 57#define PCI_CHIP_RADEON_QE 0x5145 58#define PCI_CHIP_RADEON_QF 0x5146 59#define PCI_CHIP_RADEON_QG 0x5147 60 61#define PCI_CHIP_RADEON_QY 0x5159 62#define PCI_CHIP_RADEON_QZ 0x515A 63 64#define PCI_CHIP_RADEON_LW 0x4C57 /* mobility 7 - has tcl */ 65 66#define PCI_CHIP_RADEON_LY 0x4C59 67#define PCI_CHIP_RADEON_LZ 0x4C5A 68 69#define PCI_CHIP_RV200_QW 0x5157 /* Radeon 7500 - not an R200 at all */ 70#endif 71 72static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo ); 73 74/* Create the device specific screen private data struct. 75 */ 76radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv ) 77{ 78 radeonScreenPtr screen; 79 RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv; 80 unsigned char *RADEONMMIO; 81 82 if ( ! driCheckDriDdxDrmVersions( sPriv, "Radeon", 4, 0, 4, 0, 1, 3 ) ) 83 return NULL; 84 85 /* Allocate the private area */ 86 screen = (radeonScreenPtr) CALLOC( sizeof(*screen) ); 87 if ( !screen ) { 88 __driUtilMessage("%s: Could not allocate memory for screen structure", 89 __FUNCTION__); 90 return NULL; 91 } 92 93 /* parse information in __driConfigOptions */ 94 driParseOptionInfo (&screen->optionCache); 95 96 /* This is first since which regions we map depends on whether or 97 * not we are using a PCI card. 98 */ 99 screen->IsPCI = dri_priv->IsPCI; 100 101 { 102 int ret; 103 drmRadeonGetParam gp; 104 105 gp.param = RADEON_PARAM_GART_BUFFER_OFFSET; 106 gp.value = &screen->gart_buffer_offset; 107 108 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, 109 &gp, sizeof(gp)); 110 if (ret) { 111 FREE( screen ); 112 fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret); 113 return NULL; 114 } 115 116 if (sPriv->drmMinor >= 6) { 117 gp.param = RADEON_PARAM_IRQ_NR; 118 gp.value = &screen->irq; 119 120 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, 121 &gp, sizeof(gp)); 122 if (ret) { 123 FREE( screen ); 124 fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret); 125 return NULL; 126 } 127 } 128 } 129 130 screen->mmio.handle = dri_priv->registerHandle; 131 screen->mmio.size = dri_priv->registerSize; 132 if ( drmMap( sPriv->fd, 133 screen->mmio.handle, 134 screen->mmio.size, 135 &screen->mmio.map ) ) { 136 FREE( screen ); 137 __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ ); 138 return NULL; 139 } 140 141 RADEONMMIO = screen->mmio.map; 142 143 screen->status.handle = dri_priv->statusHandle; 144 screen->status.size = dri_priv->statusSize; 145 if ( drmMap( sPriv->fd, 146 screen->status.handle, 147 screen->status.size, 148 &screen->status.map ) ) { 149 drmUnmap( screen->mmio.map, screen->mmio.size ); 150 FREE( screen ); 151 __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ ); 152 return NULL; 153 } 154 screen->scratch = (__volatile__ CARD32 *) 155 ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET); 156 157 screen->buffers = drmMapBufs( sPriv->fd ); 158 if ( !screen->buffers ) { 159 drmUnmap( screen->status.map, screen->status.size ); 160 drmUnmap( screen->mmio.map, screen->mmio.size ); 161 FREE( screen ); 162 __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__ ); 163 return NULL; 164 } 165 166 if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) { 167 screen->gartTextures.handle = dri_priv->gartTexHandle; 168 screen->gartTextures.size = dri_priv->gartTexMapSize; 169 if ( drmMap( sPriv->fd, 170 screen->gartTextures.handle, 171 screen->gartTextures.size, 172 (drmAddressPtr)&screen->gartTextures.map ) ) { 173 drmUnmapBufs( screen->buffers ); 174 drmUnmap( screen->status.map, screen->status.size ); 175 drmUnmap( screen->mmio.map, screen->mmio.size ); 176 FREE( screen ); 177 __driUtilMessage("%s: drmMap failed for GART texture area\n", __FUNCTION__); 178 return NULL; 179 } 180 181 screen->gart_texture_offset = dri_priv->gartTexOffset + ( screen->IsPCI 182 ? INREG( RADEON_AIC_LO_ADDR ) 183 : ( ( INREG( RADEON_MC_AGP_LOCATION ) & 0x0ffffU ) << 16 ) ); 184 } 185 186 screen->chipset = 0; 187 switch ( dri_priv->deviceID ) { 188 default: 189 fprintf(stderr, "unknown chip id, assuming full radeon support\n"); 190 case PCI_CHIP_RADEON_QD: 191 case PCI_CHIP_RADEON_QE: 192 case PCI_CHIP_RADEON_QF: 193 case PCI_CHIP_RADEON_QG: 194 case PCI_CHIP_RV200_QW: 195 case PCI_CHIP_RADEON_LW: 196 screen->chipset |= RADEON_CHIPSET_TCL; 197 case PCI_CHIP_RADEON_QY: 198 case PCI_CHIP_RADEON_QZ: 199 case PCI_CHIP_RADEON_LY: 200 case PCI_CHIP_RADEON_LZ: 201 break; 202 } 203 204 screen->cpp = dri_priv->bpp / 8; 205 screen->AGPMode = dri_priv->AGPMode; 206 207 screen->fbLocation = ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff ) << 16; 208 209 if ( sPriv->drmMinor >= 10 ) { 210 drmRadeonSetParam sp; 211 212 sp.param = RADEON_SETPARAM_FB_LOCATION; 213 sp.value = screen->fbLocation; 214 215 drmCommandWrite( sPriv->fd, DRM_RADEON_SETPARAM, 216 &sp, sizeof( sp ) ); 217 } 218 219 screen->frontOffset = dri_priv->frontOffset; 220 screen->frontPitch = dri_priv->frontPitch; 221 screen->backOffset = dri_priv->backOffset; 222 screen->backPitch = dri_priv->backPitch; 223 screen->depthOffset = dri_priv->depthOffset; 224 screen->depthPitch = dri_priv->depthPitch; 225 226 screen->texOffset[RADEON_CARD_HEAP] = dri_priv->textureOffset 227 + screen->fbLocation; 228 screen->texSize[RADEON_CARD_HEAP] = dri_priv->textureSize; 229 screen->logTexGranularity[RADEON_CARD_HEAP] = 230 dri_priv->log2TexGran; 231 232 if ( !screen->gartTextures.map 233 || getenv( "RADEON_GARTTEXTURING_FORCE_DISABLE" ) ) { 234 screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1; 235 screen->texOffset[RADEON_GART_HEAP] = 0; 236 screen->texSize[RADEON_GART_HEAP] = 0; 237 screen->logTexGranularity[RADEON_GART_HEAP] = 0; 238 } else { 239 screen->numTexHeaps = RADEON_NR_TEX_HEAPS; 240 screen->texOffset[RADEON_GART_HEAP] = screen->gart_texture_offset; 241 screen->texSize[RADEON_GART_HEAP] = dri_priv->gartTexMapSize; 242 screen->logTexGranularity[RADEON_GART_HEAP] = 243 dri_priv->log2GARTTexGran; 244 } 245#ifndef _SOLO 246 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) { 247 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = 248 (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" ); 249 void * const psc = sPriv->psc->screenConfigs; 250 251 if ( glx_enable_extension != NULL ) { 252 if ( screen->irq != 0 ) { 253 (*glx_enable_extension)( psc, "GLX_SGI_swap_control" ); 254 (*glx_enable_extension)( psc, "GLX_SGI_video_sync" ); 255 (*glx_enable_extension)( psc, "GLX_MESA_swap_control" ); 256 } 257 258 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" ); 259 } 260 } 261#endif 262 screen->driScreen = sPriv; 263 screen->sarea_priv_offset = dri_priv->sarea_priv_offset; 264 return screen; 265} 266 267/* Destroy the device specific screen private data struct. 268 */ 269void radeonDestroyScreen( __DRIscreenPrivate *sPriv ) 270{ 271 radeonScreenPtr screen = (radeonScreenPtr)sPriv->private; 272 273 if (!screen) 274 return; 275 276 if ( screen->gartTextures.map ) { 277 drmUnmap( screen->gartTextures.map, screen->gartTextures.size ); 278 } 279 drmUnmapBufs( screen->buffers ); 280 drmUnmap( screen->status.map, screen->status.size ); 281 drmUnmap( screen->mmio.map, screen->mmio.size ); 282 283 /* free all option information */ 284 driDestroyOptionInfo (&screen->optionCache); 285 286 FREE( screen ); 287 sPriv->private = NULL; 288} 289 290 291/* Initialize the driver specific screen private data. 292 */ 293static GLboolean 294radeonInitDriver( __DRIscreenPrivate *sPriv ) 295{ 296 sPriv->private = (void *) radeonCreateScreen( sPriv ); 297 if ( !sPriv->private ) { 298 radeonDestroyScreen( sPriv ); 299 return GL_FALSE; 300 } 301 302 return GL_TRUE; 303} 304 305 306 307/* Create and initialize the Mesa and driver specific pixmap buffer 308 * data. 309 */ 310static GLboolean 311radeonCreateBuffer( __DRIscreenPrivate *driScrnPriv, 312 __DRIdrawablePrivate *driDrawPriv, 313 const __GLcontextModes *mesaVis, 314 GLboolean isPixmap ) 315{ 316 if (isPixmap) { 317 return GL_FALSE; /* not implemented */ 318 } 319 else { 320 const GLboolean swDepth = GL_FALSE; 321 const GLboolean swAlpha = GL_FALSE; 322 const GLboolean swAccum = mesaVis->accumRedBits > 0; 323 const GLboolean swStencil = mesaVis->stencilBits > 0 && 324 mesaVis->depthBits != 24; 325 driDrawPriv->driverPrivate = (void *) 326 _mesa_create_framebuffer( mesaVis, 327 swDepth, 328 swStencil, 329 swAccum, 330 swAlpha ); 331 return (driDrawPriv->driverPrivate != NULL); 332 } 333} 334 335 336static void 337radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) 338{ 339 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); 340} 341 342 343 344 345/* Fullscreen mode isn't used for much -- could be a way to shrink 346 * front/back buffers & get more texture memory if the client has 347 * changed the video resolution. 348 * 349 * Pageflipping is now done automatically whenever there is a single 350 * 3d client. 351 */ 352static GLboolean 353radeonOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv ) 354{ 355 return GL_TRUE; 356} 357 358static struct __DriverAPIRec radeonAPI = { 359 .InitDriver = radeonInitDriver, 360 .DestroyScreen = radeonDestroyScreen, 361 .CreateContext = radeonCreateContext, 362 .DestroyContext = radeonDestroyContext, 363 .CreateBuffer = radeonCreateBuffer, 364 .DestroyBuffer = radeonDestroyBuffer, 365 .SwapBuffers = radeonSwapBuffers, 366 .MakeCurrent = radeonMakeCurrent, 367 .UnbindContext = radeonUnbindContext, 368 .OpenFullScreen = radeonOpenCloseFullScreen, 369 .CloseFullScreen = radeonOpenCloseFullScreen, 370 .GetSwapInfo = getSwapInfo, 371 .GetMSC = driGetMSC32, 372 .WaitForMSC = driWaitForMSC32, 373 .WaitForSBC = NULL, 374 .SwapBuffersMSC = NULL 375}; 376 377 378 379/* 380 * This is the bootstrap function for the driver. 381 * The __driCreateScreen name is the symbol that libGL.so fetches. 382 * Return: pointer to a __DRIscreenPrivate. 383 */ 384#ifndef _SOLO 385void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc, 386 int numConfigs, __GLXvisualConfig *config) 387{ 388 __DRIscreenPrivate *psp; 389 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &radeonAPI); 390 return (void *) psp; 391} 392#else 393void *__driCreateScreen(struct DRIDriverRec *driver, 394 struct DRIDriverContextRec *driverContext) 395{ 396 __DRIscreenPrivate *psp; 397 psp = __driUtilCreateScreen(driver, driverContext, &radeonAPI); 398 return (void *) psp; 399} 400#endif 401 402#ifndef _SOLO 403/** 404 * This function is called by libGL.so as soon as libGL.so is loaded. 405 * This is where we'd register new extension functions with the dispatcher. 406 * 407 * \todo This interface has been deprecated, so we should probably remove 408 * this function before the next XFree86 release. 409 */ 410void 411__driRegisterExtensions( void ) 412{ 413 PFNGLXENABLEEXTENSIONPROC glx_enable_extension; 414 415 416 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) { 417 glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC) 418 glXGetProcAddress( (const GLubyte *) "__glXEnableExtension" ); 419 420 if ( glx_enable_extension != NULL ) { 421 (*glx_enable_extension)( "GLX_SGI_swap_control", GL_FALSE ); 422 (*glx_enable_extension)( "GLX_SGI_video_sync", GL_FALSE ); 423 (*glx_enable_extension)( "GLX_MESA_swap_control", GL_FALSE ); 424 (*glx_enable_extension)( "GLX_MESA_swap_frame_usage", GL_FALSE ); 425 } 426 } 427} 428#endif 429 430/** 431 * Get information about previous buffer swaps. 432 */ 433static int 434getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo ) 435{ 436 radeonContextPtr rmesa; 437 438 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL) 439 || (dPriv->driContextPriv->driverPrivate == NULL) 440 || (sInfo == NULL) ) { 441 return -1; 442 } 443 444 rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; 445 sInfo->swap_count = rmesa->swap_count; 446 sInfo->swap_ust = rmesa->swap_ust; 447 sInfo->swap_missed_count = rmesa->swap_missed_count; 448 449 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) 450 ? driCalculateSwapUsage( dPriv, 0, rmesa->swap_missed_ust ) 451 : 0.0; 452 453 return 0; 454} 455