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"
41 #include "main/context.h"
42 #include "main/imports.h"
43 #include "main/framebuffer.h"
44 #include "main/renderbuffer.h"
49 #include "GL/internal/dri_interface.h"
55 PUBLIC
const char __driConfigOptions
[] =
57 DRI_CONF_SECTION_PERFORMANCE
58 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
60 DRI_CONF_SECTION_QUALITY
61 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB
)
63 DRI_CONF_SECTION_DEBUG
64 DRI_CONF_NO_RAST(false)
66 DRI_CONF_PERFORMANCE_BOXES(false)
71 static const GLuint __driNConfigOptions
= 4;
73 static const GLuint __driNConfigOptions
= 3;
77 /* Including xf86PciInfo.h introduces a bunch of errors...
79 #define PCI_CHIP_RAGE128LE 0x4C45
80 #define PCI_CHIP_RAGE128LF 0x4C46
81 #define PCI_CHIP_RAGE128PF 0x5046
82 #define PCI_CHIP_RAGE128PR 0x5052
83 #define PCI_CHIP_RAGE128RE 0x5245
84 #define PCI_CHIP_RAGE128RF 0x5246
85 #define PCI_CHIP_RAGE128RK 0x524B
86 #define PCI_CHIP_RAGE128RL 0x524C
90 /* Create the device specific screen private data struct.
93 r128CreateScreen( __DRIscreen
*sPriv
)
95 r128ScreenPtr r128Screen
;
96 R128DRIPtr r128DRIPriv
= (R128DRIPtr
)sPriv
->pDevPriv
;
99 if (sPriv
->devPrivSize
!= sizeof(R128DRIRec
)) {
100 fprintf(stderr
,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
104 /* Allocate the private area */
105 r128Screen
= (r128ScreenPtr
) CALLOC( sizeof(*r128Screen
) );
106 if ( !r128Screen
) return NULL
;
108 /* parse information in __driConfigOptions */
109 driParseOptionInfo (&r128Screen
->optionCache
,
110 __driConfigOptions
, __driNConfigOptions
);
112 /* This is first since which regions we map depends on whether or
113 * not we are using a PCI card.
115 r128Screen
->IsPCI
= r128DRIPriv
->IsPCI
;
116 r128Screen
->sarea_priv_offset
= r128DRIPriv
->sarea_priv_offset
;
118 if (sPriv
->drm_version
.minor
>= 3) {
119 drm_r128_getparam_t gp
;
122 gp
.param
= R128_PARAM_IRQ_NR
;
123 gp
.value
= &r128Screen
->irq
;
125 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_R128_GETPARAM
,
128 fprintf(stderr
, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret
);
134 r128Screen
->mmio
.handle
= r128DRIPriv
->registerHandle
;
135 r128Screen
->mmio
.size
= r128DRIPriv
->registerSize
;
136 if ( drmMap( sPriv
->fd
,
137 r128Screen
->mmio
.handle
,
138 r128Screen
->mmio
.size
,
139 (drmAddressPtr
)&r128Screen
->mmio
.map
) ) {
144 r128Screen
->buffers
= drmMapBufs( sPriv
->fd
);
145 if ( !r128Screen
->buffers
) {
146 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
151 if ( !r128Screen
->IsPCI
) {
152 r128Screen
->agpTextures
.handle
= r128DRIPriv
->agpTexHandle
;
153 r128Screen
->agpTextures
.size
= r128DRIPriv
->agpTexMapSize
;
154 if ( drmMap( sPriv
->fd
,
155 r128Screen
->agpTextures
.handle
,
156 r128Screen
->agpTextures
.size
,
157 (drmAddressPtr
)&r128Screen
->agpTextures
.map
) ) {
158 drmUnmapBufs( r128Screen
->buffers
);
159 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
165 switch ( r128DRIPriv
->deviceID
) {
166 case PCI_CHIP_RAGE128RE
:
167 case PCI_CHIP_RAGE128RF
:
168 case PCI_CHIP_RAGE128RK
:
169 case PCI_CHIP_RAGE128RL
:
170 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
172 case PCI_CHIP_RAGE128PF
:
173 r128Screen
->chipset
= R128_CARD_TYPE_R128_PRO
;
175 case PCI_CHIP_RAGE128LE
:
176 case PCI_CHIP_RAGE128LF
:
177 r128Screen
->chipset
= R128_CARD_TYPE_R128_MOBILITY
;
180 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
184 r128Screen
->cpp
= r128DRIPriv
->bpp
/ 8;
185 r128Screen
->AGPMode
= r128DRIPriv
->AGPMode
;
187 r128Screen
->frontOffset
= r128DRIPriv
->frontOffset
;
188 r128Screen
->frontPitch
= r128DRIPriv
->frontPitch
;
189 r128Screen
->backOffset
= r128DRIPriv
->backOffset
;
190 r128Screen
->backPitch
= r128DRIPriv
->backPitch
;
191 r128Screen
->depthOffset
= r128DRIPriv
->depthOffset
;
192 r128Screen
->depthPitch
= r128DRIPriv
->depthPitch
;
193 r128Screen
->spanOffset
= r128DRIPriv
->spanOffset
;
195 if ( r128DRIPriv
->textureSize
== 0 ) {
196 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] =
197 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
198 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
199 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] =
200 r128DRIPriv
->log2AGPTexGran
;
202 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureOffset
;
203 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureSize
;
204 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->log2TexGran
;
207 if ( !r128Screen
->agpTextures
.map
|| r128DRIPriv
->textureSize
== 0 ) {
208 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
- 1;
209 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] = 0;
210 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = 0;
211 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] = 0;
213 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
;
214 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] =
215 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
216 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
217 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] =
218 r128DRIPriv
->log2AGPTexGran
;
221 r128Screen
->driScreen
= sPriv
;
224 r128Screen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
225 if ( r128Screen
->irq
!= 0 ) {
226 r128Screen
->extensions
[i
++] = &driSwapControlExtension
.base
;
227 r128Screen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
229 r128Screen
->extensions
[i
++] = NULL
;
230 sPriv
->extensions
= r128Screen
->extensions
;
235 /* Destroy the device specific screen private data struct.
238 r128DestroyScreen( __DRIscreen
*sPriv
)
240 r128ScreenPtr r128Screen
= (r128ScreenPtr
)sPriv
->private;
245 if ( !r128Screen
->IsPCI
) {
246 drmUnmap( (drmAddress
)r128Screen
->agpTextures
.map
,
247 r128Screen
->agpTextures
.size
);
249 drmUnmapBufs( r128Screen
->buffers
);
250 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
252 /* free all option information */
253 driDestroyOptionInfo (&r128Screen
->optionCache
);
256 sPriv
->private = NULL
;
260 /* Create and initialize the Mesa and driver specific pixmap buffer
264 r128CreateBuffer( __DRIscreen
*driScrnPriv
,
265 __DRIdrawable
*driDrawPriv
,
266 const __GLcontextModes
*mesaVis
,
269 r128ScreenPtr screen
= (r128ScreenPtr
) driScrnPriv
->private;
272 return GL_FALSE
; /* not implemented */
275 const GLboolean swDepth
= GL_FALSE
;
276 const GLboolean swAlpha
= GL_FALSE
;
277 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
278 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 &&
279 mesaVis
->depthBits
!= 24;
280 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
283 driRenderbuffer
*frontRb
284 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
,
287 screen
->frontOffset
, screen
->frontPitch
,
289 r128SetSpanFunctions(frontRb
, mesaVis
);
290 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
293 if (mesaVis
->doubleBufferMode
) {
294 driRenderbuffer
*backRb
295 = driNewRenderbuffer(MESA_FORMAT_ARGB8888
,
298 screen
->backOffset
, screen
->backPitch
,
300 r128SetSpanFunctions(backRb
, mesaVis
);
301 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
304 if (mesaVis
->depthBits
== 16) {
305 driRenderbuffer
*depthRb
306 = driNewRenderbuffer(MESA_FORMAT_Z16
,
309 screen
->depthOffset
, screen
->depthPitch
,
311 r128SetSpanFunctions(depthRb
, mesaVis
);
312 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
314 else if (mesaVis
->depthBits
== 24) {
315 driRenderbuffer
*depthRb
316 = driNewRenderbuffer(MESA_FORMAT_S8_Z24
,
319 screen
->depthOffset
, screen
->depthPitch
,
321 r128SetSpanFunctions(depthRb
, mesaVis
);
322 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
325 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
326 driRenderbuffer
*stencilRb
327 = driNewRenderbuffer(MESA_FORMAT_S8
,
330 screen
->depthOffset
, screen
->depthPitch
,
332 r128SetSpanFunctions(stencilRb
, mesaVis
);
333 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
336 _mesa_add_soft_renderbuffers(fb
,
337 GL_FALSE
, /* color */
343 driDrawPriv
->driverPrivate
= (void *) fb
;
345 return (driDrawPriv
->driverPrivate
!= NULL
);
351 r128DestroyBuffer(__DRIdrawable
*driDrawPriv
)
353 _mesa_reference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)), NULL
);
357 /* Copy the back color buffer to the front color buffer */
359 r128SwapBuffers(__DRIdrawable
*dPriv
)
361 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
362 r128ContextPtr rmesa
;
364 rmesa
= (r128ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
366 if (ctx
->Visual
.doubleBufferMode
) {
367 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
368 if ( rmesa
->doPageFlip
) {
369 r128PageFlip( dPriv
);
372 r128CopyBuffer( dPriv
);
377 /* XXX this shouldn't be an error but we can't handle it for now */
378 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
383 /* Initialize the driver specific screen private data.
386 r128InitDriver( __DRIscreen
*sPriv
)
388 sPriv
->private = (void *) r128CreateScreen( sPriv
);
390 if ( !sPriv
->private ) {
391 r128DestroyScreen( sPriv
);
398 static const __DRIconfig
**
399 r128FillInModes( __DRIscreen
*psp
,
400 unsigned pixel_bits
, unsigned depth_bits
,
401 unsigned stencil_bits
, GLboolean have_back_buffer
)
403 __DRIconfig
**configs
;
404 __GLcontextModes
* m
;
405 unsigned depth_buffer_factor
;
406 unsigned back_buffer_factor
;
411 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
412 * enough to add support. Basically, if a context is created with an
413 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
414 * will never be used.
416 static const GLenum back_buffer_modes
[] = {
417 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
420 uint8_t depth_bits_array
[2];
421 uint8_t stencil_bits_array
[2];
422 uint8_t msaa_samples_array
[1];
424 depth_bits_array
[0] = depth_bits
;
425 depth_bits_array
[1] = depth_bits
;
427 /* Just like with the accumulation buffer, always provide some modes
428 * with a stencil buffer. It will be a sw fallback, but some apps won't
431 stencil_bits_array
[0] = 0;
432 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
434 msaa_samples_array
[0] = 0;
436 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
437 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
439 if ( pixel_bits
== 16 ) {
441 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
445 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
448 configs
= driCreateConfigs(fb_format
, fb_type
,
449 depth_bits_array
, stencil_bits_array
,
450 depth_buffer_factor
, back_buffer_modes
,
452 msaa_samples_array
, 1, GL_TRUE
);
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(__DRIscreen
*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 if (!r128InitDriver(psp
))
496 return r128FillInModes( psp
,
498 (dri_priv
->bpp
== 16) ? 16 : 24,
499 (dri_priv
->bpp
== 16) ? 0 : 8,
500 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
503 const struct __DriverAPIRec driDriverAPI
= {
504 .InitScreen
= r128InitScreen
,
505 .DestroyScreen
= r128DestroyScreen
,
506 .CreateContext
= r128CreateContext
,
507 .DestroyContext
= r128DestroyContext
,
508 .CreateBuffer
= r128CreateBuffer
,
509 .DestroyBuffer
= r128DestroyBuffer
,
510 .SwapBuffers
= r128SwapBuffers
,
511 .MakeCurrent
= r128MakeCurrent
,
512 .UnbindContext
= r128UnbindContext
,
514 .GetDrawableMSC
= driDrawableGetMSC32
,
515 .WaitForMSC
= driWaitForMSC32
,
517 .SwapBuffersMSC
= NULL
520 /* This is the table of extensions that the loader will dlsym() for. */
521 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
522 &driCoreExtension
.base
,
523 &driLegacyExtension
.base
,