1 /* -*- 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"
38 #include "main/context.h"
39 #include "main/imports.h"
40 #include "main/framebuffer.h"
41 #include "main/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 const __DRIconfig
**
73 mach64FillInModes( __DRIscreenPrivate
*psp
,
74 unsigned pixel_bits
, unsigned depth_bits
,
75 unsigned stencil_bits
, GLboolean have_back_buffer
)
77 __DRIconfig
**configs
;
81 unsigned depth_buffer_factor
;
82 unsigned back_buffer_factor
;
85 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
86 * enough to add support. Basically, if a context is created with an
87 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
90 static const GLenum back_buffer_modes
[] = {
91 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
94 uint8_t depth_bits_array
[2];
95 uint8_t stencil_bits_array
[2];
97 depth_bits_array
[0] = depth_bits
;
98 depth_bits_array
[1] = depth_bits
;
100 /* Just like with the accumulation buffer, always provide some modes
101 * with a stencil buffer. It will be a sw fallback, but some apps won't
104 stencil_bits_array
[0] = 0;
105 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
107 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
108 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
110 if (pixel_bits
== 16) {
112 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
116 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
119 configs
= driCreateConfigs(fb_format
, fb_type
,
120 depth_bits_array
, stencil_bits_array
,
121 depth_buffer_factor
, back_buffer_modes
,
123 if (configs
== NULL
) {
124 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n",
129 /* Mark the visual as slow if there are "fake" stencil bits.
131 for (i
= 0; configs
[i
]; i
++) {
132 m
= &configs
[i
]->modes
;
133 if ((m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
)) {
134 m
->visualRating
= GLX_SLOW_CONFIG
;
138 return (const __DRIconfig
**) configs
;
142 /* Create the device specific screen private data struct.
144 static mach64ScreenRec
*
145 mach64CreateScreen( __DRIscreenPrivate
*sPriv
)
147 mach64ScreenPtr mach64Screen
;
148 ATIDRIPtr serverInfo
= (ATIDRIPtr
)sPriv
->pDevPriv
;
151 if (sPriv
->devPrivSize
!= sizeof(ATIDRIRec
)) {
152 fprintf(stderr
,"\nERROR! sizeof(ATIDRIRec) does not match passed size from device driver\n");
156 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
157 fprintf( stderr
, "%s\n", __FUNCTION__
);
159 /* Allocate the private area */
160 mach64Screen
= (mach64ScreenPtr
) CALLOC( sizeof(*mach64Screen
) );
161 if ( !mach64Screen
) return NULL
;
163 /* parse information in __driConfigOptions */
164 driParseOptionInfo (&mach64Screen
->optionCache
,
165 __driConfigOptions
, __driNConfigOptions
);
167 mach64Screen
->IsPCI
= serverInfo
->IsPCI
;
170 drm_mach64_getparam_t gp
;
173 gp
.param
= MACH64_PARAM_IRQ_NR
;
174 gp
.value
= (void *) &mach64Screen
->irq
;
176 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_MACH64_GETPARAM
,
179 fprintf(stderr
, "DRM_MACH64_GETPARAM (MACH64_PARAM_IRQ_NR): %d\n", ret
);
180 FREE( mach64Screen
);
185 mach64Screen
->mmio
.handle
= serverInfo
->regs
;
186 mach64Screen
->mmio
.size
= serverInfo
->regsSize
;
187 if ( drmMap( sPriv
->fd
,
188 mach64Screen
->mmio
.handle
,
189 mach64Screen
->mmio
.size
,
190 (drmAddressPtr
)&mach64Screen
->mmio
.map
) != 0 ) {
191 FREE( mach64Screen
);
195 mach64Screen
->buffers
= drmMapBufs( sPriv
->fd
);
196 if ( !mach64Screen
->buffers
) {
197 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
,
198 mach64Screen
->mmio
.size
);
199 FREE( mach64Screen
);
203 if ( !mach64Screen
->IsPCI
) {
204 mach64Screen
->agpTextures
.handle
= serverInfo
->agp
;
205 mach64Screen
->agpTextures
.size
= serverInfo
->agpSize
;
206 if ( drmMap( sPriv
->fd
,
207 mach64Screen
->agpTextures
.handle
,
208 mach64Screen
->agpTextures
.size
,
209 (drmAddressPtr
)&mach64Screen
->agpTextures
.map
) ) {
210 drmUnmapBufs( mach64Screen
->buffers
);
211 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
, mach64Screen
->mmio
.size
);
212 FREE( mach64Screen
);
217 mach64Screen
->AGPMode
= serverInfo
->AGPMode
;
219 mach64Screen
->chipset
= serverInfo
->chipset
;
220 mach64Screen
->width
= serverInfo
->width
;
221 mach64Screen
->height
= serverInfo
->height
;
222 mach64Screen
->mem
= serverInfo
->mem
;
223 mach64Screen
->cpp
= serverInfo
->cpp
;
225 mach64Screen
->frontOffset
= serverInfo
->frontOffset
;
226 mach64Screen
->frontPitch
= serverInfo
->frontPitch
;
227 mach64Screen
->backOffset
= serverInfo
->backOffset
;
228 mach64Screen
->backPitch
= serverInfo
->backPitch
;
229 mach64Screen
->depthOffset
= serverInfo
->depthOffset
;
230 mach64Screen
->depthPitch
= serverInfo
->depthPitch
;
232 mach64Screen
->texOffset
[MACH64_CARD_HEAP
] = serverInfo
->textureOffset
;
233 mach64Screen
->texSize
[MACH64_CARD_HEAP
] = serverInfo
->textureSize
;
234 mach64Screen
->logTexGranularity
[MACH64_CARD_HEAP
] =
235 serverInfo
->logTextureGranularity
;
237 if ( mach64Screen
->IsPCI
) {
238 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
- 1;
239 mach64Screen
->firstTexHeap
= MACH64_CARD_HEAP
;
240 mach64Screen
->texOffset
[MACH64_AGP_HEAP
] = 0;
241 mach64Screen
->texSize
[MACH64_AGP_HEAP
] = 0;
242 mach64Screen
->logTexGranularity
[MACH64_AGP_HEAP
] = 0;
244 if (serverInfo
->textureSize
> 0) {
245 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
;
246 mach64Screen
->firstTexHeap
= MACH64_CARD_HEAP
;
248 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
- 1;
249 mach64Screen
->firstTexHeap
= MACH64_AGP_HEAP
;
251 mach64Screen
->texOffset
[MACH64_AGP_HEAP
] = serverInfo
->agpTextureOffset
;
252 mach64Screen
->texSize
[MACH64_AGP_HEAP
] = serverInfo
->agpSize
;
253 mach64Screen
->logTexGranularity
[MACH64_AGP_HEAP
] = serverInfo
->logAgpTextureGranularity
;
256 mach64Screen
->driScreen
= sPriv
;
259 mach64Screen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
260 if ( mach64Screen
->irq
!= 0 ) {
261 mach64Screen
->extensions
[i
++] = &driSwapControlExtension
.base
;
262 mach64Screen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
264 mach64Screen
->extensions
[i
++] = NULL
;
265 sPriv
->extensions
= mach64Screen
->extensions
;
270 /* Destroy the device specific screen private data struct.
273 mach64DestroyScreen( __DRIscreenPrivate
*driScreen
)
275 mach64ScreenRec
*mach64Screen
= (mach64ScreenRec
*) driScreen
->private;
280 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
281 fprintf( stderr
, "%s\n", __FUNCTION__
);
283 if ( !mach64Screen
->IsPCI
) {
284 drmUnmap( (drmAddress
)mach64Screen
->agpTextures
.map
,
285 mach64Screen
->agpTextures
.size
);
288 drmUnmapBufs( mach64Screen
->buffers
);
289 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
, mach64Screen
->mmio
.size
);
291 FREE( mach64Screen
);
292 driScreen
->private = NULL
;
296 /* Create and initialize the Mesa and driver specific pixmap buffer
300 mach64CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
301 __DRIdrawablePrivate
*driDrawPriv
,
302 const __GLcontextModes
*mesaVis
,
305 mach64ScreenPtr screen
= (mach64ScreenPtr
) driScrnPriv
->private;
308 return GL_FALSE
; /* not implemented */
311 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
314 driRenderbuffer
*frontRb
315 = driNewRenderbuffer(GL_RGBA
,
318 screen
->frontOffset
, screen
->frontPitch
,
320 mach64SetSpanFunctions(frontRb
, mesaVis
);
321 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
324 if (mesaVis
->doubleBufferMode
) {
325 driRenderbuffer
*backRb
326 = driNewRenderbuffer(GL_RGBA
,
329 screen
->backOffset
, screen
->backPitch
,
331 mach64SetSpanFunctions(backRb
, mesaVis
);
332 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
335 if (mesaVis
->depthBits
== 16) {
336 driRenderbuffer
*depthRb
337 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
339 screen
->depthOffset
, screen
->depthPitch
,
341 mach64SetSpanFunctions(depthRb
, mesaVis
);
342 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
344 else if (mesaVis
->depthBits
== 24) {
345 /* XXX I don't think 24-bit Z is supported - so this isn't used */
346 driRenderbuffer
*depthRb
347 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
350 screen
->depthOffset
, screen
->depthPitch
,
352 mach64SetSpanFunctions(depthRb
, mesaVis
);
353 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
356 _mesa_add_soft_renderbuffers(fb
,
357 GL_FALSE
, /* color */
358 GL_FALSE
, /* depth */
359 mesaVis
->stencilBits
> 0,
360 mesaVis
->accumRedBits
> 0,
361 GL_FALSE
, /* alpha */
363 driDrawPriv
->driverPrivate
= (void *) fb
;
365 return (driDrawPriv
->driverPrivate
!= NULL
);
371 mach64DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
373 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
377 /* Copy the back color buffer to the front color buffer */
379 mach64SwapBuffers(__DRIdrawablePrivate
*dPriv
)
381 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
382 mach64ContextPtr mmesa
;
384 mmesa
= (mach64ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
386 if (ctx
->Visual
.doubleBufferMode
) {
387 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
388 mach64CopyBuffer( dPriv
);
392 /* XXX this shouldn't be an error but we can't handle it for now */
393 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
398 /* Initialize the driver specific screen private data.
401 mach64InitDriver( __DRIscreenPrivate
*driScreen
)
403 driScreen
->private = (void *) mach64CreateScreen( driScreen
);
405 if ( !driScreen
->private ) {
406 mach64DestroyScreen( driScreen
);
414 * This is the driver specific part of the createNewScreen entry point.
416 * \todo maybe fold this into intelInitDriver
418 * \return the __GLcontextModes supported by this driver
420 static const __DRIconfig
**
421 mach64InitScreen(__DRIscreenPrivate
*psp
)
423 static const __DRIversion ddx_expected
= { 6, 4, 0 };
424 static const __DRIversion dri_expected
= { 4, 0, 0 };
425 static const __DRIversion drm_expected
= { 2, 0, 0 };
426 ATIDRIPtr dri_priv
= (ATIDRIPtr
) psp
->pDevPriv
;
428 if ( ! driCheckDriDdxDrmVersions2( "Mach64",
429 &psp
->dri_version
, & dri_expected
,
430 &psp
->ddx_version
, & ddx_expected
,
431 &psp
->drm_version
, & drm_expected
) ) {
435 /* Calling driInitExtensions here, with a NULL context pointer,
436 * does not actually enable the extensions. It just makes sure
437 * that all the dispatch offsets for all the extensions that
438 * *might* be enables are known. This is needed because the
439 * dispatch offsets need to be known when _mesa_context_create is
440 * called, but we can't enable the extensions until we have a
443 * Hello chicken. Hello egg. How are you two today?
445 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
447 if (!mach64InitDriver(psp
))
450 return mach64FillInModes( psp
, dri_priv
->cpp
* 8, 16, 0, 1);
453 const struct __DriverAPIRec driDriverAPI
= {
454 .InitScreen
= mach64InitScreen
,
455 .DestroyScreen
= mach64DestroyScreen
,
456 .CreateContext
= mach64CreateContext
,
457 .DestroyContext
= mach64DestroyContext
,
458 .CreateBuffer
= mach64CreateBuffer
,
459 .DestroyBuffer
= mach64DestroyBuffer
,
460 .SwapBuffers
= mach64SwapBuffers
,
461 .MakeCurrent
= mach64MakeCurrent
,
462 .UnbindContext
= mach64UnbindContext
,
464 .GetDrawableMSC
= driDrawableGetMSC32
,
465 .WaitForMSC
= driWaitForMSC32
,
467 .SwapBuffersMSC
= NULL