1 /**************************************************************************
3 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Gareth Hughes <gareth@valinux.com>
31 * Kevin E. Martin <martin@valinux.com>
37 #include "r128_context.h"
38 #include "r128_ioctl.h"
39 #include "r128_span.h"
40 #include "r128_tris.h"
44 #include "framebuffer.h"
45 #include "renderbuffer.h"
50 #include "GL/internal/dri_interface.h"
56 PUBLIC
const char __driConfigOptions
[] =
58 DRI_CONF_SECTION_PERFORMANCE
59 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
61 DRI_CONF_SECTION_QUALITY
62 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB
)
64 DRI_CONF_SECTION_DEBUG
65 DRI_CONF_NO_RAST(false)
67 DRI_CONF_PERFORMANCE_BOXES(false)
72 static const GLuint __driNConfigOptions
= 4;
74 static const GLuint __driNConfigOptions
= 3;
77 extern const struct dri_extension card_extensions
[];
80 /* Including xf86PciInfo.h introduces a bunch of errors...
82 #define PCI_CHIP_RAGE128LE 0x4C45
83 #define PCI_CHIP_RAGE128LF 0x4C46
84 #define PCI_CHIP_RAGE128PF 0x5046
85 #define PCI_CHIP_RAGE128PR 0x5052
86 #define PCI_CHIP_RAGE128RE 0x5245
87 #define PCI_CHIP_RAGE128RF 0x5246
88 #define PCI_CHIP_RAGE128RK 0x524B
89 #define PCI_CHIP_RAGE128RL 0x524C
93 /* Create the device specific screen private data struct.
96 r128CreateScreen( __DRIscreenPrivate
*sPriv
)
98 r128ScreenPtr r128Screen
;
99 R128DRIPtr r128DRIPriv
= (R128DRIPtr
)sPriv
->pDevPriv
;
100 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
101 (PFNGLXSCRENABLEEXTENSIONPROC
) (*dri_interface
->getProcAddress("glxEnableExtension"));
102 void * const psc
= sPriv
->psc
->screenConfigs
;
104 if (sPriv
->devPrivSize
!= sizeof(R128DRIRec
)) {
105 fprintf(stderr
,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
109 /* Allocate the private area */
110 r128Screen
= (r128ScreenPtr
) CALLOC( sizeof(*r128Screen
) );
111 if ( !r128Screen
) return NULL
;
113 /* parse information in __driConfigOptions */
114 driParseOptionInfo (&r128Screen
->optionCache
,
115 __driConfigOptions
, __driNConfigOptions
);
117 /* This is first since which regions we map depends on whether or
118 * not we are using a PCI card.
120 r128Screen
->IsPCI
= r128DRIPriv
->IsPCI
;
121 r128Screen
->sarea_priv_offset
= r128DRIPriv
->sarea_priv_offset
;
123 if (sPriv
->drmMinor
>= 3) {
124 drm_r128_getparam_t gp
;
127 gp
.param
= R128_PARAM_IRQ_NR
;
128 gp
.value
= &r128Screen
->irq
;
130 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_R128_GETPARAM
,
133 fprintf(stderr
, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret
);
139 r128Screen
->mmio
.handle
= r128DRIPriv
->registerHandle
;
140 r128Screen
->mmio
.size
= r128DRIPriv
->registerSize
;
141 if ( drmMap( sPriv
->fd
,
142 r128Screen
->mmio
.handle
,
143 r128Screen
->mmio
.size
,
144 (drmAddressPtr
)&r128Screen
->mmio
.map
) ) {
149 r128Screen
->buffers
= drmMapBufs( sPriv
->fd
);
150 if ( !r128Screen
->buffers
) {
151 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
156 if ( !r128Screen
->IsPCI
) {
157 r128Screen
->agpTextures
.handle
= r128DRIPriv
->agpTexHandle
;
158 r128Screen
->agpTextures
.size
= r128DRIPriv
->agpTexMapSize
;
159 if ( drmMap( sPriv
->fd
,
160 r128Screen
->agpTextures
.handle
,
161 r128Screen
->agpTextures
.size
,
162 (drmAddressPtr
)&r128Screen
->agpTextures
.map
) ) {
163 drmUnmapBufs( r128Screen
->buffers
);
164 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
170 switch ( r128DRIPriv
->deviceID
) {
171 case PCI_CHIP_RAGE128RE
:
172 case PCI_CHIP_RAGE128RF
:
173 case PCI_CHIP_RAGE128RK
:
174 case PCI_CHIP_RAGE128RL
:
175 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
177 case PCI_CHIP_RAGE128PF
:
178 r128Screen
->chipset
= R128_CARD_TYPE_R128_PRO
;
180 case PCI_CHIP_RAGE128LE
:
181 case PCI_CHIP_RAGE128LF
:
182 r128Screen
->chipset
= R128_CARD_TYPE_R128_MOBILITY
;
185 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
189 r128Screen
->cpp
= r128DRIPriv
->bpp
/ 8;
190 r128Screen
->AGPMode
= r128DRIPriv
->AGPMode
;
192 r128Screen
->frontOffset
= r128DRIPriv
->frontOffset
;
193 r128Screen
->frontPitch
= r128DRIPriv
->frontPitch
;
194 r128Screen
->backOffset
= r128DRIPriv
->backOffset
;
195 r128Screen
->backPitch
= r128DRIPriv
->backPitch
;
196 r128Screen
->depthOffset
= r128DRIPriv
->depthOffset
;
197 r128Screen
->depthPitch
= r128DRIPriv
->depthPitch
;
198 r128Screen
->spanOffset
= r128DRIPriv
->spanOffset
;
200 if ( r128DRIPriv
->textureSize
== 0 ) {
201 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] =
202 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
203 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
204 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] =
205 r128DRIPriv
->log2AGPTexGran
;
207 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureOffset
;
208 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureSize
;
209 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->log2TexGran
;
212 if ( !r128Screen
->agpTextures
.map
|| r128DRIPriv
->textureSize
== 0 ) {
213 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
- 1;
214 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] = 0;
215 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = 0;
216 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] = 0;
218 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
;
219 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] =
220 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
221 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
222 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] =
223 r128DRIPriv
->log2AGPTexGran
;
226 r128Screen
->driScreen
= sPriv
;
228 if ( glx_enable_extension
!= NULL
) {
229 if ( r128Screen
->irq
!= 0 ) {
230 (*glx_enable_extension
)( psc
, "GLX_SGI_swap_control" );
231 (*glx_enable_extension
)( psc
, "GLX_SGI_video_sync" );
232 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_control" );
235 (*glx_enable_extension
)( psc
, "GLX_MESA_swap_frame_usage" );
241 /* Destroy the device specific screen private data struct.
244 r128DestroyScreen( __DRIscreenPrivate
*sPriv
)
246 r128ScreenPtr r128Screen
= (r128ScreenPtr
)sPriv
->private;
251 if ( !r128Screen
->IsPCI
) {
252 drmUnmap( (drmAddress
)r128Screen
->agpTextures
.map
,
253 r128Screen
->agpTextures
.size
);
255 drmUnmapBufs( r128Screen
->buffers
);
256 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
258 /* free all option information */
259 driDestroyOptionInfo (&r128Screen
->optionCache
);
262 sPriv
->private = NULL
;
266 /* Create and initialize the Mesa and driver specific pixmap buffer
270 r128CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
271 __DRIdrawablePrivate
*driDrawPriv
,
272 const __GLcontextModes
*mesaVis
,
275 r128ScreenPtr screen
= (r128ScreenPtr
) driScrnPriv
->private;
278 return GL_FALSE
; /* not implemented */
281 const GLboolean swDepth
= GL_FALSE
;
282 const GLboolean swAlpha
= GL_FALSE
;
283 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
284 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 &&
285 mesaVis
->depthBits
!= 24;
286 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
289 driRenderbuffer
*frontRb
290 = driNewRenderbuffer(GL_RGBA
,
293 screen
->frontOffset
, screen
->frontPitch
,
295 r128SetSpanFunctions(frontRb
, mesaVis
);
296 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
299 if (mesaVis
->doubleBufferMode
) {
300 driRenderbuffer
*backRb
301 = driNewRenderbuffer(GL_RGBA
,
304 screen
->backOffset
, screen
->backPitch
,
306 r128SetSpanFunctions(backRb
, mesaVis
);
307 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
310 if (mesaVis
->depthBits
== 16) {
311 driRenderbuffer
*depthRb
312 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
315 screen
->depthOffset
, screen
->depthPitch
,
317 r128SetSpanFunctions(depthRb
, mesaVis
);
318 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
320 else if (mesaVis
->depthBits
== 24) {
321 driRenderbuffer
*depthRb
322 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
325 screen
->depthOffset
, screen
->depthPitch
,
327 r128SetSpanFunctions(depthRb
, mesaVis
);
328 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
331 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
332 driRenderbuffer
*stencilRb
333 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
,
336 screen
->depthOffset
, screen
->depthPitch
,
338 r128SetSpanFunctions(stencilRb
, mesaVis
);
339 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
342 _mesa_add_soft_renderbuffers(fb
,
343 GL_FALSE
, /* color */
349 driDrawPriv
->driverPrivate
= (void *) fb
;
351 return (driDrawPriv
->driverPrivate
!= NULL
);
357 r128DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
359 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
363 /* Copy the back color buffer to the front color buffer */
365 r128SwapBuffers(__DRIdrawablePrivate
*dPriv
)
367 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
368 r128ContextPtr rmesa
;
370 rmesa
= (r128ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
372 if (ctx
->Visual
.doubleBufferMode
) {
373 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
374 if ( rmesa
->doPageFlip
) {
375 r128PageFlip( dPriv
);
378 r128CopyBuffer( dPriv
);
383 /* XXX this shouldn't be an error but we can't handle it for now */
384 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
389 /* Initialize the driver specific screen private data.
392 r128InitDriver( __DRIscreenPrivate
*sPriv
)
394 sPriv
->private = (void *) r128CreateScreen( sPriv
);
396 if ( !sPriv
->private ) {
397 r128DestroyScreen( sPriv
);
405 static struct __DriverAPIRec r128API
= {
406 .InitDriver
= r128InitDriver
,
407 .DestroyScreen
= r128DestroyScreen
,
408 .CreateContext
= r128CreateContext
,
409 .DestroyContext
= r128DestroyContext
,
410 .CreateBuffer
= r128CreateBuffer
,
411 .DestroyBuffer
= r128DestroyBuffer
,
412 .SwapBuffers
= r128SwapBuffers
,
413 .MakeCurrent
= r128MakeCurrent
,
414 .UnbindContext
= r128UnbindContext
,
416 .GetMSC
= driGetMSC32
,
417 .WaitForMSC
= driWaitForMSC32
,
419 .SwapBuffersMSC
= NULL
424 static __GLcontextModes
*
425 r128FillInModes( unsigned pixel_bits
, unsigned depth_bits
,
426 unsigned stencil_bits
, GLboolean have_back_buffer
)
428 __GLcontextModes
* modes
;
429 __GLcontextModes
* m
;
431 unsigned depth_buffer_factor
;
432 unsigned back_buffer_factor
;
436 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
437 * enough to add support. Basically, if a context is created with an
438 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
439 * will never be used.
441 static const GLenum back_buffer_modes
[] = {
442 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
445 uint8_t depth_bits_array
[2];
446 uint8_t stencil_bits_array
[2];
449 depth_bits_array
[0] = depth_bits
;
450 depth_bits_array
[1] = depth_bits
;
452 /* Just like with the accumulation buffer, always provide some modes
453 * with a stencil buffer. It will be a sw fallback, but some apps won't
456 stencil_bits_array
[0] = 0;
457 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
459 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
460 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
462 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
464 if ( pixel_bits
== 16 ) {
466 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
470 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
473 modes
= (*dri_interface
->createContextModes
)( num_modes
, sizeof( __GLcontextModes
) );
475 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
476 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
477 back_buffer_modes
, back_buffer_factor
,
479 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
480 __func__
, __LINE__
);
484 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
485 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
486 back_buffer_modes
, back_buffer_factor
,
487 GLX_DIRECT_COLOR
) ) {
488 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
489 __func__
, __LINE__
);
493 /* Mark the visual as slow if there are "fake" stencil bits.
495 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
496 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
497 m
->visualRating
= GLX_SLOW_CONFIG
;
506 * This is the bootstrap function for the driver. libGL supplies all of the
507 * requisite information about the system, and the driver initializes itself.
508 * This routine also fills in the linked list pointed to by \c driver_modes
509 * with the \c __GLcontextModes that the driver can support for windows or
512 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
516 void * __driCreateNewScreen_20050727( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
517 const __GLcontextModes
* modes
,
518 const __DRIversion
* ddx_version
,
519 const __DRIversion
* dri_version
,
520 const __DRIversion
* drm_version
,
521 const __DRIframebuffer
* frame_buffer
,
522 drmAddress pSAREA
, int fd
,
523 int internal_api_version
,
524 const __DRIinterfaceMethods
* interface
,
525 __GLcontextModes
** driver_modes
)
528 __DRIscreenPrivate
*psp
;
529 static const __DRIversion ddx_expected
= { 4, 0, 0 };
530 static const __DRIversion dri_expected
= { 4, 0, 0 };
531 static const __DRIversion drm_expected
= { 2, 2, 0 };
534 dri_interface
= interface
;
536 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
537 dri_version
, & dri_expected
,
538 ddx_version
, & ddx_expected
,
539 drm_version
, & drm_expected
) ) {
543 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
544 ddx_version
, dri_version
, drm_version
,
545 frame_buffer
, pSAREA
, fd
,
546 internal_api_version
, &r128API
);
548 R128DRIPtr dri_priv
= (R128DRIPtr
) psp
->pDevPriv
;
549 *driver_modes
= r128FillInModes( dri_priv
->bpp
,
550 (dri_priv
->bpp
== 16) ? 16 : 24,
551 (dri_priv
->bpp
== 16) ? 0 : 8,
552 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
554 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
555 * enable the extensions. It just makes sure that all the dispatch offsets for all
556 * the extensions that *might* be enables are known. This is needed because the
557 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
558 * enable the extensions until we have a context pointer.
560 * Hello chicken. Hello egg. How are you two today?
562 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);