1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_screen.c,v 1.9 2003/03/26 20:43:49 tsi Exp $ */
2 /**************************************************************************
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
31 * Gareth Hughes <gareth@valinux.com>
32 * Kevin E. Martin <martin@valinux.com>
38 #include "r128_context.h"
39 #include "r128_ioctl.h"
40 #include "r128_tris.h"
48 #include "GL/internal/dri_interface.h"
54 const char __driConfigOptions
[] =
56 DRI_CONF_SECTION_PERFORMANCE
57 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
59 DRI_CONF_SECTION_QUALITY
60 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB
)
62 DRI_CONF_SECTION_DEBUG
63 DRI_CONF_NO_RAST(false)
65 DRI_CONF_PERFORMANCE_BOXES(false)
70 static const GLuint __driNConfigOptions
= 4;
72 static const GLuint __driNConfigOptions
= 3;
76 /* Including xf86PciInfo.h introduces a bunch of errors...
78 #define PCI_CHIP_RAGE128LE 0x4C45
79 #define PCI_CHIP_RAGE128LF 0x4C46
80 #define PCI_CHIP_RAGE128PF 0x5046
81 #define PCI_CHIP_RAGE128PR 0x5052
82 #define PCI_CHIP_RAGE128RE 0x5245
83 #define PCI_CHIP_RAGE128RF 0x5246
84 #define PCI_CHIP_RAGE128RK 0x524B
85 #define PCI_CHIP_RAGE128RL 0x524C
88 #ifdef USE_NEW_INTERFACE
89 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
90 #endif /* USE_NEW_INTERFACE */
92 /* Create the device specific screen private data struct.
95 r128CreateScreen( __DRIscreenPrivate
*sPriv
)
97 r128ScreenPtr r128Screen
;
98 R128DRIPtr r128DRIPriv
= (R128DRIPtr
)sPriv
->pDevPriv
;
101 /* Allocate the private area */
102 r128Screen
= (r128ScreenPtr
) CALLOC( sizeof(*r128Screen
) );
103 if ( !r128Screen
) return NULL
;
105 /* parse information in __driConfigOptions */
106 driParseOptionInfo (&r128Screen
->optionCache
,
107 __driConfigOptions
, __driNConfigOptions
);
109 /* This is first since which regions we map depends on whether or
110 * not we are using a PCI card.
112 r128Screen
->IsPCI
= r128DRIPriv
->IsPCI
;
113 r128Screen
->sarea_priv_offset
= r128DRIPriv
->sarea_priv_offset
;
115 if (sPriv
->drmMinor
>= 3) {
116 drm_r128_getparam_t gp
;
119 gp
.param
= R128_PARAM_IRQ_NR
;
120 gp
.value
= &r128Screen
->irq
;
122 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_R128_GETPARAM
,
125 fprintf(stderr
, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret
);
131 r128Screen
->mmio
.handle
= r128DRIPriv
->registerHandle
;
132 r128Screen
->mmio
.size
= r128DRIPriv
->registerSize
;
133 if ( drmMap( sPriv
->fd
,
134 r128Screen
->mmio
.handle
,
135 r128Screen
->mmio
.size
,
136 (drmAddressPtr
)&r128Screen
->mmio
.map
) ) {
141 r128Screen
->buffers
= drmMapBufs( sPriv
->fd
);
142 if ( !r128Screen
->buffers
) {
143 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
148 if ( !r128Screen
->IsPCI
) {
149 r128Screen
->agpTextures
.handle
= r128DRIPriv
->agpTexHandle
;
150 r128Screen
->agpTextures
.size
= r128DRIPriv
->agpTexMapSize
;
151 if ( drmMap( sPriv
->fd
,
152 r128Screen
->agpTextures
.handle
,
153 r128Screen
->agpTextures
.size
,
154 (drmAddressPtr
)&r128Screen
->agpTextures
.map
) ) {
155 drmUnmapBufs( r128Screen
->buffers
);
156 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
162 switch ( r128DRIPriv
->deviceID
) {
163 case PCI_CHIP_RAGE128RE
:
164 case PCI_CHIP_RAGE128RF
:
165 case PCI_CHIP_RAGE128RK
:
166 case PCI_CHIP_RAGE128RL
:
167 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
169 case PCI_CHIP_RAGE128PF
:
170 r128Screen
->chipset
= R128_CARD_TYPE_R128_PRO
;
172 case PCI_CHIP_RAGE128LE
:
173 case PCI_CHIP_RAGE128LF
:
174 r128Screen
->chipset
= R128_CARD_TYPE_R128_MOBILITY
;
177 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
181 r128Screen
->cpp
= r128DRIPriv
->bpp
/ 8;
182 r128Screen
->AGPMode
= r128DRIPriv
->AGPMode
;
184 r128Screen
->frontOffset
= r128DRIPriv
->frontOffset
;
185 r128Screen
->frontPitch
= r128DRIPriv
->frontPitch
;
186 r128Screen
->backOffset
= r128DRIPriv
->backOffset
;
187 r128Screen
->backPitch
= r128DRIPriv
->backPitch
;
188 r128Screen
->depthOffset
= r128DRIPriv
->depthOffset
;
189 r128Screen
->depthPitch
= r128DRIPriv
->depthPitch
;
190 r128Screen
->spanOffset
= r128DRIPriv
->spanOffset
;
192 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureOffset
;
193 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureSize
;
194 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->log2TexGran
;
196 if ( r128Screen
->IsPCI
) {
197 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
- 1;
198 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] = 0;
199 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = 0;
200 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] = 0;
202 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
;
203 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] =
204 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
205 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
206 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] =
207 r128DRIPriv
->log2AGPTexGran
;
210 r128Screen
->driScreen
= sPriv
;
211 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
212 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
213 (PFNGLXSCRENABLEEXTENSIONPROC
) glXGetProcAddress( (const GLubyte
*) "__glXScrEnableExtension" );
214 void * const psc
= sPriv
->psc
->screenConfigs
;
216 if ( glx_enable_extension
!= NULL
) {
217 if ( r128Screen
->irq
!= 0 ) {
218 (*glx_enable_extension
)( psc
, "GLX_SGI_swap_control" );
219 (*glx_enable_extension
)( psc
, "GLX_SGI_video_sync" );
220 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_control" );
223 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_frame_usage" );
229 /* Destroy the device specific screen private data struct.
232 r128DestroyScreen( __DRIscreenPrivate
*sPriv
)
234 r128ScreenPtr r128Screen
= (r128ScreenPtr
)sPriv
->private;
239 if ( !r128Screen
->IsPCI
) {
240 drmUnmap( (drmAddress
)r128Screen
->agpTextures
.map
,
241 r128Screen
->agpTextures
.size
);
243 drmUnmapBufs( r128Screen
->buffers
);
244 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
246 /* free all option information */
247 driDestroyOptionInfo (&r128Screen
->optionCache
);
250 sPriv
->private = NULL
;
254 /* Create and initialize the Mesa and driver specific pixmap buffer
258 r128CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
259 __DRIdrawablePrivate
*driDrawPriv
,
260 const __GLcontextModes
*mesaVis
,
264 return GL_FALSE
; /* not implemented */
267 driDrawPriv
->driverPrivate
= (void *)
268 _mesa_create_framebuffer( mesaVis
,
269 GL_FALSE
, /* software depth buffer? */
270 mesaVis
->stencilBits
> 0,
271 mesaVis
->accumRedBits
> 0,
272 mesaVis
->alphaBits
> 0 );
273 return (driDrawPriv
->driverPrivate
!= NULL
);
279 r128DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
281 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
285 /* Copy the back color buffer to the front color buffer */
287 r128SwapBuffers(__DRIdrawablePrivate
*dPriv
)
289 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
290 r128ContextPtr rmesa
;
292 rmesa
= (r128ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
294 if (ctx
->Visual
.doubleBufferMode
) {
295 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
296 if ( rmesa
->doPageFlip
) {
297 r128PageFlip( dPriv
);
300 r128CopyBuffer( dPriv
);
305 /* XXX this shouldn't be an error but we can't handle it for now */
306 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
311 /* Initialize the driver specific screen private data.
314 r128InitDriver( __DRIscreenPrivate
*sPriv
)
316 sPriv
->private = (void *) r128CreateScreen( sPriv
);
318 if ( !sPriv
->private ) {
319 r128DestroyScreen( sPriv
);
327 static struct __DriverAPIRec r128API
= {
328 .InitDriver
= r128InitDriver
,
329 .DestroyScreen
= r128DestroyScreen
,
330 .CreateContext
= r128CreateContext
,
331 .DestroyContext
= r128DestroyContext
,
332 .CreateBuffer
= r128CreateBuffer
,
333 .DestroyBuffer
= r128DestroyBuffer
,
334 .SwapBuffers
= r128SwapBuffers
,
335 .MakeCurrent
= r128MakeCurrent
,
336 .UnbindContext
= r128UnbindContext
,
338 .GetMSC
= driGetMSC32
,
339 .WaitForMSC
= driWaitForMSC32
,
341 .SwapBuffersMSC
= NULL
346 #ifndef DRI_NEW_INTERFACE_ONLY
348 * This is the bootstrap function for the driver.
349 * The __driCreateScreen name is the symbol that libGL.so fetches.
350 * Return: pointer to a __DRIscreenPrivate.
352 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
353 int numConfigs
, __GLXvisualConfig
*config
)
355 __DRIscreenPrivate
*psp
;
356 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &r128API
);
359 #endif /* DRI_NEW_INTERFACE_ONLY */
362 #ifdef USE_NEW_INTERFACE
363 static __GLcontextModes
*
364 r128FillInModes( unsigned pixel_bits
, unsigned depth_bits
,
365 unsigned stencil_bits
, GLboolean have_back_buffer
)
367 __GLcontextModes
* modes
;
368 __GLcontextModes
* m
;
370 unsigned depth_buffer_factor
;
371 unsigned back_buffer_factor
;
375 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
376 * enough to add support. Basically, if a context is created with an
377 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
378 * will never be used.
380 static const GLenum back_buffer_modes
[] = {
381 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
384 uint8_t depth_bits_array
[2];
385 uint8_t stencil_bits_array
[2];
388 depth_bits_array
[0] = depth_bits
;
389 depth_bits_array
[1] = depth_bits
;
391 /* Just like with the accumulation buffer, always provide some modes
392 * with a stencil buffer. It will be a sw fallback, but some apps won't
395 stencil_bits_array
[0] = 0;
396 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
398 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
399 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
401 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
403 if ( pixel_bits
== 16 ) {
405 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
409 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
412 modes
= (*create_context_modes
)( num_modes
, sizeof( __GLcontextModes
) );
414 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
415 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
416 back_buffer_modes
, back_buffer_factor
,
418 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
419 __func__
, __LINE__
);
423 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
424 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
425 back_buffer_modes
, back_buffer_factor
,
426 GLX_DIRECT_COLOR
) ) {
427 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
428 __func__
, __LINE__
);
432 /* Mark the visual as slow if there are "fake" stencil bits.
434 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
435 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
436 m
->visualRating
= GLX_SLOW_CONFIG
;
445 * This is the bootstrap function for the driver. libGL supplies all of the
446 * requisite information about the system, and the driver initializes itself.
447 * This routine also fills in the linked list pointed to by \c driver_modes
448 * with the \c __GLcontextModes that the driver can support for windows or
451 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
454 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
455 const __GLcontextModes
* modes
,
456 const __DRIversion
* ddx_version
,
457 const __DRIversion
* dri_version
,
458 const __DRIversion
* drm_version
,
459 const __DRIframebuffer
* frame_buffer
,
460 drmAddress pSAREA
, int fd
,
461 int internal_api_version
,
462 __GLcontextModes
** driver_modes
)
465 __DRIscreenPrivate
*psp
;
466 static const __DRIversion ddx_expected
= { 4, 0, 0 };
467 static const __DRIversion dri_expected
= { 4, 0, 0 };
468 static const __DRIversion drm_expected
= { 2, 2, 0 };
471 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
472 dri_version
, & dri_expected
,
473 ddx_version
, & ddx_expected
,
474 drm_version
, & drm_expected
) ) {
478 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
479 ddx_version
, dri_version
, drm_version
,
480 frame_buffer
, pSAREA
, fd
,
481 internal_api_version
, &r128API
);
483 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
484 glXGetProcAddress( (const GLubyte
*) "__glXCreateContextModes" );
485 if ( create_context_modes
!= NULL
) {
486 R128DRIPtr dri_priv
= (R128DRIPtr
) psp
->pDevPriv
;
487 *driver_modes
= r128FillInModes( dri_priv
->bpp
,
488 (dri_priv
->bpp
== 16) ? 16 : 24,
489 (dri_priv
->bpp
== 16) ? 0 : 8,
490 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
496 #endif /* USE_NEW_INTERFACE */