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