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