1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_screen.c,v 1.4 2003/05/08 09:25:35 herrb Exp $ */
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
42 #include "r200_screen.h"
43 #include "r200_context.h"
44 #include "r200_ioctl.h"
45 #include "radeon_macros.h"
46 #include "radeon_reg.h"
51 #include "glxextensions.h"
58 const char __driConfigOptions
[] =
60 DRI_CONF_SECTION_PERFORMANCE
61 DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN
)
62 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS
)
63 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
65 DRI_CONF_SECTION_QUALITY
66 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB
)
67 DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER
)
68 DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC
)
69 DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF
)
71 DRI_CONF_SECTION_DEBUG
72 DRI_CONF_NO_RAST(false)
75 static const GLuint __driNConfigOptions
= 8;
78 /* Including xf86PciInfo.h introduces a bunch of errors...
80 #define PCI_CHIP_R200_QD 0x5144
81 #define PCI_CHIP_R200_QE 0x5145
82 #define PCI_CHIP_R200_QF 0x5146
83 #define PCI_CHIP_R200_QG 0x5147
84 #define PCI_CHIP_R200_QY 0x5159
85 #define PCI_CHIP_R200_QZ 0x515A
86 #define PCI_CHIP_R200_LW 0x4C57
87 #define PCI_CHIP_R200_LY 0x4C59
88 #define PCI_CHIP_R200_LZ 0x4C5A
89 #define PCI_CHIP_RV200_QW 0x5157 /* Radeon 7500 - not an R200 at all */
92 static r200ScreenPtr __r200Screen
;
94 static int getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
);
96 /* Create the device specific screen private data struct.
99 r200CreateScreen( __DRIscreenPrivate
*sPriv
)
101 r200ScreenPtr screen
;
102 RADEONDRIPtr dri_priv
= (RADEONDRIPtr
)sPriv
->pDevPriv
;
103 unsigned char *RADEONMMIO
;
105 if ( ! driCheckDriDdxDrmVersions( sPriv
, "R200", 4, 0, 4, 0, 1, 5 ) )
108 /* Allocate the private area */
109 screen
= (r200ScreenPtr
) CALLOC( sizeof(*screen
) );
111 __driUtilMessage("%s: Could not allocate memory for screen structure",
116 switch ( dri_priv
->deviceID
) {
117 case PCI_CHIP_R200_QD
:
118 case PCI_CHIP_R200_QE
:
119 case PCI_CHIP_R200_QF
:
120 case PCI_CHIP_R200_QG
:
121 case PCI_CHIP_R200_QY
:
122 case PCI_CHIP_R200_QZ
:
123 case PCI_CHIP_RV200_QW
:
124 case PCI_CHIP_R200_LW
:
125 case PCI_CHIP_R200_LY
:
126 case PCI_CHIP_R200_LZ
:
127 __driUtilMessage("r200CreateScreen(): Device isn't an r200!\n");
131 screen
->chipset
= R200_CHIPSET_R200
;
135 /* parse information in __driConfigOptions */
136 driParseOptionInfo (&screen
->optionCache
,
137 __driConfigOptions
, __driNConfigOptions
);
139 /* This is first since which regions we map depends on whether or
140 * not we are using a PCI card.
142 screen
->IsPCI
= dri_priv
->IsPCI
;
146 drmRadeonGetParam gp
;
148 gp
.param
= RADEON_PARAM_GART_BUFFER_OFFSET
;
149 gp
.value
= &screen
->gart_buffer_offset
;
151 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_RADEON_GETPARAM
,
155 fprintf(stderr
, "drmRadeonGetParam (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret
);
159 if (sPriv
->drmMinor
>= 6) {
160 gp
.param
= RADEON_PARAM_GART_BASE
;
161 gp
.value
= &screen
->gart_base
;
163 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_RADEON_GETPARAM
,
167 fprintf(stderr
, "drmR200GetParam (RADEON_PARAM_GART_BASE): %d\n", ret
);
172 gp
.param
= RADEON_PARAM_IRQ_NR
;
173 gp
.value
= &screen
->irq
;
175 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_RADEON_GETPARAM
,
179 fprintf(stderr
, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret
);
183 /* Check if kernel module is new enough to support cube maps */
184 screen
->drmSupportsCubeMaps
= (sPriv
->drmMinor
>= 7);
188 screen
->mmio
.handle
= dri_priv
->registerHandle
;
189 screen
->mmio
.size
= dri_priv
->registerSize
;
190 if ( drmMap( sPriv
->fd
,
193 &screen
->mmio
.map
) ) {
195 __driUtilMessage("%s: drmMap failed\n", __FUNCTION__
);
199 screen
->status
.handle
= dri_priv
->statusHandle
;
200 screen
->status
.size
= dri_priv
->statusSize
;
201 if ( drmMap( sPriv
->fd
,
202 screen
->status
.handle
,
204 &screen
->status
.map
) ) {
205 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
207 __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__
);
210 screen
->scratch
= (__volatile__ CARD32
*)
211 ((GLubyte
*)screen
->status
.map
+ RADEON_SCRATCH_REG_OFFSET
);
213 screen
->buffers
= drmMapBufs( sPriv
->fd
);
214 if ( !screen
->buffers
) {
215 drmUnmap( screen
->status
.map
, screen
->status
.size
);
216 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
218 __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__
);
222 RADEONMMIO
= screen
->mmio
.map
;
224 if ( dri_priv
->gartTexHandle
&& dri_priv
->gartTexMapSize
) {
226 screen
->gartTextures
.handle
= dri_priv
->gartTexHandle
;
227 screen
->gartTextures
.size
= dri_priv
->gartTexMapSize
;
228 if ( drmMap( sPriv
->fd
,
229 screen
->gartTextures
.handle
,
230 screen
->gartTextures
.size
,
231 (drmAddressPtr
)&screen
->gartTextures
.map
) ) {
232 drmUnmapBufs( screen
->buffers
);
233 drmUnmap( screen
->status
.map
, screen
->status
.size
);
234 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
236 __driUtilMessage("%s: drmMAP failed for GART texture area\n", __FUNCTION__
);
240 screen
->gart_texture_offset
= dri_priv
->gartTexOffset
+ ( screen
->IsPCI
241 ? INREG( RADEON_AIC_LO_ADDR
)
242 : ( ( INREG( RADEON_MC_AGP_LOCATION
) & 0x0ffffU
) << 16 ) );
245 screen
->cpp
= dri_priv
->bpp
/ 8;
246 screen
->AGPMode
= dri_priv
->AGPMode
;
248 screen
->fbLocation
= ( INREG( RADEON_MC_FB_LOCATION
) & 0xffff ) << 16;
250 if ( sPriv
->drmMinor
>= 10 ) {
251 drmRadeonSetParam sp
;
253 sp
.param
= RADEON_SETPARAM_FB_LOCATION
;
254 sp
.value
= screen
->fbLocation
;
256 drmCommandWrite( sPriv
->fd
, DRM_RADEON_SETPARAM
,
260 screen
->frontOffset
= dri_priv
->frontOffset
;
261 screen
->frontPitch
= dri_priv
->frontPitch
;
262 screen
->backOffset
= dri_priv
->backOffset
;
263 screen
->backPitch
= dri_priv
->backPitch
;
264 screen
->depthOffset
= dri_priv
->depthOffset
;
265 screen
->depthPitch
= dri_priv
->depthPitch
;
267 screen
->texOffset
[RADEON_CARD_HEAP
] = dri_priv
->textureOffset
268 + screen
->fbLocation
;
269 screen
->texSize
[RADEON_CARD_HEAP
] = dri_priv
->textureSize
;
270 screen
->logTexGranularity
[RADEON_CARD_HEAP
] =
271 dri_priv
->log2TexGran
;
273 if ( !screen
->gartTextures
.map
) {
274 screen
->numTexHeaps
= RADEON_NR_TEX_HEAPS
- 1;
275 screen
->texOffset
[RADEON_GART_HEAP
] = 0;
276 screen
->texSize
[RADEON_GART_HEAP
] = 0;
277 screen
->logTexGranularity
[RADEON_GART_HEAP
] = 0;
279 screen
->numTexHeaps
= RADEON_NR_TEX_HEAPS
;
280 screen
->texOffset
[RADEON_GART_HEAP
] = screen
->gart_texture_offset
;
281 screen
->texSize
[RADEON_GART_HEAP
] = dri_priv
->gartTexMapSize
;
282 screen
->logTexGranularity
[RADEON_GART_HEAP
] =
283 dri_priv
->log2GARTTexGran
;
286 screen
->driScreen
= sPriv
;
287 screen
->sarea_priv_offset
= dri_priv
->sarea_priv_offset
;
289 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
290 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
291 (PFNGLXSCRENABLEEXTENSIONPROC
) glXGetProcAddress( (const GLubyte
*) "__glXScrEnableExtension" );
292 void * const psc
= sPriv
->psc
->screenConfigs
;
294 if ( glx_enable_extension
!= NULL
) {
295 if ( screen
->irq
!= 0 ) {
296 (*glx_enable_extension
)( psc
, "GLX_SGI_swap_control" );
297 (*glx_enable_extension
)( psc
, "GLX_SGI_video_sync" );
298 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_control" );
301 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_frame_usage" );
303 if ( driCompareGLXAPIVersion( 20030818 ) >= 0 ) {
304 sPriv
->psc
->allocateMemory
= r200AllocateMemoryMESA
;
305 sPriv
->psc
->freeMemory
= r200FreeMemoryMESA
;
306 sPriv
->psc
->memoryOffset
= r200GetMemoryOffsetMESA
;
308 (*glx_enable_extension
)( psc
, "GLX_MESA_allocate_memory" );
316 /* Destroy the device specific screen private data struct.
319 r200DestroyScreen( __DRIscreenPrivate
*sPriv
)
321 r200ScreenPtr screen
= (r200ScreenPtr
)sPriv
->private;
326 if ( screen
->gartTextures
.map
) {
327 drmUnmap( screen
->gartTextures
.map
, screen
->gartTextures
.size
);
329 drmUnmapBufs( screen
->buffers
);
330 drmUnmap( screen
->status
.map
, screen
->status
.size
);
331 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
333 /* free all option information */
334 driDestroyOptionInfo (&screen
->optionCache
);
337 sPriv
->private = NULL
;
341 /* Initialize the driver specific screen private data.
344 r200InitDriver( __DRIscreenPrivate
*sPriv
)
346 __r200Screen
= r200CreateScreen( sPriv
);
348 sPriv
->private = (void *) __r200Screen
;
350 return sPriv
->private ? GL_TRUE
: GL_FALSE
;
355 /* Create and initialize the Mesa and driver specific pixmap buffer
359 r200CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
360 __DRIdrawablePrivate
*driDrawPriv
,
361 const __GLcontextModes
*mesaVis
,
365 return GL_FALSE
; /* not implemented */
368 const GLboolean swDepth
= GL_FALSE
;
369 const GLboolean swAlpha
= GL_FALSE
;
370 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
371 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 &&
372 mesaVis
->depthBits
!= 24;
373 driDrawPriv
->driverPrivate
= (void *)
374 _mesa_create_framebuffer( mesaVis
,
379 return (driDrawPriv
->driverPrivate
!= NULL
);
385 r200DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
387 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
393 /* Fullscreen mode isn't used for much -- could be a way to shrink
394 * front/back buffers & get more texture memory if the client has
395 * changed the video resolution.
397 * Pageflipping is now done automatically whenever there is a single
401 r200OpenCloseFullScreen( __DRIcontextPrivate
*driContextPriv
)
406 static struct __DriverAPIRec r200API
= {
407 .InitDriver
= r200InitDriver
,
408 .DestroyScreen
= r200DestroyScreen
,
409 .CreateContext
= r200CreateContext
,
410 .DestroyContext
= r200DestroyContext
,
411 .CreateBuffer
= r200CreateBuffer
,
412 .DestroyBuffer
= r200DestroyBuffer
,
413 .SwapBuffers
= r200SwapBuffers
,
414 .MakeCurrent
= r200MakeCurrent
,
415 .UnbindContext
= r200UnbindContext
,
416 .OpenFullScreen
= r200OpenCloseFullScreen
,
417 .CloseFullScreen
= r200OpenCloseFullScreen
,
418 .GetSwapInfo
= getSwapInfo
,
419 .GetMSC
= driGetMSC32
,
420 .WaitForMSC
= driWaitForMSC32
,
422 .SwapBuffersMSC
= NULL
427 * This is the bootstrap function for the driver.
428 * The __driCreateScreen name is the symbol that libGL.so fetches.
429 * Return: pointer to a __DRIscreenPrivate.
433 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
434 int numConfigs
, __GLXvisualConfig
*config
)
436 __DRIscreenPrivate
*psp
;
437 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &r200API
);
441 void *__driCreateScreen(struct DRIDriverRec
*driver
,
442 struct DRIDriverContextRec
*driverContext
)
444 __DRIscreenPrivate
*psp
;
445 psp
= __driUtilCreateScreen(driver
, driverContext
, &r200API
);
452 * This function is called by libGL.so to allow the driver to dynamically
453 * extend libGL. We can add new GLX functions and/or new GL functions.
454 * Note that _mesa_create_context() will probably add most of the newer
455 * OpenGL extension functions into the dispatcher.
457 * \todo This interface has been deprecated, so we should probably remove
458 * this function before the next XFree86 release.
461 __driRegisterExtensions( void )
463 PFNGLXENABLEEXTENSIONPROC glx_enable_extension
;
466 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
467 glx_enable_extension
= (PFNGLXENABLEEXTENSIONPROC
)
468 glXGetProcAddress( (const GLubyte
*) "__glXEnableExtension" );
470 if ( glx_enable_extension
!= NULL
) {
471 (*glx_enable_extension
)( "GLX_SGI_swap_control", GL_FALSE
);
472 (*glx_enable_extension
)( "GLX_SGI_video_sync", GL_FALSE
);
473 (*glx_enable_extension
)( "GLX_MESA_swap_control", GL_FALSE
);
474 (*glx_enable_extension
)( "GLX_MESA_swap_frame_usage", GL_FALSE
);
481 * Get information about previous buffer swaps.
484 getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
)
486 r200ContextPtr rmesa
;
488 if ( (dPriv
== NULL
) || (dPriv
->driContextPriv
== NULL
)
489 || (dPriv
->driContextPriv
->driverPrivate
== NULL
)
490 || (sInfo
== NULL
) ) {
494 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
495 sInfo
->swap_count
= rmesa
->swap_count
;
496 sInfo
->swap_ust
= rmesa
->swap_ust
;
497 sInfo
->swap_missed_count
= rmesa
->swap_missed_count
;
499 sInfo
->swap_missed_usage
= (sInfo
->swap_missed_count
!= 0)
500 ? driCalculateSwapUsage( dPriv
, 0, rmesa
->swap_missed_ust
)