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"
43 #include "main/context.h"
44 #include "main/imports.h"
45 #include "main/framebuffer.h"
46 #include "main/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
;
103 if (sPriv
->devPrivSize
!= sizeof(R128DRIRec
)) {
104 fprintf(stderr
,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
108 /* Allocate the private area */
109 r128Screen
= (r128ScreenPtr
) CALLOC( sizeof(*r128Screen
) );
110 if ( !r128Screen
) return NULL
;
112 /* parse information in __driConfigOptions */
113 driParseOptionInfo (&r128Screen
->optionCache
,
114 __driConfigOptions
, __driNConfigOptions
);
116 /* This is first since which regions we map depends on whether or
117 * not we are using a PCI card.
119 r128Screen
->IsPCI
= r128DRIPriv
->IsPCI
;
120 r128Screen
->sarea_priv_offset
= r128DRIPriv
->sarea_priv_offset
;
122 if (sPriv
->drm_version
.minor
>= 3) {
123 drm_r128_getparam_t gp
;
126 gp
.param
= R128_PARAM_IRQ_NR
;
127 gp
.value
= &r128Screen
->irq
;
129 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_R128_GETPARAM
,
132 fprintf(stderr
, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret
);
138 r128Screen
->mmio
.handle
= r128DRIPriv
->registerHandle
;
139 r128Screen
->mmio
.size
= r128DRIPriv
->registerSize
;
140 if ( drmMap( sPriv
->fd
,
141 r128Screen
->mmio
.handle
,
142 r128Screen
->mmio
.size
,
143 (drmAddressPtr
)&r128Screen
->mmio
.map
) ) {
148 r128Screen
->buffers
= drmMapBufs( sPriv
->fd
);
149 if ( !r128Screen
->buffers
) {
150 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
155 if ( !r128Screen
->IsPCI
) {
156 r128Screen
->agpTextures
.handle
= r128DRIPriv
->agpTexHandle
;
157 r128Screen
->agpTextures
.size
= r128DRIPriv
->agpTexMapSize
;
158 if ( drmMap( sPriv
->fd
,
159 r128Screen
->agpTextures
.handle
,
160 r128Screen
->agpTextures
.size
,
161 (drmAddressPtr
)&r128Screen
->agpTextures
.map
) ) {
162 drmUnmapBufs( r128Screen
->buffers
);
163 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
169 switch ( r128DRIPriv
->deviceID
) {
170 case PCI_CHIP_RAGE128RE
:
171 case PCI_CHIP_RAGE128RF
:
172 case PCI_CHIP_RAGE128RK
:
173 case PCI_CHIP_RAGE128RL
:
174 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
176 case PCI_CHIP_RAGE128PF
:
177 r128Screen
->chipset
= R128_CARD_TYPE_R128_PRO
;
179 case PCI_CHIP_RAGE128LE
:
180 case PCI_CHIP_RAGE128LF
:
181 r128Screen
->chipset
= R128_CARD_TYPE_R128_MOBILITY
;
184 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
188 r128Screen
->cpp
= r128DRIPriv
->bpp
/ 8;
189 r128Screen
->AGPMode
= r128DRIPriv
->AGPMode
;
191 r128Screen
->frontOffset
= r128DRIPriv
->frontOffset
;
192 r128Screen
->frontPitch
= r128DRIPriv
->frontPitch
;
193 r128Screen
->backOffset
= r128DRIPriv
->backOffset
;
194 r128Screen
->backPitch
= r128DRIPriv
->backPitch
;
195 r128Screen
->depthOffset
= r128DRIPriv
->depthOffset
;
196 r128Screen
->depthPitch
= r128DRIPriv
->depthPitch
;
197 r128Screen
->spanOffset
= r128DRIPriv
->spanOffset
;
199 if ( r128DRIPriv
->textureSize
== 0 ) {
200 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] =
201 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
202 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
203 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] =
204 r128DRIPriv
->log2AGPTexGran
;
206 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureOffset
;
207 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureSize
;
208 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->log2TexGran
;
211 if ( !r128Screen
->agpTextures
.map
|| r128DRIPriv
->textureSize
== 0 ) {
212 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
- 1;
213 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] = 0;
214 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = 0;
215 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] = 0;
217 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
;
218 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] =
219 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
220 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
221 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] =
222 r128DRIPriv
->log2AGPTexGran
;
225 r128Screen
->driScreen
= sPriv
;
228 r128Screen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
229 if ( r128Screen
->irq
!= 0 ) {
230 r128Screen
->extensions
[i
++] = &driSwapControlExtension
.base
;
231 r128Screen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
233 r128Screen
->extensions
[i
++] = NULL
;
234 sPriv
->extensions
= r128Screen
->extensions
;
239 /* Destroy the device specific screen private data struct.
242 r128DestroyScreen( __DRIscreenPrivate
*sPriv
)
244 r128ScreenPtr r128Screen
= (r128ScreenPtr
)sPriv
->private;
249 if ( !r128Screen
->IsPCI
) {
250 drmUnmap( (drmAddress
)r128Screen
->agpTextures
.map
,
251 r128Screen
->agpTextures
.size
);
253 drmUnmapBufs( r128Screen
->buffers
);
254 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
256 /* free all option information */
257 driDestroyOptionInfo (&r128Screen
->optionCache
);
260 sPriv
->private = NULL
;
264 /* Create and initialize the Mesa and driver specific pixmap buffer
268 r128CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
269 __DRIdrawablePrivate
*driDrawPriv
,
270 const __GLcontextModes
*mesaVis
,
273 r128ScreenPtr screen
= (r128ScreenPtr
) driScrnPriv
->private;
276 return GL_FALSE
; /* not implemented */
279 const GLboolean swDepth
= GL_FALSE
;
280 const GLboolean swAlpha
= GL_FALSE
;
281 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
282 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 &&
283 mesaVis
->depthBits
!= 24;
284 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
287 driRenderbuffer
*frontRb
288 = driNewRenderbuffer(GL_RGBA
,
291 screen
->frontOffset
, screen
->frontPitch
,
293 r128SetSpanFunctions(frontRb
, mesaVis
);
294 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
297 if (mesaVis
->doubleBufferMode
) {
298 driRenderbuffer
*backRb
299 = driNewRenderbuffer(GL_RGBA
,
302 screen
->backOffset
, screen
->backPitch
,
304 r128SetSpanFunctions(backRb
, mesaVis
);
305 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
308 if (mesaVis
->depthBits
== 16) {
309 driRenderbuffer
*depthRb
310 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
313 screen
->depthOffset
, screen
->depthPitch
,
315 r128SetSpanFunctions(depthRb
, mesaVis
);
316 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
318 else if (mesaVis
->depthBits
== 24) {
319 driRenderbuffer
*depthRb
320 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
323 screen
->depthOffset
, screen
->depthPitch
,
325 r128SetSpanFunctions(depthRb
, mesaVis
);
326 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
329 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
330 driRenderbuffer
*stencilRb
331 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
,
334 screen
->depthOffset
, screen
->depthPitch
,
336 r128SetSpanFunctions(stencilRb
, mesaVis
);
337 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
340 _mesa_add_soft_renderbuffers(fb
,
341 GL_FALSE
, /* color */
347 driDrawPriv
->driverPrivate
= (void *) fb
;
349 return (driDrawPriv
->driverPrivate
!= NULL
);
355 r128DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
357 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
361 /* Copy the back color buffer to the front color buffer */
363 r128SwapBuffers(__DRIdrawablePrivate
*dPriv
)
365 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
366 r128ContextPtr rmesa
;
368 rmesa
= (r128ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
370 if (ctx
->Visual
.doubleBufferMode
) {
371 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
372 if ( rmesa
->doPageFlip
) {
373 r128PageFlip( dPriv
);
376 r128CopyBuffer( dPriv
);
381 /* XXX this shouldn't be an error but we can't handle it for now */
382 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
387 /* Initialize the driver specific screen private data.
390 r128InitDriver( __DRIscreenPrivate
*sPriv
)
392 sPriv
->private = (void *) r128CreateScreen( sPriv
);
394 if ( !sPriv
->private ) {
395 r128DestroyScreen( sPriv
);
402 static const __DRIconfig
**
403 r128FillInModes( __DRIscreenPrivate
*psp
,
404 unsigned pixel_bits
, unsigned depth_bits
,
405 unsigned stencil_bits
, GLboolean have_back_buffer
)
407 __DRIconfig
**configs
;
408 __GLcontextModes
* m
;
409 unsigned depth_buffer_factor
;
410 unsigned back_buffer_factor
;
415 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
416 * enough to add support. Basically, if a context is created with an
417 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
418 * will never be used.
420 static const GLenum back_buffer_modes
[] = {
421 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
424 u_int8_t depth_bits_array
[2];
425 u_int8_t stencil_bits_array
[2];
428 depth_bits_array
[0] = depth_bits
;
429 depth_bits_array
[1] = depth_bits
;
431 /* Just like with the accumulation buffer, always provide some modes
432 * with a stencil buffer. It will be a sw fallback, but some apps won't
435 stencil_bits_array
[0] = 0;
436 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
438 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
439 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
441 if ( pixel_bits
== 16 ) {
443 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
447 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
450 configs
= driCreateConfigs(fb_format
, fb_type
,
451 depth_bits_array
, stencil_bits_array
,
452 depth_buffer_factor
, back_buffer_modes
,
454 if (configs
== NULL
) {
455 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
,
460 /* Mark the visual as slow if there are "fake" stencil bits.
462 for (i
= 0; configs
[i
]; i
++) {
463 m
= &configs
[i
]->modes
;
464 if ((m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
)) {
465 m
->visualRating
= GLX_SLOW_CONFIG
;
469 return (const __DRIconfig
**) configs
;
474 * This is the driver specific part of the createNewScreen entry point.
476 * \todo maybe fold this into intelInitDriver
478 * \return the __GLcontextModes supported by this driver
480 static const __DRIconfig
**
481 r128InitScreen(__DRIscreenPrivate
*psp
)
483 static const __DRIversion ddx_expected
= { 4, 0, 0 };
484 static const __DRIversion dri_expected
= { 4, 0, 0 };
485 static const __DRIversion drm_expected
= { 2, 2, 0 };
486 R128DRIPtr dri_priv
= (R128DRIPtr
) psp
->pDevPriv
;
488 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
489 &psp
->dri_version
, & dri_expected
,
490 &psp
->ddx_version
, & ddx_expected
,
491 &psp
->drm_version
, & drm_expected
) )
494 /* Calling driInitExtensions here, with a NULL context pointer,
495 * does not actually enable the extensions. It just makes sure
496 * that all the dispatch offsets for all the extensions that
497 * *might* be enables are known. This is needed because the
498 * dispatch offsets need to be known when _mesa_context_create is
499 * called, but we can't enable the extensions until we have a
502 * Hello chicken. Hello egg. How are you two today?
504 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
506 if (!r128InitDriver(psp
))
509 return r128FillInModes( psp
,
511 (dri_priv
->bpp
== 16) ? 16 : 24,
512 (dri_priv
->bpp
== 16) ? 0 : 8,
513 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
516 const struct __DriverAPIRec driDriverAPI
= {
517 .InitScreen
= r128InitScreen
,
518 .DestroyScreen
= r128DestroyScreen
,
519 .CreateContext
= r128CreateContext
,
520 .DestroyContext
= r128DestroyContext
,
521 .CreateBuffer
= r128CreateBuffer
,
522 .DestroyBuffer
= r128DestroyBuffer
,
523 .SwapBuffers
= r128SwapBuffers
,
524 .MakeCurrent
= r128MakeCurrent
,
525 .UnbindContext
= r128UnbindContext
,
527 .GetDrawableMSC
= driDrawableGetMSC32
,
528 .WaitForMSC
= driWaitForMSC32
,
530 .SwapBuffersMSC
= NULL