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"
42 #include "main/context.h"
43 #include "main/imports.h"
44 #include "main/framebuffer.h"
45 #include "main/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
;
102 if (sPriv
->devPrivSize
!= sizeof(R128DRIRec
)) {
103 fprintf(stderr
,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
107 /* Allocate the private area */
108 r128Screen
= (r128ScreenPtr
) CALLOC( sizeof(*r128Screen
) );
109 if ( !r128Screen
) return NULL
;
111 /* parse information in __driConfigOptions */
112 driParseOptionInfo (&r128Screen
->optionCache
,
113 __driConfigOptions
, __driNConfigOptions
);
115 /* This is first since which regions we map depends on whether or
116 * not we are using a PCI card.
118 r128Screen
->IsPCI
= r128DRIPriv
->IsPCI
;
119 r128Screen
->sarea_priv_offset
= r128DRIPriv
->sarea_priv_offset
;
121 if (sPriv
->drm_version
.minor
>= 3) {
122 drm_r128_getparam_t gp
;
125 gp
.param
= R128_PARAM_IRQ_NR
;
126 gp
.value
= &r128Screen
->irq
;
128 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_R128_GETPARAM
,
131 fprintf(stderr
, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret
);
137 r128Screen
->mmio
.handle
= r128DRIPriv
->registerHandle
;
138 r128Screen
->mmio
.size
= r128DRIPriv
->registerSize
;
139 if ( drmMap( sPriv
->fd
,
140 r128Screen
->mmio
.handle
,
141 r128Screen
->mmio
.size
,
142 (drmAddressPtr
)&r128Screen
->mmio
.map
) ) {
147 r128Screen
->buffers
= drmMapBufs( sPriv
->fd
);
148 if ( !r128Screen
->buffers
) {
149 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
154 if ( !r128Screen
->IsPCI
) {
155 r128Screen
->agpTextures
.handle
= r128DRIPriv
->agpTexHandle
;
156 r128Screen
->agpTextures
.size
= r128DRIPriv
->agpTexMapSize
;
157 if ( drmMap( sPriv
->fd
,
158 r128Screen
->agpTextures
.handle
,
159 r128Screen
->agpTextures
.size
,
160 (drmAddressPtr
)&r128Screen
->agpTextures
.map
) ) {
161 drmUnmapBufs( r128Screen
->buffers
);
162 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
168 switch ( r128DRIPriv
->deviceID
) {
169 case PCI_CHIP_RAGE128RE
:
170 case PCI_CHIP_RAGE128RF
:
171 case PCI_CHIP_RAGE128RK
:
172 case PCI_CHIP_RAGE128RL
:
173 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
175 case PCI_CHIP_RAGE128PF
:
176 r128Screen
->chipset
= R128_CARD_TYPE_R128_PRO
;
178 case PCI_CHIP_RAGE128LE
:
179 case PCI_CHIP_RAGE128LF
:
180 r128Screen
->chipset
= R128_CARD_TYPE_R128_MOBILITY
;
183 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
187 r128Screen
->cpp
= r128DRIPriv
->bpp
/ 8;
188 r128Screen
->AGPMode
= r128DRIPriv
->AGPMode
;
190 r128Screen
->frontOffset
= r128DRIPriv
->frontOffset
;
191 r128Screen
->frontPitch
= r128DRIPriv
->frontPitch
;
192 r128Screen
->backOffset
= r128DRIPriv
->backOffset
;
193 r128Screen
->backPitch
= r128DRIPriv
->backPitch
;
194 r128Screen
->depthOffset
= r128DRIPriv
->depthOffset
;
195 r128Screen
->depthPitch
= r128DRIPriv
->depthPitch
;
196 r128Screen
->spanOffset
= r128DRIPriv
->spanOffset
;
198 if ( r128DRIPriv
->textureSize
== 0 ) {
199 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] =
200 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
201 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
202 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] =
203 r128DRIPriv
->log2AGPTexGran
;
205 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureOffset
;
206 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureSize
;
207 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->log2TexGran
;
210 if ( !r128Screen
->agpTextures
.map
|| r128DRIPriv
->textureSize
== 0 ) {
211 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
- 1;
212 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] = 0;
213 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = 0;
214 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] = 0;
216 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
;
217 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] =
218 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
219 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
220 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] =
221 r128DRIPriv
->log2AGPTexGran
;
224 r128Screen
->driScreen
= sPriv
;
227 r128Screen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
228 if ( r128Screen
->irq
!= 0 ) {
229 r128Screen
->extensions
[i
++] = &driSwapControlExtension
.base
;
230 r128Screen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
232 r128Screen
->extensions
[i
++] = NULL
;
233 sPriv
->extensions
= r128Screen
->extensions
;
238 /* Destroy the device specific screen private data struct.
241 r128DestroyScreen( __DRIscreenPrivate
*sPriv
)
243 r128ScreenPtr r128Screen
= (r128ScreenPtr
)sPriv
->private;
248 if ( !r128Screen
->IsPCI
) {
249 drmUnmap( (drmAddress
)r128Screen
->agpTextures
.map
,
250 r128Screen
->agpTextures
.size
);
252 drmUnmapBufs( r128Screen
->buffers
);
253 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
255 /* free all option information */
256 driDestroyOptionInfo (&r128Screen
->optionCache
);
259 sPriv
->private = NULL
;
263 /* Create and initialize the Mesa and driver specific pixmap buffer
267 r128CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
268 __DRIdrawablePrivate
*driDrawPriv
,
269 const __GLcontextModes
*mesaVis
,
272 r128ScreenPtr screen
= (r128ScreenPtr
) driScrnPriv
->private;
275 return GL_FALSE
; /* not implemented */
278 const GLboolean swDepth
= GL_FALSE
;
279 const GLboolean swAlpha
= GL_FALSE
;
280 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
281 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 &&
282 mesaVis
->depthBits
!= 24;
283 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
286 driRenderbuffer
*frontRb
287 = driNewRenderbuffer(GL_RGBA
,
290 screen
->frontOffset
, screen
->frontPitch
,
292 r128SetSpanFunctions(frontRb
, mesaVis
);
293 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
296 if (mesaVis
->doubleBufferMode
) {
297 driRenderbuffer
*backRb
298 = driNewRenderbuffer(GL_RGBA
,
301 screen
->backOffset
, screen
->backPitch
,
303 r128SetSpanFunctions(backRb
, mesaVis
);
304 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
307 if (mesaVis
->depthBits
== 16) {
308 driRenderbuffer
*depthRb
309 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
312 screen
->depthOffset
, screen
->depthPitch
,
314 r128SetSpanFunctions(depthRb
, mesaVis
);
315 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
317 else if (mesaVis
->depthBits
== 24) {
318 driRenderbuffer
*depthRb
319 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
322 screen
->depthOffset
, screen
->depthPitch
,
324 r128SetSpanFunctions(depthRb
, mesaVis
);
325 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
328 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
329 driRenderbuffer
*stencilRb
330 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
,
333 screen
->depthOffset
, screen
->depthPitch
,
335 r128SetSpanFunctions(stencilRb
, mesaVis
);
336 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
339 _mesa_add_soft_renderbuffers(fb
,
340 GL_FALSE
, /* color */
346 driDrawPriv
->driverPrivate
= (void *) fb
;
348 return (driDrawPriv
->driverPrivate
!= NULL
);
354 r128DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
356 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
360 /* Copy the back color buffer to the front color buffer */
362 r128SwapBuffers(__DRIdrawablePrivate
*dPriv
)
364 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
365 r128ContextPtr rmesa
;
367 rmesa
= (r128ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
369 if (ctx
->Visual
.doubleBufferMode
) {
370 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
371 if ( rmesa
->doPageFlip
) {
372 r128PageFlip( dPriv
);
375 r128CopyBuffer( dPriv
);
380 /* XXX this shouldn't be an error but we can't handle it for now */
381 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
386 /* Initialize the driver specific screen private data.
389 r128InitDriver( __DRIscreenPrivate
*sPriv
)
391 sPriv
->private = (void *) r128CreateScreen( sPriv
);
393 if ( !sPriv
->private ) {
394 r128DestroyScreen( sPriv
);
401 static const __DRIconfig
**
402 r128FillInModes( __DRIscreenPrivate
*psp
,
403 unsigned pixel_bits
, unsigned depth_bits
,
404 unsigned stencil_bits
, GLboolean have_back_buffer
)
406 __DRIconfig
**configs
;
407 __GLcontextModes
* m
;
408 unsigned depth_buffer_factor
;
409 unsigned back_buffer_factor
;
414 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
415 * enough to add support. Basically, if a context is created with an
416 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
417 * will never be used.
419 static const GLenum back_buffer_modes
[] = {
420 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
423 uint8_t depth_bits_array
[2];
424 uint8_t stencil_bits_array
[2];
427 depth_bits_array
[0] = depth_bits
;
428 depth_bits_array
[1] = depth_bits
;
430 /* Just like with the accumulation buffer, always provide some modes
431 * with a stencil buffer. It will be a sw fallback, but some apps won't
434 stencil_bits_array
[0] = 0;
435 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
437 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
438 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
440 if ( pixel_bits
== 16 ) {
442 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
446 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
449 configs
= driCreateConfigs(fb_format
, fb_type
,
450 depth_bits_array
, stencil_bits_array
,
451 depth_buffer_factor
, back_buffer_modes
,
453 if (configs
== NULL
) {
454 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
,
459 /* Mark the visual as slow if there are "fake" stencil bits.
461 for (i
= 0; configs
[i
]; i
++) {
462 m
= &configs
[i
]->modes
;
463 if ((m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
)) {
464 m
->visualRating
= GLX_SLOW_CONFIG
;
468 return (const __DRIconfig
**) configs
;
473 * This is the driver specific part of the createNewScreen entry point.
475 * \todo maybe fold this into intelInitDriver
477 * \return the __GLcontextModes supported by this driver
479 static const __DRIconfig
**
480 r128InitScreen(__DRIscreenPrivate
*psp
)
482 static const __DRIversion ddx_expected
= { 4, 0, 0 };
483 static const __DRIversion dri_expected
= { 4, 0, 0 };
484 static const __DRIversion drm_expected
= { 2, 2, 0 };
485 R128DRIPtr dri_priv
= (R128DRIPtr
) psp
->pDevPriv
;
487 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
488 &psp
->dri_version
, & dri_expected
,
489 &psp
->ddx_version
, & ddx_expected
,
490 &psp
->drm_version
, & drm_expected
) )
493 /* Calling driInitExtensions here, with a NULL context pointer,
494 * does not actually enable the extensions. It just makes sure
495 * that all the dispatch offsets for all the extensions that
496 * *might* be enables are known. This is needed because the
497 * dispatch offsets need to be known when _mesa_context_create is
498 * called, but we can't enable the extensions until we have a
501 * Hello chicken. Hello egg. How are you two today?
503 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
505 if (!r128InitDriver(psp
))
508 return r128FillInModes( psp
,
510 (dri_priv
->bpp
== 16) ? 16 : 24,
511 (dri_priv
->bpp
== 16) ? 0 : 8,
512 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
515 const struct __DriverAPIRec driDriverAPI
= {
516 .InitScreen
= r128InitScreen
,
517 .DestroyScreen
= r128DestroyScreen
,
518 .CreateContext
= r128CreateContext
,
519 .DestroyContext
= r128DestroyContext
,
520 .CreateBuffer
= r128CreateBuffer
,
521 .DestroyBuffer
= r128DestroyBuffer
,
522 .SwapBuffers
= r128SwapBuffers
,
523 .MakeCurrent
= r128MakeCurrent
,
524 .UnbindContext
= r128UnbindContext
,
526 .GetDrawableMSC
= driDrawableGetMSC32
,
527 .WaitForMSC
= driWaitForMSC32
,
529 .SwapBuffersMSC
= NULL