1 /* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
3 * Copyright 2000 Gareth Hughes
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * Jos�Fonseca <j_r_fonseca@yahoo.co.uk>
32 #include "mach64_context.h"
33 #include "mach64_ioctl.h"
34 #include "mach64_tris.h"
35 #include "mach64_vb.h"
36 #include "mach64_span.h"
40 #include "framebuffer.h"
41 #include "renderbuffer.h"
46 #include "GL/internal/dri_interface.h"
48 /* Mach64 configuration
52 PUBLIC
const char __driConfigOptions
[] =
54 DRI_CONF_SECTION_PERFORMANCE
55 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
57 DRI_CONF_SECTION_DEBUG
58 DRI_CONF_NO_RAST(false)
60 DRI_CONF_PERFORMANCE_BOXES(false)
65 static const GLuint __driNConfigOptions
= 3;
67 static const GLuint __driNConfigOptions
= 2;
70 extern const struct dri_extension card_extensions
[];
72 static __GLcontextModes
* fill_in_modes( __GLcontextModes
* modes
,
75 unsigned stencil_bits
,
76 const GLenum
* db_modes
,
77 unsigned num_db_modes
,
80 static const u_int8_t bits
[2][4] = {
85 static const u_int32_t masks
[2][4] = {
86 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
87 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }
92 const unsigned index
= ((pixel_bits
+ 15) / 16) - 1;
94 for ( i
= 0 ; i
< num_db_modes
; i
++ ) {
95 for ( j
= 0 ; j
< 2 ; j
++ ) {
97 modes
->redBits
= bits
[index
][0];
98 modes
->greenBits
= bits
[index
][1];
99 modes
->blueBits
= bits
[index
][2];
100 modes
->alphaBits
= bits
[index
][3];
101 modes
->redMask
= masks
[index
][0];
102 modes
->greenMask
= masks
[index
][1];
103 modes
->blueMask
= masks
[index
][2];
104 modes
->alphaMask
= masks
[index
][3];
105 modes
->rgbBits
= modes
->redBits
+ modes
->greenBits
106 + modes
->blueBits
+ modes
->alphaBits
;
108 modes
->accumRedBits
= 16 * j
;
109 modes
->accumGreenBits
= 16 * j
;
110 modes
->accumBlueBits
= 16 * j
;
111 modes
->accumAlphaBits
= 0;
112 modes
->visualRating
= (j
== 0) ? GLX_NONE
: GLX_SLOW_CONFIG
;
113 modes
->drawableType
= GLX_WINDOW_BIT
| GLX_PIXMAP_BIT
;
114 modes
->stencilBits
= stencil_bits
;
115 modes
->depthBits
= depth_bits
;
117 modes
->visualType
= visType
;
118 modes
->renderType
= GLX_RGBA_BIT
;
119 modes
->rgbMode
= GL_TRUE
;
121 if ( db_modes
[i
] == GLX_NONE
) {
123 modes
->doubleBufferMode
= GL_FALSE
;
126 modes
->doubleBufferMode
= GL_TRUE
;
127 modes
->swapMethod
= db_modes
[i
];
138 static __GLcontextModes
*
139 mach64FillInModes( unsigned pixel_bits
, unsigned depth_bits
,
140 unsigned stencil_bits
, GLboolean have_back_buffer
)
142 __GLcontextModes
* modes
;
143 __GLcontextModes
* m
;
145 unsigned depth_buffer_factor
;
146 unsigned back_buffer_factor
;
149 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
150 * enough to add support. Basically, if a context is created with an
151 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
152 * will never be used.
154 static const GLenum back_buffer_modes
[] = {
155 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
158 int depth_buffer_modes
[2][2];
161 depth_buffer_modes
[0][0] = depth_bits
;
162 depth_buffer_modes
[1][0] = depth_bits
;
164 /* Just like with the accumulation buffer, always provide some modes
165 * with a stencil buffer. It will be a sw fallback, but some apps won't
168 depth_buffer_modes
[0][1] = 0;
169 depth_buffer_modes
[1][1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
171 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
172 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
174 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
176 modes
= (*dri_interface
->createContextModes
)( num_modes
, sizeof( __GLcontextModes
) );
178 for ( i
= 0 ; i
< depth_buffer_factor
; i
++ ) {
179 m
= fill_in_modes( m
, pixel_bits
,
180 depth_buffer_modes
[i
][0], depth_buffer_modes
[i
][1],
181 back_buffer_modes
, back_buffer_factor
,
185 for ( i
= 0 ; i
< depth_buffer_factor
; i
++ ) {
186 m
= fill_in_modes( m
, pixel_bits
,
187 depth_buffer_modes
[i
][0], depth_buffer_modes
[i
][1],
188 back_buffer_modes
, back_buffer_factor
,
192 /* Mark the visual as slow if there are "fake" stencil bits.
194 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
195 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ){
196 m
->visualRating
= GLX_SLOW_CONFIG
;
204 /* Create the device specific screen private data struct.
206 static mach64ScreenRec
*
207 mach64CreateScreen( __DRIscreenPrivate
*sPriv
)
209 mach64ScreenPtr mach64Screen
;
210 ATIDRIPtr serverInfo
= (ATIDRIPtr
)sPriv
->pDevPriv
;
213 if (sPriv
->devPrivSize
!= sizeof(ATIDRIRec
)) {
214 fprintf(stderr
,"\nERROR! sizeof(ATIDRIRec) does not match passed size from device driver\n");
218 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
219 fprintf( stderr
, "%s\n", __FUNCTION__
);
221 /* Allocate the private area */
222 mach64Screen
= (mach64ScreenPtr
) CALLOC( sizeof(*mach64Screen
) );
223 if ( !mach64Screen
) return NULL
;
225 /* parse information in __driConfigOptions */
226 driParseOptionInfo (&mach64Screen
->optionCache
,
227 __driConfigOptions
, __driNConfigOptions
);
229 mach64Screen
->IsPCI
= serverInfo
->IsPCI
;
232 drm_mach64_getparam_t gp
;
235 gp
.param
= MACH64_PARAM_IRQ_NR
;
236 gp
.value
= (void *) &mach64Screen
->irq
;
238 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_MACH64_GETPARAM
,
241 fprintf(stderr
, "DRM_MACH64_GETPARAM (MACH64_PARAM_IRQ_NR): %d\n", ret
);
242 FREE( mach64Screen
);
247 mach64Screen
->mmio
.handle
= serverInfo
->regs
;
248 mach64Screen
->mmio
.size
= serverInfo
->regsSize
;
249 if ( drmMap( sPriv
->fd
,
250 mach64Screen
->mmio
.handle
,
251 mach64Screen
->mmio
.size
,
252 (drmAddressPtr
)&mach64Screen
->mmio
.map
) != 0 ) {
253 FREE( mach64Screen
);
257 mach64Screen
->buffers
= drmMapBufs( sPriv
->fd
);
258 if ( !mach64Screen
->buffers
) {
259 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
,
260 mach64Screen
->mmio
.size
);
261 FREE( mach64Screen
);
265 if ( !mach64Screen
->IsPCI
) {
266 mach64Screen
->agpTextures
.handle
= serverInfo
->agp
;
267 mach64Screen
->agpTextures
.size
= serverInfo
->agpSize
;
268 if ( drmMap( sPriv
->fd
,
269 mach64Screen
->agpTextures
.handle
,
270 mach64Screen
->agpTextures
.size
,
271 (drmAddressPtr
)&mach64Screen
->agpTextures
.map
) ) {
272 drmUnmapBufs( mach64Screen
->buffers
);
273 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
, mach64Screen
->mmio
.size
);
274 FREE( mach64Screen
);
279 mach64Screen
->AGPMode
= serverInfo
->AGPMode
;
281 mach64Screen
->chipset
= serverInfo
->chipset
;
282 mach64Screen
->width
= serverInfo
->width
;
283 mach64Screen
->height
= serverInfo
->height
;
284 mach64Screen
->mem
= serverInfo
->mem
;
285 mach64Screen
->cpp
= serverInfo
->cpp
;
287 mach64Screen
->frontOffset
= serverInfo
->frontOffset
;
288 mach64Screen
->frontPitch
= serverInfo
->frontPitch
;
289 mach64Screen
->backOffset
= serverInfo
->backOffset
;
290 mach64Screen
->backPitch
= serverInfo
->backPitch
;
291 mach64Screen
->depthOffset
= serverInfo
->depthOffset
;
292 mach64Screen
->depthPitch
= serverInfo
->depthPitch
;
294 mach64Screen
->texOffset
[MACH64_CARD_HEAP
] = serverInfo
->textureOffset
;
295 mach64Screen
->texSize
[MACH64_CARD_HEAP
] = serverInfo
->textureSize
;
296 mach64Screen
->logTexGranularity
[MACH64_CARD_HEAP
] =
297 serverInfo
->logTextureGranularity
;
299 if ( mach64Screen
->IsPCI
) {
300 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
- 1;
301 mach64Screen
->firstTexHeap
= MACH64_CARD_HEAP
;
302 mach64Screen
->texOffset
[MACH64_AGP_HEAP
] = 0;
303 mach64Screen
->texSize
[MACH64_AGP_HEAP
] = 0;
304 mach64Screen
->logTexGranularity
[MACH64_AGP_HEAP
] = 0;
306 if (serverInfo
->textureSize
> 0) {
307 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
;
308 mach64Screen
->firstTexHeap
= MACH64_CARD_HEAP
;
310 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
- 1;
311 mach64Screen
->firstTexHeap
= MACH64_AGP_HEAP
;
313 mach64Screen
->texOffset
[MACH64_AGP_HEAP
] = serverInfo
->agpTextureOffset
;
314 mach64Screen
->texSize
[MACH64_AGP_HEAP
] = serverInfo
->agpSize
;
315 mach64Screen
->logTexGranularity
[MACH64_AGP_HEAP
] = serverInfo
->logAgpTextureGranularity
;
318 mach64Screen
->driScreen
= sPriv
;
321 mach64Screen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
322 if ( mach64Screen
->irq
!= 0 ) {
323 mach64Screen
->extensions
[i
++] = &driSwapControlExtension
.base
;
324 mach64Screen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
326 mach64Screen
->extensions
[i
++] = NULL
;
327 sPriv
->extensions
= mach64Screen
->extensions
;
332 /* Destroy the device specific screen private data struct.
335 mach64DestroyScreen( __DRIscreenPrivate
*driScreen
)
337 mach64ScreenRec
*mach64Screen
= (mach64ScreenRec
*) driScreen
->private;
342 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
343 fprintf( stderr
, "%s\n", __FUNCTION__
);
345 if ( !mach64Screen
->IsPCI
) {
346 drmUnmap( (drmAddress
)mach64Screen
->agpTextures
.map
,
347 mach64Screen
->agpTextures
.size
);
350 drmUnmapBufs( mach64Screen
->buffers
);
351 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
, mach64Screen
->mmio
.size
);
353 FREE( mach64Screen
);
354 driScreen
->private = NULL
;
358 /* Create and initialize the Mesa and driver specific pixmap buffer
362 mach64CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
363 __DRIdrawablePrivate
*driDrawPriv
,
364 const __GLcontextModes
*mesaVis
,
367 mach64ScreenPtr screen
= (mach64ScreenPtr
) driScrnPriv
->private;
370 return GL_FALSE
; /* not implemented */
373 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
376 driRenderbuffer
*frontRb
377 = driNewRenderbuffer(GL_RGBA
,
380 screen
->frontOffset
, screen
->frontPitch
,
382 mach64SetSpanFunctions(frontRb
, mesaVis
);
383 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
386 if (mesaVis
->doubleBufferMode
) {
387 driRenderbuffer
*backRb
388 = driNewRenderbuffer(GL_RGBA
,
391 screen
->backOffset
, screen
->backPitch
,
393 mach64SetSpanFunctions(backRb
, mesaVis
);
394 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
397 if (mesaVis
->depthBits
== 16) {
398 driRenderbuffer
*depthRb
399 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
401 screen
->depthOffset
, screen
->depthPitch
,
403 mach64SetSpanFunctions(depthRb
, mesaVis
);
404 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
406 else if (mesaVis
->depthBits
== 24) {
407 /* XXX I don't think 24-bit Z is supported - so this isn't used */
408 driRenderbuffer
*depthRb
409 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
412 screen
->depthOffset
, screen
->depthPitch
,
414 mach64SetSpanFunctions(depthRb
, mesaVis
);
415 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
418 _mesa_add_soft_renderbuffers(fb
,
419 GL_FALSE
, /* color */
420 GL_FALSE
, /* depth */
421 mesaVis
->stencilBits
> 0,
422 mesaVis
->accumRedBits
> 0,
423 GL_FALSE
, /* alpha */
425 driDrawPriv
->driverPrivate
= (void *) fb
;
427 return (driDrawPriv
->driverPrivate
!= NULL
);
433 mach64DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
435 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
439 /* Copy the back color buffer to the front color buffer */
441 mach64SwapBuffers(__DRIdrawablePrivate
*dPriv
)
443 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
444 mach64ContextPtr mmesa
;
446 mmesa
= (mach64ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
448 if (ctx
->Visual
.doubleBufferMode
) {
449 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
450 mach64CopyBuffer( dPriv
);
454 /* XXX this shouldn't be an error but we can't handle it for now */
455 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
460 /* Initialize the driver specific screen private data.
463 mach64InitDriver( __DRIscreenPrivate
*driScreen
)
465 driScreen
->private = (void *) mach64CreateScreen( driScreen
);
467 if ( !driScreen
->private ) {
468 mach64DestroyScreen( driScreen
);
476 static struct __DriverAPIRec mach64API
= {
477 .DestroyScreen
= mach64DestroyScreen
,
478 .CreateContext
= mach64CreateContext
,
479 .DestroyContext
= mach64DestroyContext
,
480 .CreateBuffer
= mach64CreateBuffer
,
481 .DestroyBuffer
= mach64DestroyBuffer
,
482 .SwapBuffers
= mach64SwapBuffers
,
483 .MakeCurrent
= mach64MakeCurrent
,
484 .UnbindContext
= mach64UnbindContext
,
486 .GetMSC
= driGetMSC32
,
487 .GetDrawableMSC
= driDrawableGetMSC32
,
488 .WaitForMSC
= driWaitForMSC32
,
490 .SwapBuffersMSC
= NULL
495 * This is the driver specific part of the createNewScreen entry point.
497 * \todo maybe fold this into intelInitDriver
499 * \return the __GLcontextModes supported by this driver
501 __GLcontextModes
*__driDriverInitScreen(__DRIscreenPrivate
*psp
)
503 static const __DRIversion ddx_expected
= { 6, 4, 0 };
504 static const __DRIversion dri_expected
= { 4, 0, 0 };
505 static const __DRIversion drm_expected
= { 2, 0, 0 };
506 ATIDRIPtr dri_priv
= (ATIDRIPtr
) psp
->pDevPriv
;
508 psp
->DriverAPI
= mach64API
;
509 if ( ! driCheckDriDdxDrmVersions2( "Mach64",
510 &psp
->dri_version
, & dri_expected
,
511 &psp
->ddx_version
, & ddx_expected
,
512 &psp
->drm_version
, & drm_expected
) ) {
516 /* Calling driInitExtensions here, with a NULL context pointer,
517 * does not actually enable the extensions. It just makes sure
518 * that all the dispatch offsets for all the extensions that
519 * *might* be enables are known. This is needed because the
520 * dispatch offsets need to be known when _mesa_context_create is
521 * called, but we can't enable the extensions until we have a
524 * Hello chicken. Hello egg. How are you two today?
526 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
528 if (!mach64InitDriver(psp
))
531 return mach64FillInModes( dri_priv
->cpp
* 8, 16, 0, 1);