fixup mach64 for newer build/types
[mesa.git] / src / mesa / drivers / dri / mach64 / mach64_screen.c
1 /* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
2 /*
3 * Copyright 2000 Gareth Hughes
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /*
26 * Authors:
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * José Fonseca <j_r_fonseca@yahoo.co.uk>
30 */
31
32 #include "mach64_context.h"
33 #include "mach64_ioctl.h"
34 #include "mach64_tris.h"
35 #include "mach64_vb.h"
36
37 #include "context.h"
38 #include "imports.h"
39
40 #include "utils.h"
41 #include "vblank.h"
42
43 #ifndef _SOLO
44 #include "GL/internal/dri_interface.h"
45 #endif
46
47 /* Mach64 configuration
48 */
49 #include "xmlpool.h"
50
51 const char __driConfigOptions[] =
52 DRI_CONF_BEGIN
53 DRI_CONF_SECTION_PERFORMANCE
54 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
55 DRI_CONF_SECTION_END
56 #if ENABLE_PERF_BOXES
57 DRI_CONF_SECTION_DEBUG
58 DRI_CONF_PERFORMANCE_BOXES(false)
59 DRI_CONF_SECTION_END
60 #endif
61 DRI_CONF_END;
62 #if ENABLE_PERF_BOXES
63 static const GLuint __driNConfigOptions = 2;
64 #else
65 static const GLuint __driNConfigOptions = 1;
66 #endif
67
68 #ifdef USE_NEW_INTERFACE
69 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
70 #endif /* USE_NEW_INTERFACE */
71
72 #ifdef USE_NEW_INTERFACE
73 static __GLcontextModes * fill_in_modes( __GLcontextModes * modes,
74 unsigned pixel_bits,
75 unsigned depth_bits,
76 unsigned stencil_bits,
77 const GLenum * db_modes,
78 unsigned num_db_modes,
79 int visType )
80 {
81 static const uint8_t bits[2][4] = {
82 { 5, 6, 5, 0 },
83 { 8, 8, 8, 0 }
84 };
85
86 static const uint32_t masks[2][4] = {
87 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
88 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }
89 };
90
91 unsigned i;
92 unsigned j;
93 const unsigned index = ((pixel_bits + 15) / 16) - 1;
94
95 for ( i = 0 ; i < num_db_modes ; i++ ) {
96 for ( j = 0 ; j < 2 ; j++ ) {
97
98 modes->redBits = bits[index][0];
99 modes->greenBits = bits[index][1];
100 modes->blueBits = bits[index][2];
101 modes->alphaBits = bits[index][3];
102 modes->redMask = masks[index][0];
103 modes->greenMask = masks[index][1];
104 modes->blueMask = masks[index][2];
105 modes->alphaMask = masks[index][3];
106 modes->rgbBits = modes->redBits + modes->greenBits
107 + modes->blueBits + modes->alphaBits;
108
109 modes->accumRedBits = 16 * j;
110 modes->accumGreenBits = 16 * j;
111 modes->accumBlueBits = 16 * j;
112 modes->accumAlphaBits = 0;
113 modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
114 modes->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
115 modes->stencilBits = stencil_bits;
116 modes->depthBits = depth_bits;
117
118 modes->visualType = visType;
119 modes->renderType = GLX_RGBA_BIT;
120 modes->rgbMode = GL_TRUE;
121
122 if ( db_modes[i] == GLX_NONE ) {
123
124 modes->doubleBufferMode = GL_FALSE;
125 }
126 else {
127 modes->doubleBufferMode = GL_TRUE;
128 modes->swapMethod = db_modes[i];
129 }
130
131 modes = modes->next;
132 }
133 }
134
135 return modes;
136 }
137 #endif /* USE_NEW_INTERFACE */
138
139
140 #ifdef USE_NEW_INTERFACE
141 static __GLcontextModes *
142 mach64FillInModes( unsigned pixel_bits, unsigned depth_bits,
143 unsigned stencil_bits, GLboolean have_back_buffer )
144 {
145 __GLcontextModes * modes;
146 __GLcontextModes * m;
147 unsigned num_modes;
148 unsigned depth_buffer_factor;
149 unsigned back_buffer_factor;
150 unsigned i;
151
152 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
153 * enough to add support. Basically, if a context is created with an
154 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
155 * will never be used.
156 */
157 static const GLenum back_buffer_modes[] = {
158 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
159 };
160
161 int depth_buffer_modes[2][2];
162
163
164 depth_buffer_modes[0][0] = depth_bits;
165 depth_buffer_modes[1][0] = depth_bits;
166
167 /* Just like with the accumulation buffer, always provide some modes
168 * with a stencil buffer. It will be a sw fallback, but some apps won't
169 * care about that.
170 */
171 depth_buffer_modes[0][1] = 0;
172 depth_buffer_modes[1][1] = (stencil_bits == 0) ? 8 : stencil_bits;
173
174 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
175 back_buffer_factor = (have_back_buffer) ? 2 : 1;
176
177 num_modes = depth_buffer_factor * back_buffer_factor * 4;
178
179 modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
180 m = modes;
181 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
182 m = fill_in_modes( m, pixel_bits,
183 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
184 back_buffer_modes, back_buffer_factor,
185 GLX_TRUE_COLOR );
186 }
187
188 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
189 m = fill_in_modes( m, pixel_bits,
190 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
191 back_buffer_modes, back_buffer_factor,
192 GLX_DIRECT_COLOR );
193 }
194
195 /* Mark the visual as slow if there are "fake" stencil bits.
196 */
197 for ( m = modes ; m != NULL ; m = m->next ) {
198 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ){
199 m->visualRating = GLX_SLOW_CONFIG;
200 }
201 }
202
203 return modes;
204 }
205 #endif /* USE_NEW_INTERFACE */
206
207
208 /* Create the device specific screen private data struct.
209 */
210 static mach64ScreenRec *
211 mach64CreateScreen( __DRIscreenPrivate *sPriv )
212 {
213 mach64ScreenPtr mach64Screen;
214 ATIDRIPtr serverInfo = (ATIDRIPtr)sPriv->pDevPriv;
215
216 if ( MACH64_DEBUG & DEBUG_VERBOSE_DRI )
217 fprintf( stderr, "%s\n", __FUNCTION__ );
218
219 if ( ! driCheckDriDdxDrmVersions( sPriv, "Mach64", 4, 0, 6, 4, 1, 0 ) )
220 return NULL;
221
222 /* Allocate the private area */
223 mach64Screen = (mach64ScreenPtr) CALLOC( sizeof(*mach64Screen) );
224 if ( !mach64Screen ) return NULL;
225
226 /* parse information in __driConfigOptions */
227 driParseOptionInfo (&mach64Screen->optionCache,
228 __driConfigOptions, __driNConfigOptions);
229
230 mach64Screen->IsPCI = serverInfo->IsPCI;
231
232 {
233 drm_mach64_getparam_t gp;
234 int ret;
235
236 gp.param = MACH64_PARAM_IRQ_NR;
237 gp.value = (void *) &mach64Screen->irq;
238
239 ret = drmCommandWriteRead( sPriv->fd, DRM_MACH64_GETPARAM,
240 &gp, sizeof(gp));
241 if (ret) {
242 fprintf(stderr, "DRM_MACH64_GETPARAM (MACH64_PARAM_IRQ_NR): %d\n", ret);
243 FREE( mach64Screen );
244 return NULL;
245 }
246 }
247
248 mach64Screen->mmio.handle = serverInfo->regs;
249 mach64Screen->mmio.size = serverInfo->regsSize;
250 if ( drmMap( sPriv->fd,
251 mach64Screen->mmio.handle,
252 mach64Screen->mmio.size,
253 (drmAddressPtr)&mach64Screen->mmio.map ) != 0 ) {
254 FREE( mach64Screen );
255 return NULL;
256 }
257
258 mach64Screen->buffers = drmMapBufs( sPriv->fd );
259 if ( !mach64Screen->buffers ) {
260 drmUnmap( (drmAddress)mach64Screen->mmio.map,
261 mach64Screen->mmio.size );
262 FREE( mach64Screen );
263 return NULL;
264 }
265
266 if ( !mach64Screen->IsPCI ) {
267 mach64Screen->agpTextures.handle = serverInfo->agp;
268 mach64Screen->agpTextures.size = serverInfo->agpSize;
269 if ( drmMap( sPriv->fd,
270 mach64Screen->agpTextures.handle,
271 mach64Screen->agpTextures.size,
272 (drmAddressPtr)&mach64Screen->agpTextures.map ) ) {
273 drmUnmapBufs( mach64Screen->buffers );
274 drmUnmap( (drmAddress)mach64Screen->mmio.map, mach64Screen->mmio.size );
275 FREE( mach64Screen );
276 return NULL;
277 }
278 }
279
280 mach64Screen->AGPMode = serverInfo->AGPMode;
281
282 mach64Screen->chipset = serverInfo->chipset;
283 mach64Screen->width = serverInfo->width;
284 mach64Screen->height = serverInfo->height;
285 mach64Screen->mem = serverInfo->mem;
286 mach64Screen->cpp = serverInfo->cpp;
287
288 mach64Screen->frontOffset = serverInfo->frontOffset;
289 mach64Screen->frontPitch = serverInfo->frontPitch;
290 mach64Screen->backOffset = serverInfo->backOffset;
291 mach64Screen->backPitch = serverInfo->backPitch;
292 mach64Screen->depthOffset = serverInfo->depthOffset;
293 mach64Screen->depthPitch = serverInfo->depthPitch;
294
295 mach64Screen->texOffset[MACH64_CARD_HEAP] = serverInfo->textureOffset;
296 mach64Screen->texSize[MACH64_CARD_HEAP] = serverInfo->textureSize;
297 mach64Screen->logTexGranularity[MACH64_CARD_HEAP] =
298 serverInfo->logTextureGranularity;
299
300 if ( mach64Screen->IsPCI ) {
301 mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS - 1;
302 mach64Screen->firstTexHeap = MACH64_CARD_HEAP;
303 mach64Screen->texOffset[MACH64_AGP_HEAP] = 0;
304 mach64Screen->texSize[MACH64_AGP_HEAP] = 0;
305 mach64Screen->logTexGranularity[MACH64_AGP_HEAP] = 0;
306 } else {
307 if (mach64Screen->texSize[MACH64_CARD_HEAP] > 0) {
308 mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS;
309 mach64Screen->firstTexHeap = MACH64_CARD_HEAP;
310 } else {
311 mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS - 1;
312 mach64Screen->firstTexHeap = MACH64_AGP_HEAP;
313 }
314 mach64Screen->texOffset[MACH64_AGP_HEAP] = serverInfo->agpTextureOffset;
315 mach64Screen->texSize[MACH64_AGP_HEAP] = serverInfo->agpSize;
316 mach64Screen->logTexGranularity[MACH64_AGP_HEAP] = serverInfo->logAgpTextureGranularity;
317 }
318
319 mach64Screen->driScreen = sPriv;
320 #ifndef _SOLO
321 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
322 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
323 (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
324 void * const psc = sPriv->psc->screenConfigs;
325
326 if ( glx_enable_extension != NULL ) {
327 if ( mach64Screen->irq != 0 ) {
328 (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
329 (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
330 (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
331 }
332
333 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
334 }
335 }
336 #endif
337 return mach64Screen;
338 }
339
340 /* Destroy the device specific screen private data struct.
341 */
342 static void
343 mach64DestroyScreen( __DRIscreenPrivate *driScreen )
344 {
345 mach64ScreenRec *mach64Screen = (mach64ScreenRec *) driScreen->private;
346
347 if ( !mach64Screen )
348 return;
349
350 if ( MACH64_DEBUG & DEBUG_VERBOSE_DRI )
351 fprintf( stderr, "%s\n", __FUNCTION__ );
352
353 if ( !mach64Screen->IsPCI ) {
354 drmUnmap( (drmAddress)mach64Screen->agpTextures.map,
355 mach64Screen->agpTextures.size );
356 }
357
358 drmUnmapBufs( mach64Screen->buffers );
359 drmUnmap( (drmAddress)mach64Screen->mmio.map, mach64Screen->mmio.size );
360
361 FREE( mach64Screen );
362 driScreen->private = NULL;
363 }
364
365 /* Initialize the fullscreen mode.
366 */
367 static GLboolean
368 mach64OpenFullScreen( __DRIcontextPrivate *driContextPriv )
369 {
370 return GL_TRUE;
371 }
372
373 /* Shut down the fullscreen mode.
374 */
375 static GLboolean
376 mach64CloseFullScreen( __DRIcontextPrivate *driContextPriv )
377 {
378 return GL_TRUE;
379 }
380
381
382 /* Create and initialize the Mesa and driver specific pixmap buffer
383 * data.
384 */
385 static GLboolean
386 mach64CreateBuffer( __DRIscreenPrivate *driScrnPriv,
387 __DRIdrawablePrivate *driDrawPriv,
388 const __GLcontextModes *mesaVis,
389 GLboolean isPixmap )
390 {
391 if (isPixmap) {
392 return GL_FALSE; /* not implemented */
393 }
394 else {
395 driDrawPriv->driverPrivate = (void *)
396 _mesa_create_framebuffer( mesaVis,
397 GL_FALSE, /* software depth buffer? */
398 mesaVis->stencilBits > 0,
399 mesaVis->accumRedBits > 0,
400 mesaVis->alphaBits > 0 );
401 return (driDrawPriv->driverPrivate != NULL);
402 }
403 }
404
405
406 static void
407 mach64DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
408 {
409 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
410 }
411
412
413 /* Copy the back color buffer to the front color buffer */
414 static void
415 mach64SwapBuffers(__DRIdrawablePrivate *dPriv)
416 {
417 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
418 mach64ContextPtr mmesa;
419 GLcontext *ctx;
420 mmesa = (mach64ContextPtr) dPriv->driContextPriv->driverPrivate;
421 ctx = mmesa->glCtx;
422 if (ctx->Visual.doubleBufferMode) {
423 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
424 mach64CopyBuffer( dPriv );
425 }
426 }
427 else {
428 /* XXX this shouldn't be an error but we can't handle it for now */
429 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
430 }
431 }
432
433
434 /* Initialize the driver specific screen private data.
435 */
436 static GLboolean
437 mach64InitDriver( __DRIscreenPrivate *driScreen )
438 {
439 driScreen->private = (void *) mach64CreateScreen( driScreen );
440
441 if ( !driScreen->private ) {
442 mach64DestroyScreen( driScreen );
443 return GL_FALSE;
444 }
445
446 return GL_TRUE;
447 }
448
449 #ifndef _SOLO
450 /* This function is called by libGL.so as soon as libGL.so is loaded.
451 * This is where we register new extension functions with the dispatcher.
452 */
453 void __driRegisterExtensions( void )
454 {
455 #if 0
456 /* KW: This is handled differently in the other drivers, not sure
457 * what to do here.
458 */
459 PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
460
461 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
462 glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
463 glXGetProcAddress( (const GLubyte *) "__glXEnableExtension" );
464
465 if ( glx_enable_extension != NULL ) {
466 glx_enable_extension( "GLX_SGI_swap_control", GL_FALSE );
467 glx_enable_extension( "GLX_SGI_video_sync", GL_FALSE );
468 glx_enable_extension( "GLX_MESA_swap_control", GL_FALSE );
469 }
470 }
471 #endif
472 }
473 #endif
474
475 static struct __DriverAPIRec mach64API = {
476 .InitDriver = mach64InitDriver,
477 .DestroyScreen = mach64DestroyScreen,
478 .CreateContext = mach64CreateContext,
479 .DestroyContext = mach64DestroyContext,
480 .CreateBuffer = mach64CreateBuffer,
481 .DestroyBuffer = mach64DestroyBuffer,
482 .SwapBuffers = mach64SwapBuffers,
483 .MakeCurrent = mach64MakeCurrent,
484 .UnbindContext = mach64UnbindContext,
485 .OpenFullScreen = mach64OpenFullScreen,
486 .CloseFullScreen = mach64CloseFullScreen,
487 .GetSwapInfo = NULL,
488 .GetMSC = driGetMSC32,
489 .WaitForMSC = driWaitForMSC32,
490 .WaitForSBC = NULL,
491 .SwapBuffersMSC = NULL
492 };
493
494
495 /*
496 * This is the bootstrap function for the driver.
497 * The __driCreateScreen name is the symbol that libGL.so fetches.
498 * Return: pointer to a __DRIscreenPrivate.
499 */
500 #ifndef _SOLO
501 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
502 int numConfigs, __GLXvisualConfig *config)
503 {
504 __DRIscreenPrivate *psp;
505 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &mach64API);
506 return (void *) psp;
507 }
508 #else
509 void *__driCreateScreen(struct DRIDriverRec *driver,
510 struct DRIDriverContextRec *driverContext)
511 {
512 __DRIscreenPrivate *psp;
513 psp = __driUtilCreateScreen(driver, driverContext, &mach64API);
514 return (void *) psp;
515 }
516 #endif
517
518 /**
519 * This is the bootstrap function for the driver. libGL supplies all of the
520 * requisite information about the system, and the driver initializes itself.
521 * This routine also fills in the linked list pointed to by \c driver_modes
522 * with the \c __GLcontextModes that the driver can support for windows or
523 * pbuffers.
524 *
525 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
526 * failure.
527 */
528 #ifdef USE_NEW_INTERFACE
529 void * __driCreateNewScreen( Display *dpy, int scrn, __DRIscreen *psc,
530 const __GLcontextModes * modes,
531 const __DRIversion * ddx_version,
532 const __DRIversion * dri_version,
533 const __DRIversion * drm_version,
534 const __DRIframebuffer * frame_buffer,
535 drmAddress pSAREA, int fd,
536 int internal_api_version,
537 __GLcontextModes ** driver_modes )
538
539 {
540 __DRIscreenPrivate *psp;
541
542 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
543 ddx_version, dri_version, drm_version,
544 frame_buffer, pSAREA, fd,
545 internal_api_version, &mach64API);
546 if ( psp != NULL ) {
547 create_context_modes = (PFNGLXCREATECONTEXTMODES)
548 glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
549 if ( create_context_modes != NULL ) {
550 ATIDRIPtr dri_priv = (ATIDRIPtr) psp->pDevPriv;
551 *driver_modes = mach64FillInModes( dri_priv->cpp * 8,
552 16,
553 0,
554 1);
555 }
556 }
557
558 return (void *) psp;
559 }
560 #endif /* USE_NEW_INTERFACE */