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;
78 /* Including xf86PciInfo.h introduces a bunch of errors...
80 #define PCI_CHIP_RAGE128LE 0x4C45
81 #define PCI_CHIP_RAGE128LF 0x4C46
82 #define PCI_CHIP_RAGE128PF 0x5046
83 #define PCI_CHIP_RAGE128PR 0x5052
84 #define PCI_CHIP_RAGE128RE 0x5245
85 #define PCI_CHIP_RAGE128RF 0x5246
86 #define PCI_CHIP_RAGE128RK 0x524B
87 #define PCI_CHIP_RAGE128RL 0x524C
91 /* Create the device specific screen private data struct.
94 r128CreateScreen( __DRIscreenPrivate
*sPriv
)
96 r128ScreenPtr r128Screen
;
97 R128DRIPtr r128DRIPriv
= (R128DRIPtr
)sPriv
->pDevPriv
;
100 if (sPriv
->devPrivSize
!= sizeof(R128DRIRec
)) {
101 fprintf(stderr
,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
105 /* Allocate the private area */
106 r128Screen
= (r128ScreenPtr
) CALLOC( sizeof(*r128Screen
) );
107 if ( !r128Screen
) return NULL
;
109 /* parse information in __driConfigOptions */
110 driParseOptionInfo (&r128Screen
->optionCache
,
111 __driConfigOptions
, __driNConfigOptions
);
113 /* This is first since which regions we map depends on whether or
114 * not we are using a PCI card.
116 r128Screen
->IsPCI
= r128DRIPriv
->IsPCI
;
117 r128Screen
->sarea_priv_offset
= r128DRIPriv
->sarea_priv_offset
;
119 if (sPriv
->drm_version
.minor
>= 3) {
120 drm_r128_getparam_t gp
;
123 gp
.param
= R128_PARAM_IRQ_NR
;
124 gp
.value
= &r128Screen
->irq
;
126 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_R128_GETPARAM
,
129 fprintf(stderr
, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret
);
135 r128Screen
->mmio
.handle
= r128DRIPriv
->registerHandle
;
136 r128Screen
->mmio
.size
= r128DRIPriv
->registerSize
;
137 if ( drmMap( sPriv
->fd
,
138 r128Screen
->mmio
.handle
,
139 r128Screen
->mmio
.size
,
140 (drmAddressPtr
)&r128Screen
->mmio
.map
) ) {
145 r128Screen
->buffers
= drmMapBufs( sPriv
->fd
);
146 if ( !r128Screen
->buffers
) {
147 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
152 if ( !r128Screen
->IsPCI
) {
153 r128Screen
->agpTextures
.handle
= r128DRIPriv
->agpTexHandle
;
154 r128Screen
->agpTextures
.size
= r128DRIPriv
->agpTexMapSize
;
155 if ( drmMap( sPriv
->fd
,
156 r128Screen
->agpTextures
.handle
,
157 r128Screen
->agpTextures
.size
,
158 (drmAddressPtr
)&r128Screen
->agpTextures
.map
) ) {
159 drmUnmapBufs( r128Screen
->buffers
);
160 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
166 switch ( r128DRIPriv
->deviceID
) {
167 case PCI_CHIP_RAGE128RE
:
168 case PCI_CHIP_RAGE128RF
:
169 case PCI_CHIP_RAGE128RK
:
170 case PCI_CHIP_RAGE128RL
:
171 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
173 case PCI_CHIP_RAGE128PF
:
174 r128Screen
->chipset
= R128_CARD_TYPE_R128_PRO
;
176 case PCI_CHIP_RAGE128LE
:
177 case PCI_CHIP_RAGE128LF
:
178 r128Screen
->chipset
= R128_CARD_TYPE_R128_MOBILITY
;
181 r128Screen
->chipset
= R128_CARD_TYPE_R128
;
185 r128Screen
->cpp
= r128DRIPriv
->bpp
/ 8;
186 r128Screen
->AGPMode
= r128DRIPriv
->AGPMode
;
188 r128Screen
->frontOffset
= r128DRIPriv
->frontOffset
;
189 r128Screen
->frontPitch
= r128DRIPriv
->frontPitch
;
190 r128Screen
->backOffset
= r128DRIPriv
->backOffset
;
191 r128Screen
->backPitch
= r128DRIPriv
->backPitch
;
192 r128Screen
->depthOffset
= r128DRIPriv
->depthOffset
;
193 r128Screen
->depthPitch
= r128DRIPriv
->depthPitch
;
194 r128Screen
->spanOffset
= r128DRIPriv
->spanOffset
;
196 if ( r128DRIPriv
->textureSize
== 0 ) {
197 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] =
198 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
199 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
200 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] =
201 r128DRIPriv
->log2AGPTexGran
;
203 r128Screen
->texOffset
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureOffset
;
204 r128Screen
->texSize
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->textureSize
;
205 r128Screen
->logTexGranularity
[R128_LOCAL_TEX_HEAP
] = r128DRIPriv
->log2TexGran
;
208 if ( !r128Screen
->agpTextures
.map
|| r128DRIPriv
->textureSize
== 0 ) {
209 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
- 1;
210 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] = 0;
211 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = 0;
212 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] = 0;
214 r128Screen
->numTexHeaps
= R128_NR_TEX_HEAPS
;
215 r128Screen
->texOffset
[R128_AGP_TEX_HEAP
] =
216 r128DRIPriv
->agpTexOffset
+ R128_AGP_TEX_OFFSET
;
217 r128Screen
->texSize
[R128_AGP_TEX_HEAP
] = r128DRIPriv
->agpTexMapSize
;
218 r128Screen
->logTexGranularity
[R128_AGP_TEX_HEAP
] =
219 r128DRIPriv
->log2AGPTexGran
;
222 r128Screen
->driScreen
= sPriv
;
225 r128Screen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
226 if ( r128Screen
->irq
!= 0 ) {
227 r128Screen
->extensions
[i
++] = &driSwapControlExtension
.base
;
228 r128Screen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
230 r128Screen
->extensions
[i
++] = NULL
;
231 sPriv
->extensions
= r128Screen
->extensions
;
236 /* Destroy the device specific screen private data struct.
239 r128DestroyScreen( __DRIscreenPrivate
*sPriv
)
241 r128ScreenPtr r128Screen
= (r128ScreenPtr
)sPriv
->private;
246 if ( !r128Screen
->IsPCI
) {
247 drmUnmap( (drmAddress
)r128Screen
->agpTextures
.map
,
248 r128Screen
->agpTextures
.size
);
250 drmUnmapBufs( r128Screen
->buffers
);
251 drmUnmap( (drmAddress
)r128Screen
->mmio
.map
, r128Screen
->mmio
.size
);
253 /* free all option information */
254 driDestroyOptionInfo (&r128Screen
->optionCache
);
257 sPriv
->private = NULL
;
261 /* Create and initialize the Mesa and driver specific pixmap buffer
265 r128CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
266 __DRIdrawablePrivate
*driDrawPriv
,
267 const __GLcontextModes
*mesaVis
,
270 r128ScreenPtr screen
= (r128ScreenPtr
) driScrnPriv
->private;
273 return GL_FALSE
; /* not implemented */
276 const GLboolean swDepth
= GL_FALSE
;
277 const GLboolean swAlpha
= GL_FALSE
;
278 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
279 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 &&
280 mesaVis
->depthBits
!= 24;
281 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
284 driRenderbuffer
*frontRb
285 = driNewRenderbuffer(GL_RGBA
,
288 screen
->frontOffset
, screen
->frontPitch
,
290 r128SetSpanFunctions(frontRb
, mesaVis
);
291 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
294 if (mesaVis
->doubleBufferMode
) {
295 driRenderbuffer
*backRb
296 = driNewRenderbuffer(GL_RGBA
,
299 screen
->backOffset
, screen
->backPitch
,
301 r128SetSpanFunctions(backRb
, mesaVis
);
302 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
305 if (mesaVis
->depthBits
== 16) {
306 driRenderbuffer
*depthRb
307 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
310 screen
->depthOffset
, screen
->depthPitch
,
312 r128SetSpanFunctions(depthRb
, mesaVis
);
313 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
315 else if (mesaVis
->depthBits
== 24) {
316 driRenderbuffer
*depthRb
317 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
320 screen
->depthOffset
, screen
->depthPitch
,
322 r128SetSpanFunctions(depthRb
, mesaVis
);
323 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
326 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
327 driRenderbuffer
*stencilRb
328 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
,
331 screen
->depthOffset
, screen
->depthPitch
,
333 r128SetSpanFunctions(stencilRb
, mesaVis
);
334 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
337 _mesa_add_soft_renderbuffers(fb
,
338 GL_FALSE
, /* color */
344 driDrawPriv
->driverPrivate
= (void *) fb
;
346 return (driDrawPriv
->driverPrivate
!= NULL
);
352 r128DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
354 _mesa_reference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)), NULL
);
358 /* Copy the back color buffer to the front color buffer */
360 r128SwapBuffers(__DRIdrawablePrivate
*dPriv
)
362 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
363 r128ContextPtr rmesa
;
365 rmesa
= (r128ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
367 if (ctx
->Visual
.doubleBufferMode
) {
368 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
369 if ( rmesa
->doPageFlip
) {
370 r128PageFlip( dPriv
);
373 r128CopyBuffer( dPriv
);
378 /* XXX this shouldn't be an error but we can't handle it for now */
379 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
384 /* Initialize the driver specific screen private data.
387 r128InitDriver( __DRIscreenPrivate
*sPriv
)
389 sPriv
->private = (void *) r128CreateScreen( sPriv
);
391 if ( !sPriv
->private ) {
392 r128DestroyScreen( sPriv
);
399 static const __DRIconfig
**
400 r128FillInModes( __DRIscreenPrivate
*psp
,
401 unsigned pixel_bits
, unsigned depth_bits
,
402 unsigned stencil_bits
, GLboolean have_back_buffer
)
404 __DRIconfig
**configs
;
405 __GLcontextModes
* m
;
406 unsigned depth_buffer_factor
;
407 unsigned back_buffer_factor
;
412 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
413 * enough to add support. Basically, if a context is created with an
414 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
415 * will never be used.
417 static const GLenum back_buffer_modes
[] = {
418 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
421 uint8_t depth_bits_array
[2];
422 uint8_t stencil_bits_array
[2];
423 uint8_t msaa_samples_array
[1];
425 depth_bits_array
[0] = depth_bits
;
426 depth_bits_array
[1] = depth_bits
;
428 /* Just like with the accumulation buffer, always provide some modes
429 * with a stencil buffer. It will be a sw fallback, but some apps won't
432 stencil_bits_array
[0] = 0;
433 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
435 msaa_samples_array
[0] = 0;
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 msaa_samples_array
, 1);
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 if (!r128InitDriver(psp
))
497 return r128FillInModes( psp
,
499 (dri_priv
->bpp
== 16) ? 16 : 24,
500 (dri_priv
->bpp
== 16) ? 0 : 8,
501 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
504 const struct __DriverAPIRec driDriverAPI
= {
505 .InitScreen
= r128InitScreen
,
506 .DestroyScreen
= r128DestroyScreen
,
507 .CreateContext
= r128CreateContext
,
508 .DestroyContext
= r128DestroyContext
,
509 .CreateBuffer
= r128CreateBuffer
,
510 .DestroyBuffer
= r128DestroyBuffer
,
511 .SwapBuffers
= r128SwapBuffers
,
512 .MakeCurrent
= r128MakeCurrent
,
513 .UnbindContext
= r128UnbindContext
,
515 .GetDrawableMSC
= driDrawableGetMSC32
,
516 .WaitForMSC
= driWaitForMSC32
,
518 .SwapBuffersMSC
= NULL