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_span.h"
41 #include "r128_tris.h"
45 #include "framebuffer.h"
46 #include "renderbuffer.h"
51 #include "GL/internal/dri_interface.h"
57 PUBLIC
const char __driConfigOptions
[] =
59 DRI_CONF_SECTION_PERFORMANCE
60 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
62 DRI_CONF_SECTION_QUALITY
63 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB
)
65 DRI_CONF_SECTION_DEBUG
66 DRI_CONF_NO_RAST(false)
68 DRI_CONF_PERFORMANCE_BOXES(false)
73 static const GLuint __driNConfigOptions
= 4;
75 static const GLuint __driNConfigOptions
= 3;
78 extern const struct dri_extension card_extensions
[];
81 /* Including xf86PciInfo.h introduces a bunch of errors...
83 #define PCI_CHIP_RAGE128LE 0x4C45
84 #define PCI_CHIP_RAGE128LF 0x4C46
85 #define PCI_CHIP_RAGE128PF 0x5046
86 #define PCI_CHIP_RAGE128PR 0x5052
87 #define PCI_CHIP_RAGE128RE 0x5245
88 #define PCI_CHIP_RAGE128RF 0x5246
89 #define PCI_CHIP_RAGE128RK 0x524B
90 #define PCI_CHIP_RAGE128RL 0x524C
94 /* Create the device specific screen private data struct.
97 r128CreateScreen( __DRIscreenPrivate
*sPriv
)
99 r128ScreenPtr r128Screen
;
100 R128DRIPtr r128DRIPriv
= (R128DRIPtr
)sPriv
->pDevPriv
;
101 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
102 (PFNGLXSCRENABLEEXTENSIONPROC
) (*dri_interface
->getProcAddress("glxEnableExtension"));
105 if (sPriv
->devPrivSize
!= sizeof(R128DRIRec
)) {
106 fprintf(stderr
,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
110 /* Allocate the private area */
111 r128Screen
= (r128ScreenPtr
) CALLOC( sizeof(*r128Screen
) );
112 if ( !r128Screen
) return NULL
;
114 /* parse information in __driConfigOptions */
115 driParseOptionInfo (&r128Screen
->optionCache
,
116 __driConfigOptions
, __driNConfigOptions
);
118 /* This is first since which regions we map depends on whether or
119 * not we are using a PCI card.
121 r128Screen
->IsPCI
= r128DRIPriv
->IsPCI
;
122 r128Screen
->sarea_priv_offset
= r128DRIPriv
->sarea_priv_offset
;
124 if (sPriv
->drm_version
.minor
>= 3) {
125 drm_r128_getparam_t gp
;
128 gp
.param
= R128_PARAM_IRQ_NR
;
129 gp
.value
= &r128Screen
->irq
;
131 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_R128_GETPARAM
,
134 fprintf(stderr
, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret
);
140 r128Screen
->mmio
.handle
= r128DRIPriv
->registerHandle
;
141 r128Screen
->mmio
.size
= r128DRIPriv
->registerSize
;
142 if ( drmMap( sPriv
->fd
,
143 r128Screen
->mmio
.handle
,
144 r128Screen
->mmio
.size
,
145 (drmAddressPtr
)&r128Screen
->mmio
.map
) ) {
150 r128Screen
->buffers
= drmMapBufs( sPriv
->fd
);
151 if ( !r128Screen
->buffers
) {
152 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
157 if ( !r128Screen
->IsPCI
) {
158 r128Screen
->agpTextures
.handle
= r128DRIPriv
->agpTexHandle
;
159 r128Screen
->agpTextures
.size
= r128DRIPriv
->agpTexMapSize
;
160 if ( drmMap( sPriv
->fd
,
161 r128Screen
->agpTextures
.handle
,
162 r128Screen
->agpTextures
.size
,
163 (drmAddressPtr
)&r128Screen
->agpTextures
.map
) ) {
164 drmUnmapBufs( r128Screen
->buffers
);
165 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
171 switch ( r128DRIPriv
->deviceID
) {
172 case PCI_CHIP_RAGE128RE
:
173 case PCI_CHIP_RAGE128RF
:
174 case PCI_CHIP_RAGE128RK
:
175 case PCI_CHIP_RAGE128RL
:
176 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
178 case PCI_CHIP_RAGE128PF
:
179 r128Screen
->chipset
= R128_CARD_TYPE_R128_PRO
;
181 case PCI_CHIP_RAGE128LE
:
182 case PCI_CHIP_RAGE128LF
:
183 r128Screen
->chipset
= R128_CARD_TYPE_R128_MOBILITY
;
186 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
190 r128Screen
->cpp
= r128DRIPriv
->bpp
/ 8;
191 r128Screen
->AGPMode
= r128DRIPriv
->AGPMode
;
193 r128Screen
->frontOffset
= r128DRIPriv
->frontOffset
;
194 r128Screen
->frontPitch
= r128DRIPriv
->frontPitch
;
195 r128Screen
->backOffset
= r128DRIPriv
->backOffset
;
196 r128Screen
->backPitch
= r128DRIPriv
->backPitch
;
197 r128Screen
->depthOffset
= r128DRIPriv
->depthOffset
;
198 r128Screen
->depthPitch
= r128DRIPriv
->depthPitch
;
199 r128Screen
->spanOffset
= r128DRIPriv
->spanOffset
;
201 if ( r128DRIPriv
->textureSize
== 0 ) {
202 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] =
203 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
204 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
205 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] =
206 r128DRIPriv
->log2AGPTexGran
;
208 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureOffset
;
209 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureSize
;
210 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->log2TexGran
;
213 if ( !r128Screen
->agpTextures
.map
|| r128DRIPriv
->textureSize
== 0 ) {
214 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
- 1;
215 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] = 0;
216 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = 0;
217 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] = 0;
219 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
;
220 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] =
221 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
222 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
223 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] =
224 r128DRIPriv
->log2AGPTexGran
;
227 r128Screen
->driScreen
= sPriv
;
230 r128Screen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
231 if ( glx_enable_extension
!= NULL
) {
232 if ( r128Screen
->irq
!= 0 ) {
233 r128Screen
->extensions
[i
++] = &driSwapControlExtension
.base
;
234 (*glx_enable_extension
)( sPriv
->psc
, "GLX_SGI_video_sync" );
237 r128Screen
->extensions
[i
++] = NULL
;
238 sPriv
->extensions
= r128Screen
->extensions
;
243 /* Destroy the device specific screen private data struct.
246 r128DestroyScreen( __DRIscreenPrivate
*sPriv
)
248 r128ScreenPtr r128Screen
= (r128ScreenPtr
)sPriv
->private;
253 if ( !r128Screen
->IsPCI
) {
254 drmUnmap( (drmAddress
)r128Screen
->agpTextures
.map
,
255 r128Screen
->agpTextures
.size
);
257 drmUnmapBufs( r128Screen
->buffers
);
258 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
260 /* free all option information */
261 driDestroyOptionInfo (&r128Screen
->optionCache
);
264 sPriv
->private = NULL
;
268 /* Create and initialize the Mesa and driver specific pixmap buffer
272 r128CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
273 __DRIdrawablePrivate
*driDrawPriv
,
274 const __GLcontextModes
*mesaVis
,
277 r128ScreenPtr screen
= (r128ScreenPtr
) driScrnPriv
->private;
280 return GL_FALSE
; /* not implemented */
283 const GLboolean swDepth
= GL_FALSE
;
284 const GLboolean swAlpha
= GL_FALSE
;
285 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
286 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 &&
287 mesaVis
->depthBits
!= 24;
288 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
291 driRenderbuffer
*frontRb
292 = driNewRenderbuffer(GL_RGBA
,
295 screen
->frontOffset
, screen
->frontPitch
,
297 r128SetSpanFunctions(frontRb
, mesaVis
);
298 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
301 if (mesaVis
->doubleBufferMode
) {
302 driRenderbuffer
*backRb
303 = driNewRenderbuffer(GL_RGBA
,
306 screen
->backOffset
, screen
->backPitch
,
308 r128SetSpanFunctions(backRb
, mesaVis
);
309 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
312 if (mesaVis
->depthBits
== 16) {
313 driRenderbuffer
*depthRb
314 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
317 screen
->depthOffset
, screen
->depthPitch
,
319 r128SetSpanFunctions(depthRb
, mesaVis
);
320 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
322 else if (mesaVis
->depthBits
== 24) {
323 driRenderbuffer
*depthRb
324 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
327 screen
->depthOffset
, screen
->depthPitch
,
329 r128SetSpanFunctions(depthRb
, mesaVis
);
330 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
333 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
334 driRenderbuffer
*stencilRb
335 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
,
338 screen
->depthOffset
, screen
->depthPitch
,
340 r128SetSpanFunctions(stencilRb
, mesaVis
);
341 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
344 _mesa_add_soft_renderbuffers(fb
,
345 GL_FALSE
, /* color */
351 driDrawPriv
->driverPrivate
= (void *) fb
;
353 return (driDrawPriv
->driverPrivate
!= NULL
);
359 r128DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
361 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
365 /* Copy the back color buffer to the front color buffer */
367 r128SwapBuffers(__DRIdrawablePrivate
*dPriv
)
369 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
370 r128ContextPtr rmesa
;
372 rmesa
= (r128ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
374 if (ctx
->Visual
.doubleBufferMode
) {
375 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
376 if ( rmesa
->doPageFlip
) {
377 r128PageFlip( dPriv
);
380 r128CopyBuffer( dPriv
);
385 /* XXX this shouldn't be an error but we can't handle it for now */
386 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
391 /* Initialize the driver specific screen private data.
394 r128InitDriver( __DRIscreenPrivate
*sPriv
)
396 sPriv
->private = (void *) r128CreateScreen( sPriv
);
398 if ( !sPriv
->private ) {
399 r128DestroyScreen( sPriv
);
407 static struct __DriverAPIRec r128API
= {
408 .DestroyScreen
= r128DestroyScreen
,
409 .CreateContext
= r128CreateContext
,
410 .DestroyContext
= r128DestroyContext
,
411 .CreateBuffer
= r128CreateBuffer
,
412 .DestroyBuffer
= r128DestroyBuffer
,
413 .SwapBuffers
= r128SwapBuffers
,
414 .MakeCurrent
= r128MakeCurrent
,
415 .UnbindContext
= r128UnbindContext
,
417 .GetMSC
= driGetMSC32
,
418 .WaitForMSC
= driWaitForMSC32
,
420 .SwapBuffersMSC
= NULL
425 static __GLcontextModes
*
426 r128FillInModes( unsigned pixel_bits
, unsigned depth_bits
,
427 unsigned stencil_bits
, GLboolean have_back_buffer
)
429 __GLcontextModes
* modes
;
430 __GLcontextModes
* m
;
432 unsigned depth_buffer_factor
;
433 unsigned back_buffer_factor
;
437 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
438 * enough to add support. Basically, if a context is created with an
439 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
440 * will never be used.
442 static const GLenum back_buffer_modes
[] = {
443 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
446 u_int8_t depth_bits_array
[2];
447 u_int8_t stencil_bits_array
[2];
450 depth_bits_array
[0] = depth_bits
;
451 depth_bits_array
[1] = depth_bits
;
453 /* Just like with the accumulation buffer, always provide some modes
454 * with a stencil buffer. It will be a sw fallback, but some apps won't
457 stencil_bits_array
[0] = 0;
458 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
460 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
461 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
463 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
465 if ( pixel_bits
== 16 ) {
467 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
471 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
474 modes
= (*dri_interface
->createContextModes
)( num_modes
, sizeof( __GLcontextModes
) );
476 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
477 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
478 back_buffer_modes
, back_buffer_factor
,
480 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
481 __func__
, __LINE__
);
485 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
486 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
487 back_buffer_modes
, back_buffer_factor
,
488 GLX_DIRECT_COLOR
) ) {
489 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
490 __func__
, __LINE__
);
494 /* Mark the visual as slow if there are "fake" stencil bits.
496 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
497 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
498 m
->visualRating
= GLX_SLOW_CONFIG
;
507 * This is the driver specific part of the createNewScreen entry point.
509 * \todo maybe fold this into intelInitDriver
511 * \return the __GLcontextModes supported by this driver
513 __GLcontextModes
*__driDriverInitScreen(__DRIscreenPrivate
*psp
)
515 static const __DRIversion ddx_expected
= { 4, 0, 0 };
516 static const __DRIversion dri_expected
= { 4, 0, 0 };
517 static const __DRIversion drm_expected
= { 2, 2, 0 };
518 R128DRIPtr dri_priv
= (R128DRIPtr
) psp
->pDevPriv
;
520 psp
->DriverAPI
= r128API
;
521 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
522 &psp
->dri_version
, & dri_expected
,
523 &psp
->ddx_version
, & ddx_expected
,
524 &psp
->drm_version
, & drm_expected
) )
527 /* Calling driInitExtensions here, with a NULL context pointer,
528 * does not actually enable the extensions. It just makes sure
529 * that all the dispatch offsets for all the extensions that
530 * *might* be enables are known. This is needed because the
531 * dispatch offsets need to be known when _mesa_context_create is
532 * called, but we can't enable the extensions until we have a
535 * Hello chicken. Hello egg. How are you two today?
537 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
539 if (!r128InitDriver(psp
))
542 return r128FillInModes( dri_priv
->bpp
,
543 (dri_priv
->bpp
== 16) ? 16 : 24,
544 (dri_priv
->bpp
== 16) ? 0 : 8,
545 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );