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 static const __DRIconfig
**
71 mach64FillInModes( __DRIscreenPrivate
*psp
,
72 unsigned pixel_bits
, unsigned depth_bits
,
73 unsigned stencil_bits
, GLboolean have_back_buffer
)
75 __DRIconfig
**configs
;
79 unsigned depth_buffer_factor
;
80 unsigned back_buffer_factor
;
83 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
84 * enough to add support. Basically, if a context is created with an
85 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
88 static const GLenum back_buffer_modes
[] = {
89 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
/*, GLX_SWAP_COPY_OML */
92 uint8_t depth_bits_array
[2];
93 uint8_t stencil_bits_array
[2];
94 uint8_t msaa_samples_array
[1];
96 depth_bits_array
[0] = depth_bits
;
97 depth_bits_array
[1] = depth_bits
;
99 /* Just like with the accumulation buffer, always provide some modes
100 * with a stencil buffer. It will be a sw fallback, but some apps won't
103 stencil_bits_array
[0] = 0;
104 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
106 msaa_samples_array
[0] = 0;
108 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
109 back_buffer_factor
= (have_back_buffer
) ? 2 : 1;
111 if (pixel_bits
== 16) {
113 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
117 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
120 configs
= driCreateConfigs(fb_format
, fb_type
,
121 depth_bits_array
, stencil_bits_array
,
122 depth_buffer_factor
, back_buffer_modes
,
124 msaa_samples_array
, 1);
125 if (configs
== NULL
) {
126 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n",
131 /* Mark the visual as slow if there are "fake" stencil bits.
133 for (i
= 0; configs
[i
]; i
++) {
134 m
= &configs
[i
]->modes
;
135 if ((m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
)) {
136 m
->visualRating
= GLX_SLOW_CONFIG
;
140 return (const __DRIconfig
**) configs
;
144 /* Create the device specific screen private data struct.
146 static mach64ScreenRec
*
147 mach64CreateScreen( __DRIscreenPrivate
*sPriv
)
149 mach64ScreenPtr mach64Screen
;
150 ATIDRIPtr serverInfo
= (ATIDRIPtr
)sPriv
->pDevPriv
;
153 if (sPriv
->devPrivSize
!= sizeof(ATIDRIRec
)) {
154 fprintf(stderr
,"\nERROR! sizeof(ATIDRIRec) does not match passed size from device driver\n");
158 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
159 fprintf( stderr
, "%s\n", __FUNCTION__
);
161 /* Allocate the private area */
162 mach64Screen
= (mach64ScreenPtr
) CALLOC( sizeof(*mach64Screen
) );
163 if ( !mach64Screen
) return NULL
;
165 /* parse information in __driConfigOptions */
166 driParseOptionInfo (&mach64Screen
->optionCache
,
167 __driConfigOptions
, __driNConfigOptions
);
169 mach64Screen
->IsPCI
= serverInfo
->IsPCI
;
172 drm_mach64_getparam_t gp
;
175 gp
.param
= MACH64_PARAM_IRQ_NR
;
176 gp
.value
= (void *) &mach64Screen
->irq
;
178 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_MACH64_GETPARAM
,
181 fprintf(stderr
, "DRM_MACH64_GETPARAM (MACH64_PARAM_IRQ_NR): %d\n", ret
);
182 FREE( mach64Screen
);
187 mach64Screen
->mmio
.handle
= serverInfo
->regs
;
188 mach64Screen
->mmio
.size
= serverInfo
->regsSize
;
189 if ( drmMap( sPriv
->fd
,
190 mach64Screen
->mmio
.handle
,
191 mach64Screen
->mmio
.size
,
192 (drmAddressPtr
)&mach64Screen
->mmio
.map
) != 0 ) {
193 FREE( mach64Screen
);
197 mach64Screen
->buffers
= drmMapBufs( sPriv
->fd
);
198 if ( !mach64Screen
->buffers
) {
199 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
,
200 mach64Screen
->mmio
.size
);
201 FREE( mach64Screen
);
205 if ( !mach64Screen
->IsPCI
) {
206 mach64Screen
->agpTextures
.handle
= serverInfo
->agp
;
207 mach64Screen
->agpTextures
.size
= serverInfo
->agpSize
;
208 if ( drmMap( sPriv
->fd
,
209 mach64Screen
->agpTextures
.handle
,
210 mach64Screen
->agpTextures
.size
,
211 (drmAddressPtr
)&mach64Screen
->agpTextures
.map
) ) {
212 drmUnmapBufs( mach64Screen
->buffers
);
213 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
, mach64Screen
->mmio
.size
);
214 FREE( mach64Screen
);
219 mach64Screen
->AGPMode
= serverInfo
->AGPMode
;
221 mach64Screen
->chipset
= serverInfo
->chipset
;
222 mach64Screen
->width
= serverInfo
->width
;
223 mach64Screen
->height
= serverInfo
->height
;
224 mach64Screen
->mem
= serverInfo
->mem
;
225 mach64Screen
->cpp
= serverInfo
->cpp
;
227 mach64Screen
->frontOffset
= serverInfo
->frontOffset
;
228 mach64Screen
->frontPitch
= serverInfo
->frontPitch
;
229 mach64Screen
->backOffset
= serverInfo
->backOffset
;
230 mach64Screen
->backPitch
= serverInfo
->backPitch
;
231 mach64Screen
->depthOffset
= serverInfo
->depthOffset
;
232 mach64Screen
->depthPitch
= serverInfo
->depthPitch
;
234 mach64Screen
->texOffset
[MACH64_CARD_HEAP
] = serverInfo
->textureOffset
;
235 mach64Screen
->texSize
[MACH64_CARD_HEAP
] = serverInfo
->textureSize
;
236 mach64Screen
->logTexGranularity
[MACH64_CARD_HEAP
] =
237 serverInfo
->logTextureGranularity
;
239 if ( mach64Screen
->IsPCI
) {
240 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
- 1;
241 mach64Screen
->firstTexHeap
= MACH64_CARD_HEAP
;
242 mach64Screen
->texOffset
[MACH64_AGP_HEAP
] = 0;
243 mach64Screen
->texSize
[MACH64_AGP_HEAP
] = 0;
244 mach64Screen
->logTexGranularity
[MACH64_AGP_HEAP
] = 0;
246 if (serverInfo
->textureSize
> 0) {
247 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
;
248 mach64Screen
->firstTexHeap
= MACH64_CARD_HEAP
;
250 mach64Screen
->numTexHeaps
= MACH64_NR_TEX_HEAPS
- 1;
251 mach64Screen
->firstTexHeap
= MACH64_AGP_HEAP
;
253 mach64Screen
->texOffset
[MACH64_AGP_HEAP
] = serverInfo
->agpTextureOffset
;
254 mach64Screen
->texSize
[MACH64_AGP_HEAP
] = serverInfo
->agpSize
;
255 mach64Screen
->logTexGranularity
[MACH64_AGP_HEAP
] = serverInfo
->logAgpTextureGranularity
;
258 mach64Screen
->driScreen
= sPriv
;
261 mach64Screen
->extensions
[i
++] = &driFrameTrackingExtension
.base
;
262 if ( mach64Screen
->irq
!= 0 ) {
263 mach64Screen
->extensions
[i
++] = &driSwapControlExtension
.base
;
264 mach64Screen
->extensions
[i
++] = &driMediaStreamCounterExtension
.base
;
266 mach64Screen
->extensions
[i
++] = NULL
;
267 sPriv
->extensions
= mach64Screen
->extensions
;
272 /* Destroy the device specific screen private data struct.
275 mach64DestroyScreen( __DRIscreenPrivate
*driScreen
)
277 mach64ScreenRec
*mach64Screen
= (mach64ScreenRec
*) driScreen
->private;
282 if ( MACH64_DEBUG
& DEBUG_VERBOSE_DRI
)
283 fprintf( stderr
, "%s\n", __FUNCTION__
);
285 if ( !mach64Screen
->IsPCI
) {
286 drmUnmap( (drmAddress
)mach64Screen
->agpTextures
.map
,
287 mach64Screen
->agpTextures
.size
);
290 drmUnmapBufs( mach64Screen
->buffers
);
291 drmUnmap( (drmAddress
)mach64Screen
->mmio
.map
, mach64Screen
->mmio
.size
);
293 FREE( mach64Screen
);
294 driScreen
->private = NULL
;
298 /* Create and initialize the Mesa and driver specific pixmap buffer
302 mach64CreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
303 __DRIdrawablePrivate
*driDrawPriv
,
304 const __GLcontextModes
*mesaVis
,
307 mach64ScreenPtr screen
= (mach64ScreenPtr
) driScrnPriv
->private;
310 return GL_FALSE
; /* not implemented */
313 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
316 driRenderbuffer
*frontRb
317 = driNewRenderbuffer(GL_RGBA
,
320 screen
->frontOffset
, screen
->frontPitch
,
322 mach64SetSpanFunctions(frontRb
, mesaVis
);
323 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
326 if (mesaVis
->doubleBufferMode
) {
327 driRenderbuffer
*backRb
328 = driNewRenderbuffer(GL_RGBA
,
331 screen
->backOffset
, screen
->backPitch
,
333 mach64SetSpanFunctions(backRb
, mesaVis
);
334 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
337 if (mesaVis
->depthBits
== 16) {
338 driRenderbuffer
*depthRb
339 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
341 screen
->depthOffset
, screen
->depthPitch
,
343 mach64SetSpanFunctions(depthRb
, mesaVis
);
344 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
346 else if (mesaVis
->depthBits
== 24) {
347 /* XXX I don't think 24-bit Z is supported - so this isn't used */
348 driRenderbuffer
*depthRb
349 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
352 screen
->depthOffset
, screen
->depthPitch
,
354 mach64SetSpanFunctions(depthRb
, mesaVis
);
355 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
358 _mesa_add_soft_renderbuffers(fb
,
359 GL_FALSE
, /* color */
360 GL_FALSE
, /* depth */
361 mesaVis
->stencilBits
> 0,
362 mesaVis
->accumRedBits
> 0,
363 GL_FALSE
, /* alpha */
365 driDrawPriv
->driverPrivate
= (void *) fb
;
367 return (driDrawPriv
->driverPrivate
!= NULL
);
373 mach64DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
375 _mesa_reference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)), NULL
);
379 /* Copy the back color buffer to the front color buffer */
381 mach64SwapBuffers(__DRIdrawablePrivate
*dPriv
)
383 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
384 mach64ContextPtr mmesa
;
386 mmesa
= (mach64ContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
388 if (ctx
->Visual
.doubleBufferMode
) {
389 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
390 mach64CopyBuffer( dPriv
);
394 /* XXX this shouldn't be an error but we can't handle it for now */
395 _mesa_problem(NULL
, "%s: drawable has no context!", __FUNCTION__
);
400 /* Initialize the driver specific screen private data.
403 mach64InitDriver( __DRIscreenPrivate
*driScreen
)
405 driScreen
->private = (void *) mach64CreateScreen( driScreen
);
407 if ( !driScreen
->private ) {
408 mach64DestroyScreen( driScreen
);
416 * This is the driver specific part of the createNewScreen entry point.
418 * \todo maybe fold this into intelInitDriver
420 * \return the __GLcontextModes supported by this driver
422 static const __DRIconfig
**
423 mach64InitScreen(__DRIscreenPrivate
*psp
)
425 static const __DRIversion ddx_expected
= { 6, 4, 0 };
426 static const __DRIversion dri_expected
= { 4, 0, 0 };
427 static const __DRIversion drm_expected
= { 2, 0, 0 };
428 ATIDRIPtr dri_priv
= (ATIDRIPtr
) psp
->pDevPriv
;
430 if ( ! driCheckDriDdxDrmVersions2( "Mach64",
431 &psp
->dri_version
, & dri_expected
,
432 &psp
->ddx_version
, & ddx_expected
,
433 &psp
->drm_version
, & drm_expected
) ) {
437 if (!mach64InitDriver(psp
))
440 return mach64FillInModes( psp
, dri_priv
->cpp
* 8, 16, 0, 1);
443 const struct __DriverAPIRec driDriverAPI
= {
444 .InitScreen
= mach64InitScreen
,
445 .DestroyScreen
= mach64DestroyScreen
,
446 .CreateContext
= mach64CreateContext
,
447 .DestroyContext
= mach64DestroyContext
,
448 .CreateBuffer
= mach64CreateBuffer
,
449 .DestroyBuffer
= mach64DestroyBuffer
,
450 .SwapBuffers
= mach64SwapBuffers
,
451 .MakeCurrent
= mach64MakeCurrent
,
452 .UnbindContext
= mach64UnbindContext
,
454 .GetDrawableMSC
= driDrawableGetMSC32
,
455 .WaitForMSC
= driWaitForMSC32
,
457 .SwapBuffersMSC
= NULL