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"
54 /* Including xf86PciInfo.h introduces a bunch of errors...
56 #define PCI_CHIP_R200_QD 0x5144
57 #define PCI_CHIP_R200_QE 0x5145
58 #define PCI_CHIP_R200_QF 0x5146
59 #define PCI_CHIP_R200_QG 0x5147
60 #define PCI_CHIP_R200_QY 0x5159
61 #define PCI_CHIP_R200_QZ 0x515A
62 #define PCI_CHIP_R200_LW 0x4C57
63 #define PCI_CHIP_R200_LY 0x4C59
64 #define PCI_CHIP_R200_LZ 0x4C5A
65 #define PCI_CHIP_RV200_QW 0x5157 /* Radeon 7500 - not an R200 at all */
68 static r200ScreenPtr __r200Screen
;
70 static int getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
);
72 /* Create the device specific screen private data struct.
75 r200CreateScreen( __DRIscreenPrivate
*sPriv
)
78 RADEONDRIPtr dri_priv
= (RADEONDRIPtr
)sPriv
->pDevPriv
;
79 unsigned char *RADEONMMIO
;
81 if ( ! driCheckDriDdxDrmVersions( sPriv
, "R200", 4, 0, 4, 0, 1, 5 ) )
84 /* Allocate the private area */
85 screen
= (r200ScreenPtr
) CALLOC( sizeof(*screen
) );
87 __driUtilMessage("%s: Could not allocate memory for screen structure",
92 switch ( dri_priv
->deviceID
) {
93 case PCI_CHIP_R200_QD
:
94 case PCI_CHIP_R200_QE
:
95 case PCI_CHIP_R200_QF
:
96 case PCI_CHIP_R200_QG
:
97 case PCI_CHIP_R200_QY
:
98 case PCI_CHIP_R200_QZ
:
99 case PCI_CHIP_RV200_QW
:
100 case PCI_CHIP_R200_LW
:
101 case PCI_CHIP_R200_LY
:
102 case PCI_CHIP_R200_LZ
:
103 __driUtilMessage("r200CreateScreen(): Device isn't an r200!\n");
107 screen
->chipset
= R200_CHIPSET_R200
;
111 /* parse information in __driConfigOptions */
112 driParseOptionInfo (&screen
->optionCache
);
114 /* This is first since which regions we map depends on whether or
115 * not we are using a PCI card.
117 screen
->IsPCI
= dri_priv
->IsPCI
;
121 drmRadeonGetParam gp
;
123 gp
.param
= RADEON_PARAM_GART_BUFFER_OFFSET
;
124 gp
.value
= &screen
->gart_buffer_offset
;
126 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_RADEON_GETPARAM
,
130 fprintf(stderr
, "drmRadeonGetParam (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret
);
134 if (sPriv
->drmMinor
>= 6) {
135 gp
.param
= RADEON_PARAM_GART_BASE
;
136 gp
.value
= &screen
->gart_base
;
138 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_RADEON_GETPARAM
,
142 fprintf(stderr
, "drmR200GetParam (RADEON_PARAM_GART_BASE): %d\n", ret
);
147 gp
.param
= RADEON_PARAM_IRQ_NR
;
148 gp
.value
= &screen
->irq
;
150 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_RADEON_GETPARAM
,
154 fprintf(stderr
, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret
);
158 /* Check if kernel module is new enough to support cube maps */
159 screen
->drmSupportsCubeMaps
= (sPriv
->drmMinor
>= 7);
163 screen
->mmio
.handle
= dri_priv
->registerHandle
;
164 screen
->mmio
.size
= dri_priv
->registerSize
;
165 if ( drmMap( sPriv
->fd
,
168 &screen
->mmio
.map
) ) {
170 __driUtilMessage("%s: drmMap failed\n", __FUNCTION__
);
174 screen
->status
.handle
= dri_priv
->statusHandle
;
175 screen
->status
.size
= dri_priv
->statusSize
;
176 if ( drmMap( sPriv
->fd
,
177 screen
->status
.handle
,
179 &screen
->status
.map
) ) {
180 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
182 __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__
);
185 screen
->scratch
= (__volatile__ CARD32
*)
186 ((GLubyte
*)screen
->status
.map
+ RADEON_SCRATCH_REG_OFFSET
);
188 screen
->buffers
= drmMapBufs( sPriv
->fd
);
189 if ( !screen
->buffers
) {
190 drmUnmap( screen
->status
.map
, screen
->status
.size
);
191 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
193 __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__
);
197 RADEONMMIO
= screen
->mmio
.map
;
199 if ( dri_priv
->gartTexHandle
&& dri_priv
->gartTexMapSize
) {
201 screen
->gartTextures
.handle
= dri_priv
->gartTexHandle
;
202 screen
->gartTextures
.size
= dri_priv
->gartTexMapSize
;
203 if ( drmMap( sPriv
->fd
,
204 screen
->gartTextures
.handle
,
205 screen
->gartTextures
.size
,
206 (drmAddressPtr
)&screen
->gartTextures
.map
) ) {
207 drmUnmapBufs( screen
->buffers
);
208 drmUnmap( screen
->status
.map
, screen
->status
.size
);
209 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
211 __driUtilMessage("%s: drmMAP failed for GART texture area\n", __FUNCTION__
);
215 screen
->gart_texture_offset
= dri_priv
->gartTexOffset
+ ( screen
->IsPCI
216 ? INREG( RADEON_AIC_LO_ADDR
)
217 : ( ( INREG( RADEON_MC_AGP_LOCATION
) & 0x0ffffU
) << 16 ) );
220 screen
->cpp
= dri_priv
->bpp
/ 8;
221 screen
->AGPMode
= dri_priv
->AGPMode
;
223 screen
->fbLocation
= ( INREG( RADEON_MC_FB_LOCATION
) & 0xffff ) << 16;
225 if ( sPriv
->drmMinor
>= 10 ) {
226 drmRadeonSetParam sp
;
228 sp
.param
= RADEON_SETPARAM_FB_LOCATION
;
229 sp
.value
= screen
->fbLocation
;
231 drmCommandWrite( sPriv
->fd
, DRM_RADEON_SETPARAM
,
235 screen
->frontOffset
= dri_priv
->frontOffset
;
236 screen
->frontPitch
= dri_priv
->frontPitch
;
237 screen
->backOffset
= dri_priv
->backOffset
;
238 screen
->backPitch
= dri_priv
->backPitch
;
239 screen
->depthOffset
= dri_priv
->depthOffset
;
240 screen
->depthPitch
= dri_priv
->depthPitch
;
242 screen
->texOffset
[RADEON_CARD_HEAP
] = dri_priv
->textureOffset
243 + screen
->fbLocation
;
244 screen
->texSize
[RADEON_CARD_HEAP
] = dri_priv
->textureSize
;
245 screen
->logTexGranularity
[RADEON_CARD_HEAP
] =
246 dri_priv
->log2TexGran
;
248 if ( !screen
->gartTextures
.map
) {
249 screen
->numTexHeaps
= RADEON_NR_TEX_HEAPS
- 1;
250 screen
->texOffset
[RADEON_GART_HEAP
] = 0;
251 screen
->texSize
[RADEON_GART_HEAP
] = 0;
252 screen
->logTexGranularity
[RADEON_GART_HEAP
] = 0;
254 screen
->numTexHeaps
= RADEON_NR_TEX_HEAPS
;
255 screen
->texOffset
[RADEON_GART_HEAP
] = screen
->gart_texture_offset
;
256 screen
->texSize
[RADEON_GART_HEAP
] = dri_priv
->gartTexMapSize
;
257 screen
->logTexGranularity
[RADEON_GART_HEAP
] =
258 dri_priv
->log2GARTTexGran
;
261 screen
->driScreen
= sPriv
;
262 screen
->sarea_priv_offset
= dri_priv
->sarea_priv_offset
;
264 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
265 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
266 (PFNGLXSCRENABLEEXTENSIONPROC
) glXGetProcAddress( (const GLubyte
*) "__glXScrEnableExtension" );
267 void * const psc
= sPriv
->psc
->screenConfigs
;
269 if ( glx_enable_extension
!= NULL
) {
270 if ( screen
->irq
!= 0 ) {
271 (*glx_enable_extension
)( psc
, "GLX_SGI_swap_control" );
272 (*glx_enable_extension
)( psc
, "GLX_SGI_video_sync" );
273 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_control" );
276 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_frame_usage" );
278 if ( driCompareGLXAPIVersion( 20030818 ) >= 0 ) {
279 sPriv
->psc
->allocateMemory
= r200AllocateMemoryMESA
;
280 sPriv
->psc
->freeMemory
= r200FreeMemoryMESA
;
281 sPriv
->psc
->memoryOffset
= r200GetMemoryOffsetMESA
;
283 (*glx_enable_extension
)( psc
, "GLX_MESA_allocate_memory" );
291 /* Destroy the device specific screen private data struct.
294 r200DestroyScreen( __DRIscreenPrivate
*sPriv
)
296 r200ScreenPtr screen
= (r200ScreenPtr
)sPriv
->private;
301 if ( screen
->gartTextures
.map
) {
302 drmUnmap( screen
->gartTextures
.map
, screen
->gartTextures
.size
);
304 drmUnmapBufs( screen
->buffers
);
305 drmUnmap( screen
->status
.map
, screen
->status
.size
);
306 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
308 /* free all option information */
309 driDestroyOptionInfo (&screen
->optionCache
);
312 sPriv
->private = NULL
;
316 /* Initialize the driver specific screen private data.
319 r200InitDriver( __DRIscreenPrivate
*sPriv
)
321 __r200Screen
= r200CreateScreen( sPriv
);
323 sPriv
->private = (void *) __r200Screen
;
325 return sPriv
->private ? GL_TRUE
: GL_FALSE
;
330 /* Create and initialize the Mesa and driver specific pixmap buffer
334 r200CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
335 __DRIdrawablePrivate
*driDrawPriv
,
336 const __GLcontextModes
*mesaVis
,
340 return GL_FALSE
; /* not implemented */
343 const GLboolean swDepth
= GL_FALSE
;
344 const GLboolean swAlpha
= GL_FALSE
;
345 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
346 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 &&
347 mesaVis
->depthBits
!= 24;
348 driDrawPriv
->driverPrivate
= (void *)
349 _mesa_create_framebuffer( mesaVis
,
354 return (driDrawPriv
->driverPrivate
!= NULL
);
360 r200DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
362 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
368 /* Fullscreen mode isn't used for much -- could be a way to shrink
369 * front/back buffers & get more texture memory if the client has
370 * changed the video resolution.
372 * Pageflipping is now done automatically whenever there is a single
376 r200OpenCloseFullScreen( __DRIcontextPrivate
*driContextPriv
)
381 static struct __DriverAPIRec r200API
= {
382 .InitDriver
= r200InitDriver
,
383 .DestroyScreen
= r200DestroyScreen
,
384 .CreateContext
= r200CreateContext
,
385 .DestroyContext
= r200DestroyContext
,
386 .CreateBuffer
= r200CreateBuffer
,
387 .DestroyBuffer
= r200DestroyBuffer
,
388 .SwapBuffers
= r200SwapBuffers
,
389 .MakeCurrent
= r200MakeCurrent
,
390 .UnbindContext
= r200UnbindContext
,
391 .OpenFullScreen
= r200OpenCloseFullScreen
,
392 .CloseFullScreen
= r200OpenCloseFullScreen
,
393 .GetSwapInfo
= getSwapInfo
,
394 .GetMSC
= driGetMSC32
,
395 .WaitForMSC
= driWaitForMSC32
,
397 .SwapBuffersMSC
= NULL
402 * This is the bootstrap function for the driver.
403 * The __driCreateScreen name is the symbol that libGL.so fetches.
404 * Return: pointer to a __DRIscreenPrivate.
408 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
409 int numConfigs
, __GLXvisualConfig
*config
)
411 __DRIscreenPrivate
*psp
;
412 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &r200API
);
416 void *__driCreateScreen(struct DRIDriverRec
*driver
,
417 struct DRIDriverContextRec
*driverContext
)
419 __DRIscreenPrivate
*psp
;
420 psp
= __driUtilCreateScreen(driver
, driverContext
, &r200API
);
427 * This function is called by libGL.so to allow the driver to dynamically
428 * extend libGL. We can add new GLX functions and/or new GL functions.
429 * Note that _mesa_create_context() will probably add most of the newer
430 * OpenGL extension functions into the dispatcher.
432 * \todo This interface has been deprecated, so we should probably remove
433 * this function before the next XFree86 release.
436 __driRegisterExtensions( void )
438 PFNGLXENABLEEXTENSIONPROC glx_enable_extension
;
441 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
442 glx_enable_extension
= (PFNGLXENABLEEXTENSIONPROC
)
443 glXGetProcAddress( (const GLubyte
*) "__glXEnableExtension" );
445 if ( glx_enable_extension
!= NULL
) {
446 (*glx_enable_extension
)( "GLX_SGI_swap_control", GL_FALSE
);
447 (*glx_enable_extension
)( "GLX_SGI_video_sync", GL_FALSE
);
448 (*glx_enable_extension
)( "GLX_MESA_swap_control", GL_FALSE
);
449 (*glx_enable_extension
)( "GLX_MESA_swap_frame_usage", GL_FALSE
);
456 * Get information about previous buffer swaps.
459 getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
)
461 r200ContextPtr rmesa
;
463 if ( (dPriv
== NULL
) || (dPriv
->driContextPriv
== NULL
)
464 || (dPriv
->driContextPriv
->driverPrivate
== NULL
)
465 || (sInfo
== NULL
) ) {
469 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
470 sInfo
->swap_count
= rmesa
->swap_count
;
471 sInfo
->swap_ust
= rmesa
->swap_ust
;
472 sInfo
->swap_missed_count
= rmesa
->swap_missed_count
;
474 sInfo
->swap_missed_usage
= (sInfo
->swap_missed_count
!= 0)
475 ? driCalculateSwapUsage( dPriv
, 0, rmesa
->swap_missed_ust
)