2 /**************************************************************************
4 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
6 The Weather Channel (TM) funded Tungsten Graphics to develop the
7 initial release of the Radeon 8500 driver under the XFree86 license.
8 This notice must be preserved.
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial
20 portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 * Keith Whitwell <keith@tungstengraphics.com>
43 #include "r200_screen.h"
44 #include "r200_context.h"
45 #include "r200_ioctl.h"
51 #include "glxextensions.h"
55 /* Including xf86PciInfo.h introduces a bunch of errors...
57 #define PCI_CHIP_R200_QD 0x5144
58 #define PCI_CHIP_R200_QE 0x5145
59 #define PCI_CHIP_R200_QF 0x5146
60 #define PCI_CHIP_R200_QG 0x5147
61 #define PCI_CHIP_R200_QY 0x5159
62 #define PCI_CHIP_R200_QZ 0x515A
63 #define PCI_CHIP_R200_LW 0x4C57
64 #define PCI_CHIP_R200_LY 0x4C59
65 #define PCI_CHIP_R200_LZ 0x4C5A
66 #define PCI_CHIP_RV200_QW 0x5157 /* Radeon 7500 - not an R200 at all */
69 static r200ScreenPtr __r200Screen
;
71 static int getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
);
73 /* Create the device specific screen private data struct.
76 r200CreateScreen( __DRIscreenPrivate
*sPriv
)
79 RADEONDRIPtr dri_priv
= (RADEONDRIPtr
)sPriv
->pDevPriv
;
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
;
112 /* This is first since which regions we map depends on whether or
113 * not we are using a PCI card.
115 screen
->IsPCI
= dri_priv
->IsPCI
;
119 drmRadeonGetParam gp
;
121 gp
.param
= RADEON_PARAM_AGP_BUFFER_OFFSET
;
122 gp
.value
= &screen
->agp_buffer_offset
;
124 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_RADEON_GETPARAM
,
128 fprintf(stderr
, "drmRadeonGetParam (RADEON_PARAM_AGP_BUFFER_OFFSET): %d\n", ret
);
132 screen
->agp_texture_offset
=
133 screen
->agp_buffer_offset
+ 2*1024*1024;
136 if (sPriv
->drmMinor
>= 6) {
137 gp
.param
= RADEON_PARAM_AGP_BASE
;
138 gp
.value
= &screen
->agp_base
;
140 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_RADEON_GETPARAM
,
144 fprintf(stderr
, "drmR200GetParam (RADEON_PARAM_AGP_BASE): %d\n", ret
);
149 gp
.param
= RADEON_PARAM_IRQ_NR
;
150 gp
.value
= &screen
->irq
;
152 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_RADEON_GETPARAM
,
156 fprintf(stderr
, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret
);
160 /* Check if kernel module is new enough to support cube maps */
161 screen
->drmSupportsCubeMaps
= (sPriv
->drmMinor
>= 7);
165 screen
->mmio
.handle
= dri_priv
->registerHandle
;
166 screen
->mmio
.size
= dri_priv
->registerSize
;
167 if ( drmMap( sPriv
->fd
,
170 &screen
->mmio
.map
) ) {
172 __driUtilMessage("%s: drmMap failed\n", __FUNCTION__
);
176 screen
->status
.handle
= dri_priv
->statusHandle
;
177 screen
->status
.size
= dri_priv
->statusSize
;
178 if ( drmMap( sPriv
->fd
,
179 screen
->status
.handle
,
181 &screen
->status
.map
) ) {
182 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
184 __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__
);
187 screen
->scratch
= (__volatile__ CARD32
*)
188 ((GLubyte
*)screen
->status
.map
+ RADEON_SCRATCH_REG_OFFSET
);
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
);
195 __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__
);
199 if ( !screen
->IsPCI
) {
200 screen
->agpTextures
.handle
= dri_priv
->agpTexHandle
;
201 screen
->agpTextures
.size
= dri_priv
->agpTexMapSize
;
202 if ( drmMap( sPriv
->fd
,
203 screen
->agpTextures
.handle
,
204 screen
->agpTextures
.size
,
205 (drmAddressPtr
)&screen
->agpTextures
.map
) ) {
206 drmUnmapBufs( screen
->buffers
);
207 drmUnmap( screen
->status
.map
, screen
->status
.size
);
208 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
210 __driUtilMessage("%s: IsPCI failed\n", __FUNCTION__
);
217 screen
->cpp
= dri_priv
->bpp
/ 8;
218 screen
->AGPMode
= dri_priv
->AGPMode
;
220 screen
->frontOffset
= dri_priv
->frontOffset
;
221 screen
->frontPitch
= dri_priv
->frontPitch
;
222 screen
->backOffset
= dri_priv
->backOffset
;
223 screen
->backPitch
= dri_priv
->backPitch
;
224 screen
->depthOffset
= dri_priv
->depthOffset
;
225 screen
->depthPitch
= dri_priv
->depthPitch
;
227 screen
->texOffset
[RADEON_CARD_HEAP
] = dri_priv
->textureOffset
;
228 screen
->texSize
[RADEON_CARD_HEAP
] = dri_priv
->textureSize
;
229 screen
->logTexGranularity
[RADEON_CARD_HEAP
] =
230 dri_priv
->log2TexGran
;
232 if ( screen
->IsPCI
) {
233 screen
->numTexHeaps
= RADEON_NR_TEX_HEAPS
- 1;
234 screen
->texOffset
[RADEON_AGP_HEAP
] = 0;
235 screen
->texSize
[RADEON_AGP_HEAP
] = 0;
236 screen
->logTexGranularity
[RADEON_AGP_HEAP
] = 0;
238 screen
->numTexHeaps
= RADEON_NR_TEX_HEAPS
;
239 screen
->texOffset
[RADEON_AGP_HEAP
] =
240 dri_priv
->agpTexOffset
+ R200_AGP_TEX_OFFSET
;
241 screen
->texSize
[RADEON_AGP_HEAP
] = dri_priv
->agpTexMapSize
;
242 screen
->logTexGranularity
[RADEON_AGP_HEAP
] =
243 dri_priv
->log2AGPTexGran
;
246 screen
->driScreen
= sPriv
;
247 screen
->sarea_priv_offset
= dri_priv
->sarea_priv_offset
;
251 /* Destroy the device specific screen private data struct.
254 r200DestroyScreen( __DRIscreenPrivate
*sPriv
)
256 r200ScreenPtr screen
= (r200ScreenPtr
)sPriv
->private;
261 if ( !screen
->IsPCI
) {
262 drmUnmap( screen
->agpTextures
.map
,
263 screen
->agpTextures
.size
);
265 drmUnmapBufs( screen
->buffers
);
266 drmUnmap( screen
->status
.map
, screen
->status
.size
);
267 drmUnmap( screen
->mmio
.map
, screen
->mmio
.size
);
270 sPriv
->private = NULL
;
274 /* Initialize the driver specific screen private data.
277 r200InitDriver( __DRIscreenPrivate
*sPriv
)
279 __r200Screen
= r200CreateScreen( sPriv
);
281 sPriv
->private = (void *) __r200Screen
;
283 return sPriv
->private ? GL_TRUE
: GL_FALSE
;
288 /* Create and initialize the Mesa and driver specific pixmap buffer
292 r200CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
293 __DRIdrawablePrivate
*driDrawPriv
,
294 const __GLcontextModes
*mesaVis
,
298 return GL_FALSE
; /* not implemented */
301 const GLboolean swDepth
= GL_FALSE
;
302 const GLboolean swAlpha
= GL_FALSE
;
303 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
304 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 &&
305 mesaVis
->depthBits
!= 24;
306 driDrawPriv
->driverPrivate
= (void *)
307 _mesa_create_framebuffer( mesaVis
,
312 return (driDrawPriv
->driverPrivate
!= NULL
);
318 r200DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
320 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
326 /* Fullscreen mode isn't used for much -- could be a way to shrink
327 * front/back buffers & get more texture memory if the client has
328 * changed the video resolution.
330 * Pageflipping is now done automatically whenever there is a single
334 r200OpenCloseFullScreen( __DRIcontextPrivate
*driContextPriv
)
339 static struct __DriverAPIRec r200API
= {
340 .InitDriver
= r200InitDriver
,
341 .DestroyScreen
= r200DestroyScreen
,
342 .CreateContext
= r200CreateContext
,
343 .DestroyContext
= r200DestroyContext
,
344 .CreateBuffer
= r200CreateBuffer
,
345 .DestroyBuffer
= r200DestroyBuffer
,
346 .SwapBuffers
= r200SwapBuffers
,
347 .MakeCurrent
= r200MakeCurrent
,
348 .UnbindContext
= r200UnbindContext
,
349 .OpenFullScreen
= r200OpenCloseFullScreen
,
350 .CloseFullScreen
= r200OpenCloseFullScreen
,
351 .GetSwapInfo
= getSwapInfo
,
352 .GetMSC
= driGetMSC32
,
353 .WaitForMSC
= driWaitForMSC32
,
355 .SwapBuffersMSC
= NULL
360 * This is the bootstrap function for the driver.
361 * The __driCreateScreen name is the symbol that libGL.so fetches.
362 * Return: pointer to a __DRIscreenPrivate.
366 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
367 int numConfigs
, __GLXvisualConfig
*config
)
369 __DRIscreenPrivate
*psp
;
370 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &r200API
);
374 void *__driCreateScreen(struct DRIDriverRec
*driver
,
375 struct DRIDriverContextRec
*driverContext
)
377 __DRIscreenPrivate
*psp
;
378 psp
= __driUtilCreateScreen(driver
, driverContext
, &r200API
);
386 /* This function is called by libGL.so to allow the driver to dynamically
387 * extend libGL. We can add new GLX functions and/or new GL functions.
388 * Note that _mesa_create_context() will probably add most of the newer
389 * OpenGL extension functions into the dispatcher.
392 __driRegisterExtensions( void )
394 PFNGLXENABLEEXTENSIONPROC glx_enable_extension
;
395 typedef void *(*registerFunc
)(const char *funcName
, void *funcAddr
);
396 registerFunc regFunc
;
399 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
400 glx_enable_extension
= (PFNGLXENABLEEXTENSIONPROC
)
401 glXGetProcAddress( "__glXEnableExtension" );
403 if ( glx_enable_extension
!= NULL
) {
404 glx_enable_extension( "GLX_SGI_swap_control", GL_FALSE
);
405 glx_enable_extension( "GLX_SGI_video_sync", GL_FALSE
);
406 glx_enable_extension( "GLX_MESA_swap_control", GL_FALSE
);
407 glx_enable_extension( "GLX_MESA_swap_frame_usage", GL_FALSE
);
410 /* Get pointers to libGL's __glXRegisterGLXFunction
411 * and __glXRegisterGLXExtensionString, if they exist.
413 regFunc
= (registerFunc
) glXGetProcAddress( "__glXRegisterGLXFunction" );
416 /* register our GLX extensions with libGL */
418 p
= regFunc("glXAllocateMemoryNV", (void *) r200AllocateMemoryNV
);
420 ; /* XXX already registered - what to do, wrap? */
422 p
= regFunc("glXFreeMemoryNV", (void *) r200FreeMemoryNV
);
424 ; /* XXX already registered - what to do, wrap? */
426 p
= regFunc("glXGetAGPOffsetMESA", (void *) r200GetAGPOffset
);
428 ; /* XXX already registered - what to do, wrap? */
430 glx_enable_extension( "GLX_NV_vertex_array_range", GL_TRUE
);
431 glx_enable_extension( "GLX_MESA_agp_offset", GL_TRUE
);
439 * Get information about previous buffer swaps.
442 getSwapInfo( __DRIdrawablePrivate
*dPriv
, __DRIswapInfo
* sInfo
)
444 r200ContextPtr rmesa
;
446 if ( (dPriv
== NULL
) || (dPriv
->driContextPriv
== NULL
)
447 || (dPriv
->driContextPriv
->driverPrivate
== NULL
)
448 || (sInfo
== NULL
) ) {
452 rmesa
= (r200ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
453 sInfo
->swap_count
= rmesa
->swap_count
;
454 sInfo
->swap_ust
= rmesa
->swap_ust
;
455 sInfo
->swap_missed_count
= rmesa
->swap_missed_count
;
457 sInfo
->swap_missed_usage
= (sInfo
->swap_missed_count
!= 0)
458 ? driCalculateSwapUsage( dPriv
, 0, rmesa
->swap_missed_ust
)