sync some more of the r200 driver from the DRI trunk
[mesa.git] / src / mesa / drivers / dri / r200 / r200_screen.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_screen.c,v 1.4 2003/05/08 09:25:35 herrb Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
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.
8
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:
16
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.
20
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.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include <dlfcn.h>
37
38 #include "glheader.h"
39 #include "imports.h"
40 #include "context.h"
41
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"
47
48 #include "utils.h"
49 #include "vblank.h"
50 #ifndef _SOLO
51 #include "glxextensions.h"
52 #endif
53 #if 1
54 /* Including xf86PciInfo.h introduces a bunch of errors...
55 */
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 */
66 #endif
67
68 static r200ScreenPtr __r200Screen;
69
70 static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
71
72 /* Create the device specific screen private data struct.
73 */
74 static r200ScreenPtr
75 r200CreateScreen( __DRIscreenPrivate *sPriv )
76 {
77 r200ScreenPtr screen;
78 RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
79 unsigned char *RADEONMMIO;
80
81 if ( ! driCheckDriDdxDrmVersions( sPriv, "R200", 4, 0, 4, 0, 1, 5 ) )
82 return NULL;
83
84 /* Allocate the private area */
85 screen = (r200ScreenPtr) CALLOC( sizeof(*screen) );
86 if ( !screen ) {
87 __driUtilMessage("%s: Could not allocate memory for screen structure",
88 __FUNCTION__);
89 return NULL;
90 }
91
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");
104 FREE( screen );
105 return NULL;
106 default:
107 screen->chipset = R200_CHIPSET_R200;
108 break;
109 }
110
111 /* parse information in __driConfigOptions */
112 driParseOptionInfo (&screen->optionCache);
113
114 /* This is first since which regions we map depends on whether or
115 * not we are using a PCI card.
116 */
117 screen->IsPCI = dri_priv->IsPCI;
118
119 {
120 int ret;
121 drmRadeonGetParam gp;
122
123 gp.param = RADEON_PARAM_GART_BUFFER_OFFSET;
124 gp.value = &screen->gart_buffer_offset;
125
126 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
127 &gp, sizeof(gp));
128 if (ret) {
129 FREE( screen );
130 fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret);
131 return NULL;
132 }
133
134 if (sPriv->drmMinor >= 6) {
135 gp.param = RADEON_PARAM_GART_BASE;
136 gp.value = &screen->gart_base;
137
138 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
139 &gp, sizeof(gp));
140 if (ret) {
141 FREE( screen );
142 fprintf(stderr, "drmR200GetParam (RADEON_PARAM_GART_BASE): %d\n", ret);
143 return NULL;
144 }
145
146
147 gp.param = RADEON_PARAM_IRQ_NR;
148 gp.value = &screen->irq;
149
150 ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
151 &gp, sizeof(gp));
152 if (ret) {
153 FREE( screen );
154 fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret);
155 return NULL;
156 }
157
158 /* Check if kernel module is new enough to support cube maps */
159 screen->drmSupportsCubeMaps = (sPriv->drmMinor >= 7);
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 screen->status.handle = dri_priv->statusHandle;
175 screen->status.size = dri_priv->statusSize;
176 if ( drmMap( sPriv->fd,
177 screen->status.handle,
178 screen->status.size,
179 &screen->status.map ) ) {
180 drmUnmap( screen->mmio.map, screen->mmio.size );
181 FREE( screen );
182 __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
183 return NULL;
184 }
185 screen->scratch = (__volatile__ CARD32 *)
186 ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
187
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 );
192 FREE( screen );
193 __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__ );
194 return NULL;
195 }
196
197 RADEONMMIO = screen->mmio.map;
198
199 if ( dri_priv->gartTexHandle && dri_priv->gartTexMapSize ) {
200
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 );
210 FREE( screen );
211 __driUtilMessage("%s: drmMAP failed for GART texture area\n", __FUNCTION__);
212 return NULL;
213 }
214
215 screen->gart_texture_offset = dri_priv->gartTexOffset + ( screen->IsPCI
216 ? INREG( RADEON_AIC_LO_ADDR )
217 : ( ( INREG( RADEON_MC_AGP_LOCATION ) & 0x0ffffU ) << 16 ) );
218 }
219
220 screen->cpp = dri_priv->bpp / 8;
221 screen->AGPMode = dri_priv->AGPMode;
222
223 screen->fbLocation = ( INREG( RADEON_MC_FB_LOCATION ) & 0xffff ) << 16;
224
225 if ( sPriv->drmMinor >= 10 ) {
226 drmRadeonSetParam sp;
227
228 sp.param = RADEON_SETPARAM_FB_LOCATION;
229 sp.value = screen->fbLocation;
230
231 drmCommandWrite( sPriv->fd, DRM_RADEON_SETPARAM,
232 &sp, sizeof( sp ) );
233 }
234
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;
241
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;
247
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;
253 } else {
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;
259 }
260
261 screen->driScreen = sPriv;
262 screen->sarea_priv_offset = dri_priv->sarea_priv_offset;
263 #ifndef _SOLO
264 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
265 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
266 (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
267 void * const psc = sPriv->psc->screenConfigs;
268
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" );
274 }
275
276 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
277
278 if ( driCompareGLXAPIVersion( 20030818 ) >= 0 ) {
279 sPriv->psc->allocateMemory = r200AllocateMemoryMESA;
280 sPriv->psc->freeMemory = r200FreeMemoryMESA;
281 sPriv->psc->memoryOffset = r200GetMemoryOffsetMESA;
282
283 (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
284 }
285 }
286 }
287 #endif
288 return screen;
289 }
290
291 /* Destroy the device specific screen private data struct.
292 */
293 static void
294 r200DestroyScreen( __DRIscreenPrivate *sPriv )
295 {
296 r200ScreenPtr screen = (r200ScreenPtr)sPriv->private;
297
298 if (!screen)
299 return;
300
301 if ( screen->gartTextures.map ) {
302 drmUnmap( screen->gartTextures.map, screen->gartTextures.size );
303 }
304 drmUnmapBufs( screen->buffers );
305 drmUnmap( screen->status.map, screen->status.size );
306 drmUnmap( screen->mmio.map, screen->mmio.size );
307
308 /* free all option information */
309 driDestroyOptionInfo (&screen->optionCache);
310
311 FREE( screen );
312 sPriv->private = NULL;
313 }
314
315
316 /* Initialize the driver specific screen private data.
317 */
318 static GLboolean
319 r200InitDriver( __DRIscreenPrivate *sPriv )
320 {
321 __r200Screen = r200CreateScreen( sPriv );
322
323 sPriv->private = (void *) __r200Screen;
324
325 return sPriv->private ? GL_TRUE : GL_FALSE;
326 }
327
328
329
330 /* Create and initialize the Mesa and driver specific pixmap buffer
331 * data.
332 */
333 static GLboolean
334 r200CreateBuffer( __DRIscreenPrivate *driScrnPriv,
335 __DRIdrawablePrivate *driDrawPriv,
336 const __GLcontextModes *mesaVis,
337 GLboolean isPixmap )
338 {
339 if (isPixmap) {
340 return GL_FALSE; /* not implemented */
341 }
342 else {
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,
350 swDepth,
351 swStencil,
352 swAccum,
353 swAlpha );
354 return (driDrawPriv->driverPrivate != NULL);
355 }
356 }
357
358
359 static void
360 r200DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
361 {
362 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
363 }
364
365
366
367
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.
371 *
372 * Pageflipping is now done automatically whenever there is a single
373 * 3d client.
374 */
375 static GLboolean
376 r200OpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
377 {
378 return GL_TRUE;
379 }
380
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,
396 .WaitForSBC = NULL,
397 .SwapBuffersMSC = NULL
398 };
399
400
401 /*
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.
405 *
406 */
407 #ifndef _SOLO
408 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
409 int numConfigs, __GLXvisualConfig *config)
410 {
411 __DRIscreenPrivate *psp;
412 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &r200API);
413 return (void *) psp;
414 }
415 #else
416 void *__driCreateScreen(struct DRIDriverRec *driver,
417 struct DRIDriverContextRec *driverContext)
418 {
419 __DRIscreenPrivate *psp;
420 psp = __driUtilCreateScreen(driver, driverContext, &r200API);
421 return (void *) psp;
422 }
423 #endif
424
425 #ifndef _SOLO
426 /**
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.
431 *
432 * \todo This interface has been deprecated, so we should probably remove
433 * this function before the next XFree86 release.
434 */
435 void
436 __driRegisterExtensions( void )
437 {
438 PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
439
440
441 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
442 glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
443 glXGetProcAddress( (const GLubyte *) "__glXEnableExtension" );
444
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 );
450 }
451 }
452 }
453 #endif
454
455 /**
456 * Get information about previous buffer swaps.
457 */
458 static int
459 getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
460 {
461 r200ContextPtr rmesa;
462
463 if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
464 || (dPriv->driContextPriv->driverPrivate == NULL)
465 || (sInfo == NULL) ) {
466 return -1;
467 }
468
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;
473
474 sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
475 ? driCalculateSwapUsage( dPriv, 0, rmesa->swap_missed_ust )
476 : 0.0;
477
478 return 0;
479 }