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];
96 uint8_t msaa_samples_array
[1];
98 depth_bits_array
[0] = depth_bits
;
99 depth_bits_array
[1] = depth_bits
;
101 /* Just like with the accumulation buffer, always provide some modes
102 * with a stencil buffer. It will be a sw fallback, but some apps won't
105 stencil_bits_array
[0] = 0;
106 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
108 msaa_samples_array
[0] = 0;
110 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
111 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
113 if (pixel_bits
== 16) {
115 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
119 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
122 configs
= driCreateConfigs(fb_format
, fb_type
,
123 depth_bits_array
, stencil_bits_array
,
124 depth_buffer_factor
, back_buffer_modes
,
126 msaa_samples_array
, 1);
127 if (configs
== NULL
) {
128 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n",
133 /* Mark the visual as slow if there are "fake" stencil bits.
135 for (i
= 0; configs
[i
]; i
++) {
136 m
= &configs
[i
]->modes
;
137 if ((m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
)) {
138 m
->visualRating
= GLX_SLOW_CONFIG
;
142 return (const __DRIconfig
**) configs
;
146 /* Create the device specific screen private data struct.
148 static mach64ScreenRec
*
149 mach64CreateScreen( __DRIscreenPrivate
*sPriv
)
151 mach64ScreenPtr mach64Screen
;
152 ATIDRIPtr serverInfo
= (ATIDRIPtr
)sPriv
->pDevPriv
;
155 if (sPriv
->devPrivSize
!= sizeof(ATIDRIRec
)) {
156 fprintf(stderr
,"\nERROR! sizeof(ATIDRIRec) does not match passed size from device driver\n");
160 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
161 fprintf( stderr
, "%s\n", __FUNCTION__
);
163 /* Allocate the private area */
164 mach64Screen
= (mach64ScreenPtr
) CALLOC( sizeof(*mach64Screen
) );
165 if ( !mach64Screen
) return NULL
;
167 /* parse information in __driConfigOptions */
168 driParseOptionInfo (&mach64Screen
->optionCache
,
169 __driConfigOptions
, __driNConfigOptions
);
171 mach64Screen
->IsPCI
= serverInfo
->IsPCI
;
174 drm_mach64_getparam_t gp
;
177 gp
.param
= MACH64_PARAM_IRQ_NR
;
178 gp
.value
= (void *) &mach64Screen
->irq
;
180 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_MACH64_GETPARAM
,
183 fprintf(stderr
, "DRM_MACH64_GETPARAM (MACH64_PARAM_IRQ_NR): %d\n", ret
);
184 FREE( mach64Screen
);
189 mach64Screen
->mmio
.handle
= serverInfo
->regs
;
190 mach64Screen
->mmio
.size
= serverInfo
->regsSize
;
191 if ( drmMap( sPriv
->fd
,
192 mach64Screen
->mmio
.handle
,
193 mach64Screen
->mmio
.size
,
194 (drmAddressPtr
)&mach64Screen
->mmio
.map
) != 0 ) {
195 FREE( mach64Screen
);
199 mach64Screen
->buffers
= drmMapBufs( sPriv
->fd
);
200 if ( !mach64Screen
->buffers
) {
201 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
,
202 mach64Screen
->mmio
.size
);
203 FREE( mach64Screen
);
207 if ( !mach64Screen
->IsPCI
) {
208 mach64Screen
->agpTextures
.handle
= serverInfo
->agp
;
209 mach64Screen
->agpTextures
.size
= serverInfo
->agpSize
;
210 if ( drmMap( sPriv
->fd
,
211 mach64Screen
->agpTextures
.handle
,
212 mach64Screen
->agpTextures
.size
,
213 (drmAddressPtr
)&mach64Screen
->agpTextures
.map
) ) {
214 drmUnmapBufs( mach64Screen
->buffers
);
215 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
, mach64Screen
->mmio
.size
);
216 FREE( mach64Screen
);
221 mach64Screen
->AGPMode
= serverInfo
->AGPMode
;
223 mach64Screen
->chipset
= serverInfo
->chipset
;
224 mach64Screen
->width
= serverInfo
->width
;
225 mach64Screen
->height
= serverInfo
->height
;
226 mach64Screen
->mem
= serverInfo
->mem
;
227 mach64Screen
->cpp
= serverInfo
->cpp
;
229 mach64Screen
->frontOffset
= serverInfo
->frontOffset
;
230 mach64Screen
->frontPitch
= serverInfo
->frontPitch
;
231 mach64Screen
->backOffset
= serverInfo
->backOffset
;
232 mach64Screen
->backPitch
= serverInfo
->backPitch
;
233 mach64Screen
->depthOffset
= serverInfo
->depthOffset
;
234 mach64Screen
->depthPitch
= serverInfo
->depthPitch
;
236 mach64Screen
->texOffset
[MACH64_CARD_HEAP
] = serverInfo
->textureOffset
;
237 mach64Screen
->texSize
[MACH64_CARD_HEAP
] = serverInfo
->textureSize
;
238 mach64Screen
->logTexGranularity
[MACH64_CARD_HEAP
] =
239 serverInfo
->logTextureGranularity
;
241 if ( mach64Screen
->IsPCI
) {
242 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
- 1;
243 mach64Screen
->firstTexHeap
= MACH64_CARD_HEAP
;
244 mach64Screen
->texOffset
[MACH64_AGP_HEAP
] = 0;
245 mach64Screen
->texSize
[MACH64_AGP_HEAP
] = 0;
246 mach64Screen
->logTexGranularity
[MACH64_AGP_HEAP
] = 0;
248 if (serverInfo
->textureSize
> 0) {
249 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
;
250 mach64Screen
->firstTexHeap
= MACH64_CARD_HEAP
;
252 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
- 1;
253 mach64Screen
->firstTexHeap
= MACH64_AGP_HEAP
;
255 mach64Screen
->texOffset
[MACH64_AGP_HEAP
] = serverInfo
->agpTextureOffset
;
256 mach64Screen
->texSize
[MACH64_AGP_HEAP
] = serverInfo
->agpSize
;
257 mach64Screen
->logTexGranularity
[MACH64_AGP_HEAP
] = serverInfo
->logAgpTextureGranularity
;
260 mach64Screen
->driScreen
= sPriv
;
263 mach64Screen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
264 if ( mach64Screen
->irq
!= 0 ) {
265 mach64Screen
->extensions
[i
++] = &driSwapControlExtension
.base
;
266 mach64Screen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
268 mach64Screen
->extensions
[i
++] = NULL
;
269 sPriv
->extensions
= mach64Screen
->extensions
;
274 /* Destroy the device specific screen private data struct.
277 mach64DestroyScreen( __DRIscreenPrivate
*driScreen
)
279 mach64ScreenRec
*mach64Screen
= (mach64ScreenRec
*) driScreen
->private;
284 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
285 fprintf( stderr
, "%s\n", __FUNCTION__
);
287 if ( !mach64Screen
->IsPCI
) {
288 drmUnmap( (drmAddress
)mach64Screen
->agpTextures
.map
,
289 mach64Screen
->agpTextures
.size
);
292 drmUnmapBufs( mach64Screen
->buffers
);
293 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
, mach64Screen
->mmio
.size
);
295 FREE( mach64Screen
);
296 driScreen
->private = NULL
;
300 /* Create and initialize the Mesa and driver specific pixmap buffer
304 mach64CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
305 __DRIdrawablePrivate
*driDrawPriv
,
306 const __GLcontextModes
*mesaVis
,
309 mach64ScreenPtr screen
= (mach64ScreenPtr
) driScrnPriv
->private;
312 return GL_FALSE
; /* not implemented */
315 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
318 driRenderbuffer
*frontRb
319 = driNewRenderbuffer(GL_RGBA
,
322 screen
->frontOffset
, screen
->frontPitch
,
324 mach64SetSpanFunctions(frontRb
, mesaVis
);
325 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
328 if (mesaVis
->doubleBufferMode
) {
329 driRenderbuffer
*backRb
330 = driNewRenderbuffer(GL_RGBA
,
333 screen
->backOffset
, screen
->backPitch
,
335 mach64SetSpanFunctions(backRb
, mesaVis
);
336 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
339 if (mesaVis
->depthBits
== 16) {
340 driRenderbuffer
*depthRb
341 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
343 screen
->depthOffset
, screen
->depthPitch
,
345 mach64SetSpanFunctions(depthRb
, mesaVis
);
346 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
348 else if (mesaVis
->depthBits
== 24) {
349 /* XXX I don't think 24-bit Z is supported - so this isn't used */
350 driRenderbuffer
*depthRb
351 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
354 screen
->depthOffset
, screen
->depthPitch
,
356 mach64SetSpanFunctions(depthRb
, mesaVis
);
357 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
360 _mesa_add_soft_renderbuffers(fb
,
361 GL_FALSE
, /* color */
362 GL_FALSE
, /* depth */
363 mesaVis
->stencilBits
> 0,
364 mesaVis
->accumRedBits
> 0,
365 GL_FALSE
, /* alpha */
367 driDrawPriv
->driverPrivate
= (void *) fb
;
369 return (driDrawPriv
->driverPrivate
!= NULL
);
375 mach64DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
377 _mesa_reference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)), NULL
);
381 /* Copy the back color buffer to the front color buffer */
383 mach64SwapBuffers(__DRIdrawablePrivate
*dPriv
)
385 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
386 mach64ContextPtr mmesa
;
388 mmesa
= (mach64ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
390 if (ctx
->Visual
.doubleBufferMode
) {
391 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
392 mach64CopyBuffer( dPriv
);
396 /* XXX this shouldn't be an error but we can't handle it for now */
397 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
402 /* Initialize the driver specific screen private data.
405 mach64InitDriver( __DRIscreenPrivate
*driScreen
)
407 driScreen
->private = (void *) mach64CreateScreen( driScreen
);
409 if ( !driScreen
->private ) {
410 mach64DestroyScreen( driScreen
);
418 * This is the driver specific part of the createNewScreen entry point.
420 * \todo maybe fold this into intelInitDriver
422 * \return the __GLcontextModes supported by this driver
424 static const __DRIconfig
**
425 mach64InitScreen(__DRIscreenPrivate
*psp
)
427 static const __DRIversion ddx_expected
= { 6, 4, 0 };
428 static const __DRIversion dri_expected
= { 4, 0, 0 };
429 static const __DRIversion drm_expected
= { 2, 0, 0 };
430 ATIDRIPtr dri_priv
= (ATIDRIPtr
) psp
->pDevPriv
;
432 if ( ! driCheckDriDdxDrmVersions2( "Mach64",
433 &psp
->dri_version
, & dri_expected
,
434 &psp
->ddx_version
, & ddx_expected
,
435 &psp
->drm_version
, & drm_expected
) ) {
439 /* Calling driInitExtensions here, with a NULL context pointer,
440 * does not actually enable the extensions. It just makes sure
441 * that all the dispatch offsets for all the extensions that
442 * *might* be enables are known. This is needed because the
443 * dispatch offsets need to be known when _mesa_context_create is
444 * called, but we can't enable the extensions until we have a
447 * Hello chicken. Hello egg. How are you two today?
449 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
451 if (!mach64InitDriver(psp
))
454 return mach64FillInModes( psp
, dri_priv
->cpp
* 8, 16, 0, 1);
457 const struct __DriverAPIRec driDriverAPI
= {
458 .InitScreen
= mach64InitScreen
,
459 .DestroyScreen
= mach64DestroyScreen
,
460 .CreateContext
= mach64CreateContext
,
461 .DestroyContext
= mach64DestroyContext
,
462 .CreateBuffer
= mach64CreateBuffer
,
463 .DestroyBuffer
= mach64DestroyBuffer
,
464 .SwapBuffers
= mach64SwapBuffers
,
465 .MakeCurrent
= mach64MakeCurrent
,
466 .UnbindContext
= mach64UnbindContext
,
468 .GetDrawableMSC
= driDrawableGetMSC32
,
469 .WaitForMSC
= driWaitForMSC32
,
471 .SwapBuffersMSC
= NULL