1 /* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
3 * Copyright 2000 Gareth Hughes
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:
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
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.
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * José Fonseca <j_r_fonseca@yahoo.co.uk>
32 #include "mach64_context.h"
33 #include "mach64_ioctl.h"
34 #include "mach64_tris.h"
35 #include "mach64_vb.h"
44 #include "GL/internal/dri_interface.h"
47 /* Mach64 configuration
51 const char __driConfigOptions
[] =
53 DRI_CONF_SECTION_PERFORMANCE
54 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
57 DRI_CONF_SECTION_DEBUG
58 DRI_CONF_PERFORMANCE_BOXES(false)
63 static const GLuint __driNConfigOptions
= 2;
65 static const GLuint __driNConfigOptions
= 1;
68 #ifdef USE_NEW_INTERFACE
69 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
70 #endif /* USE_NEW_INTERFACE */
72 #ifdef USE_NEW_INTERFACE
73 static __GLcontextModes
* fill_in_modes( __GLcontextModes
* modes
,
76 unsigned stencil_bits
,
77 const GLenum
* db_modes
,
78 unsigned num_db_modes
,
81 static const uint8_t bits
[2][4] = {
86 static const uint32_t masks
[2][4] = {
87 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
88 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }
93 const unsigned index
= ((pixel_bits
+ 15) / 16) - 1;
95 for ( i
= 0 ; i
< num_db_modes
; i
++ ) {
96 for ( j
= 0 ; j
< 2 ; j
++ ) {
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
;
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
;
118 modes
->visualType
= visType
;
119 modes
->renderType
= GLX_RGBA_BIT
;
120 modes
->rgbMode
= GL_TRUE
;
122 if ( db_modes
[i
] == GLX_NONE
) {
124 modes
->doubleBufferMode
= GL_FALSE
;
127 modes
->doubleBufferMode
= GL_TRUE
;
128 modes
->swapMethod
= db_modes
[i
];
137 #endif /* USE_NEW_INTERFACE */
140 #ifdef USE_NEW_INTERFACE
141 static __GLcontextModes
*
142 mach64FillInModes( unsigned pixel_bits
, unsigned depth_bits
,
143 unsigned stencil_bits
, GLboolean have_back_buffer
)
145 __GLcontextModes
* modes
;
146 __GLcontextModes
* m
;
148 unsigned depth_buffer_factor
;
149 unsigned back_buffer_factor
;
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.
157 static const GLenum back_buffer_modes
[] = {
158 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
161 int depth_buffer_modes
[2][2];
164 depth_buffer_modes
[0][0] = depth_bits
;
165 depth_buffer_modes
[1][0] = depth_bits
;
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
171 depth_buffer_modes
[0][1] = 0;
172 depth_buffer_modes
[1][1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
174 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
175 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
177 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
179 modes
= (*create_context_modes
)( num_modes
, sizeof( __GLcontextModes
) );
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
,
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
,
195 /* Mark the visual as slow if there are "fake" stencil bits.
197 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
198 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ){
199 m
->visualRating
= GLX_SLOW_CONFIG
;
205 #endif /* USE_NEW_INTERFACE */
208 /* Create the device specific screen private data struct.
210 static mach64ScreenRec
*
211 mach64CreateScreen( __DRIscreenPrivate
*sPriv
)
213 mach64ScreenPtr mach64Screen
;
214 ATIDRIPtr serverInfo
= (ATIDRIPtr
)sPriv
->pDevPriv
;
216 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
217 fprintf( stderr
, "%s\n", __FUNCTION__
);
219 if ( ! driCheckDriDdxDrmVersions( sPriv
, "Mach64", 4, 0, 6, 4, 1, 0 ) )
222 /* Allocate the private area */
223 mach64Screen
= (mach64ScreenPtr
) CALLOC( sizeof(*mach64Screen
) );
224 if ( !mach64Screen
) return NULL
;
226 /* parse information in __driConfigOptions */
227 driParseOptionInfo (&mach64Screen
->optionCache
,
228 __driConfigOptions
, __driNConfigOptions
);
230 mach64Screen
->IsPCI
= serverInfo
->IsPCI
;
233 drm_mach64_getparam_t gp
;
236 gp
.param
= MACH64_PARAM_IRQ_NR
;
237 gp
.value
= (void *) &mach64Screen
->irq
;
239 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_MACH64_GETPARAM
,
242 fprintf(stderr
, "DRM_MACH64_GETPARAM (MACH64_PARAM_IRQ_NR): %d\n", ret
);
243 FREE( mach64Screen
);
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
);
258 mach64Screen
->buffers
= drmMapBufs( sPriv
->fd
);
259 if ( !mach64Screen
->buffers
) {
260 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
,
261 mach64Screen
->mmio
.size
);
262 FREE( mach64Screen
);
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
);
280 mach64Screen
->AGPMode
= serverInfo
->AGPMode
;
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
;
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
;
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
;
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;
307 if (mach64Screen
->texSize
[MACH64_CARD_HEAP
] > 0) {
308 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
;
309 mach64Screen
->firstTexHeap
= MACH64_CARD_HEAP
;
311 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
- 1;
312 mach64Screen
->firstTexHeap
= MACH64_AGP_HEAP
;
314 mach64Screen
->texOffset
[MACH64_AGP_HEAP
] = serverInfo
->agpTextureOffset
;
315 mach64Screen
->texSize
[MACH64_AGP_HEAP
] = serverInfo
->agpSize
;
316 mach64Screen
->logTexGranularity
[MACH64_AGP_HEAP
] = serverInfo
->logAgpTextureGranularity
;
319 mach64Screen
->driScreen
= sPriv
;
321 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
322 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
323 (PFNGLXSCRENABLEEXTENSIONPROC
) glXGetProcAddress( (const GLubyte
*) "__glXScrEnableExtension" );
324 void * const psc
= sPriv
->psc
->screenConfigs
;
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" );
333 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_frame_usage" );
340 /* Destroy the device specific screen private data struct.
343 mach64DestroyScreen( __DRIscreenPrivate
*driScreen
)
345 mach64ScreenRec
*mach64Screen
= (mach64ScreenRec
*) driScreen
->private;
350 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
351 fprintf( stderr
, "%s\n", __FUNCTION__
);
353 if ( !mach64Screen
->IsPCI
) {
354 drmUnmap( (drmAddress
)mach64Screen
->agpTextures
.map
,
355 mach64Screen
->agpTextures
.size
);
358 drmUnmapBufs( mach64Screen
->buffers
);
359 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
, mach64Screen
->mmio
.size
);
361 FREE( mach64Screen
);
362 driScreen
->private = NULL
;
365 /* Initialize the fullscreen mode.
368 mach64OpenFullScreen( __DRIcontextPrivate
*driContextPriv
)
373 /* Shut down the fullscreen mode.
376 mach64CloseFullScreen( __DRIcontextPrivate
*driContextPriv
)
382 /* Create and initialize the Mesa and driver specific pixmap buffer
386 mach64CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
387 __DRIdrawablePrivate
*driDrawPriv
,
388 const __GLcontextModes
*mesaVis
,
392 return GL_FALSE
; /* not implemented */
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
);
407 mach64DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
409 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
413 /* Copy the back color buffer to the front color buffer */
415 mach64SwapBuffers(__DRIdrawablePrivate
*dPriv
)
417 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
418 mach64ContextPtr mmesa
;
420 mmesa
= (mach64ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
422 if (ctx
->Visual
.doubleBufferMode
) {
423 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
424 mach64CopyBuffer( dPriv
);
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__
);
434 /* Initialize the driver specific screen private data.
437 mach64InitDriver( __DRIscreenPrivate
*driScreen
)
439 driScreen
->private = (void *) mach64CreateScreen( driScreen
);
441 if ( !driScreen
->private ) {
442 mach64DestroyScreen( driScreen
);
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.
453 void __driRegisterExtensions( void )
456 /* KW: This is handled differently in the other drivers, not sure
459 PFNGLXENABLEEXTENSIONPROC glx_enable_extension
;
461 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
462 glx_enable_extension
= (PFNGLXENABLEEXTENSIONPROC
)
463 glXGetProcAddress( (const GLubyte
*) "__glXEnableExtension" );
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
);
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
,
488 .GetMSC
= driGetMSC32
,
489 .WaitForMSC
= driWaitForMSC32
,
491 .SwapBuffersMSC
= NULL
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.
501 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
502 int numConfigs
, __GLXvisualConfig
*config
)
504 __DRIscreenPrivate
*psp
;
505 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &mach64API
);
509 void *__driCreateScreen(struct DRIDriverRec
*driver
,
510 struct DRIDriverContextRec
*driverContext
)
512 __DRIscreenPrivate
*psp
;
513 psp
= __driUtilCreateScreen(driver
, driverContext
, &mach64API
);
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
525 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
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
)
540 __DRIscreenPrivate
*psp
;
542 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
543 ddx_version
, dri_version
, drm_version
,
544 frame_buffer
, pSAREA
, fd
,
545 internal_api_version
, &mach64API
);
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,
560 #endif /* USE_NEW_INTERFACE */