Redo of removing __driRegisterExtensions(). I accidentally undid the previous check in.
[mesa.git] / src / mesa / drivers / dri / mach64 / mach64_screen.c
1 /* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
2 /*
3 * Copyright 2000 Gareth Hughes
4 * All Rights Reserved.
5 *
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:
12 *
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
15 * Software.
16 *
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.
23 */
24
25 /*
26 * Authors:
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * Jos�Fonseca <j_r_fonseca@yahoo.co.uk>
30 */
31
32 #include "mach64_context.h"
33 #include "mach64_ioctl.h"
34 #include "mach64_tris.h"
35 #include "mach64_vb.h"
36
37 #include "context.h"
38 #include "imports.h"
39
40 #include "utils.h"
41 #include "vblank.h"
42
43 #ifndef _SOLO
44 #include "GL/internal/dri_interface.h"
45 #endif
46
47 /* Mach64 configuration
48 */
49 #include "xmlpool.h"
50
51 const char __driConfigOptions[] =
52 DRI_CONF_BEGIN
53 DRI_CONF_SECTION_PERFORMANCE
54 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
55 DRI_CONF_SECTION_END
56 #if ENABLE_PERF_BOXES
57 DRI_CONF_SECTION_DEBUG
58 DRI_CONF_PERFORMANCE_BOXES(false)
59 DRI_CONF_SECTION_END
60 #endif
61 DRI_CONF_END;
62 #if ENABLE_PERF_BOXES
63 static const GLuint __driNConfigOptions = 2;
64 #else
65 static const GLuint __driNConfigOptions = 1;
66 #endif
67
68 #ifdef USE_NEW_INTERFACE
69 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
70 #endif /* USE_NEW_INTERFACE */
71
72 #ifdef USE_NEW_INTERFACE
73 static __GLcontextModes * fill_in_modes( __GLcontextModes * modes,
74 unsigned pixel_bits,
75 unsigned depth_bits,
76 unsigned stencil_bits,
77 const GLenum * db_modes,
78 unsigned num_db_modes,
79 int visType )
80 {
81 static const uint8_t bits[2][4] = {
82 { 5, 6, 5, 0 },
83 { 8, 8, 8, 0 }
84 };
85
86 static const uint32_t masks[2][4] = {
87 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
88 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }
89 };
90
91 unsigned i;
92 unsigned j;
93 const unsigned index = ((pixel_bits + 15) / 16) - 1;
94
95 for ( i = 0 ; i < num_db_modes ; i++ ) {
96 for ( j = 0 ; j < 2 ; j++ ) {
97
98 modes->redBits = bits[index][0];
99 modes->greenBits = bits[index][1];
100 modes->blueBits = bits[index][2];
101 modes->alphaBits = bits[index][3];
102 modes->redMask = masks[index][0];
103 modes->greenMask = masks[index][1];
104 modes->blueMask = masks[index][2];
105 modes->alphaMask = masks[index][3];
106 modes->rgbBits = modes->redBits + modes->greenBits
107 + modes->blueBits + modes->alphaBits;
108
109 modes->accumRedBits = 16 * j;
110 modes->accumGreenBits = 16 * j;
111 modes->accumBlueBits = 16 * j;
112 modes->accumAlphaBits = 0;
113 modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
114 modes->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
115 modes->stencilBits = stencil_bits;
116 modes->depthBits = depth_bits;
117
118 modes->visualType = visType;
119 modes->renderType = GLX_RGBA_BIT;
120 modes->rgbMode = GL_TRUE;
121
122 if ( db_modes[i] == GLX_NONE ) {
123
124 modes->doubleBufferMode = GL_FALSE;
125 }
126 else {
127 modes->doubleBufferMode = GL_TRUE;
128 modes->swapMethod = db_modes[i];
129 }
130
131 modes = modes->next;
132 }
133 }
134
135 return modes;
136 }
137 #endif /* USE_NEW_INTERFACE */
138
139
140 #ifdef USE_NEW_INTERFACE
141 static __GLcontextModes *
142 mach64FillInModes( unsigned pixel_bits, unsigned depth_bits,
143 unsigned stencil_bits, GLboolean have_back_buffer )
144 {
145 __GLcontextModes * modes;
146 __GLcontextModes * m;
147 unsigned num_modes;
148 unsigned depth_buffer_factor;
149 unsigned back_buffer_factor;
150 unsigned i;
151
152 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
153 * enough to add support. Basically, if a context is created with an
154 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
155 * will never be used.
156 */
157 static const GLenum back_buffer_modes[] = {
158 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
159 };
160
161 int depth_buffer_modes[2][2];
162
163
164 depth_buffer_modes[0][0] = depth_bits;
165 depth_buffer_modes[1][0] = depth_bits;
166
167 /* Just like with the accumulation buffer, always provide some modes
168 * with a stencil buffer. It will be a sw fallback, but some apps won't
169 * care about that.
170 */
171 depth_buffer_modes[0][1] = 0;
172 depth_buffer_modes[1][1] = (stencil_bits == 0) ? 8 : stencil_bits;
173
174 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
175 back_buffer_factor = (have_back_buffer) ? 2 : 1;
176
177 num_modes = depth_buffer_factor * back_buffer_factor * 4;
178
179 modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
180 m = modes;
181 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
182 m = fill_in_modes( m, pixel_bits,
183 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
184 back_buffer_modes, back_buffer_factor,
185 GLX_TRUE_COLOR );
186 }
187
188 for ( i = 0 ; i < depth_buffer_factor ; i++ ) {
189 m = fill_in_modes( m, pixel_bits,
190 depth_buffer_modes[i][0], depth_buffer_modes[i][1],
191 back_buffer_modes, back_buffer_factor,
192 GLX_DIRECT_COLOR );
193 }
194
195 /* Mark the visual as slow if there are "fake" stencil bits.
196 */
197 for ( m = modes ; m != NULL ; m = m->next ) {
198 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ){
199 m->visualRating = GLX_SLOW_CONFIG;
200 }
201 }
202
203 return modes;
204 }
205 #endif /* USE_NEW_INTERFACE */
206
207
208 /* Create the device specific screen private data struct.
209 */
210 static mach64ScreenRec *
211 mach64CreateScreen( __DRIscreenPrivate *sPriv )
212 {
213 mach64ScreenPtr mach64Screen;
214 ATIDRIPtr serverInfo = (ATIDRIPtr)sPriv->pDevPriv;
215
216 if ( MACH64_DEBUG & DEBUG_VERBOSE_DRI )
217 fprintf( stderr, "%s\n", __FUNCTION__ );
218
219 /* Allocate the private area */
220 mach64Screen = (mach64ScreenPtr) CALLOC( sizeof(*mach64Screen) );
221 if ( !mach64Screen ) return NULL;
222
223 /* parse information in __driConfigOptions */
224 driParseOptionInfo (&mach64Screen->optionCache,
225 __driConfigOptions, __driNConfigOptions);
226
227 mach64Screen->IsPCI = serverInfo->IsPCI;
228
229 {
230 drm_mach64_getparam_t gp;
231 int ret;
232
233 gp.param = MACH64_PARAM_IRQ_NR;
234 gp.value = (void *) &mach64Screen->irq;
235
236 ret = drmCommandWriteRead( sPriv->fd, DRM_MACH64_GETPARAM,
237 &gp, sizeof(gp));
238 if (ret) {
239 fprintf(stderr, "DRM_MACH64_GETPARAM (MACH64_PARAM_IRQ_NR): %d\n", ret);
240 FREE( mach64Screen );
241 return NULL;
242 }
243 }
244
245 mach64Screen->mmio.handle = serverInfo->regs;
246 mach64Screen->mmio.size = serverInfo->regsSize;
247 if ( drmMap( sPriv->fd,
248 mach64Screen->mmio.handle,
249 mach64Screen->mmio.size,
250 (drmAddressPtr)&mach64Screen->mmio.map ) != 0 ) {
251 FREE( mach64Screen );
252 return NULL;
253 }
254
255 mach64Screen->buffers = drmMapBufs( sPriv->fd );
256 if ( !mach64Screen->buffers ) {
257 drmUnmap( (drmAddress)mach64Screen->mmio.map,
258 mach64Screen->mmio.size );
259 FREE( mach64Screen );
260 return NULL;
261 }
262
263 if ( !mach64Screen->IsPCI ) {
264 mach64Screen->agpTextures.handle = serverInfo->agp;
265 mach64Screen->agpTextures.size = serverInfo->agpSize;
266 if ( drmMap( sPriv->fd,
267 mach64Screen->agpTextures.handle,
268 mach64Screen->agpTextures.size,
269 (drmAddressPtr)&mach64Screen->agpTextures.map ) ) {
270 drmUnmapBufs( mach64Screen->buffers );
271 drmUnmap( (drmAddress)mach64Screen->mmio.map, mach64Screen->mmio.size );
272 FREE( mach64Screen );
273 return NULL;
274 }
275 }
276
277 mach64Screen->AGPMode = serverInfo->AGPMode;
278
279 mach64Screen->chipset = serverInfo->chipset;
280 mach64Screen->width = serverInfo->width;
281 mach64Screen->height = serverInfo->height;
282 mach64Screen->mem = serverInfo->mem;
283 mach64Screen->cpp = serverInfo->cpp;
284
285 mach64Screen->frontOffset = serverInfo->frontOffset;
286 mach64Screen->frontPitch = serverInfo->frontPitch;
287 mach64Screen->backOffset = serverInfo->backOffset;
288 mach64Screen->backPitch = serverInfo->backPitch;
289 mach64Screen->depthOffset = serverInfo->depthOffset;
290 mach64Screen->depthPitch = serverInfo->depthPitch;
291
292 mach64Screen->texOffset[MACH64_CARD_HEAP] = serverInfo->textureOffset;
293 mach64Screen->texSize[MACH64_CARD_HEAP] = serverInfo->textureSize;
294 mach64Screen->logTexGranularity[MACH64_CARD_HEAP] =
295 serverInfo->logTextureGranularity;
296
297 if ( mach64Screen->IsPCI ) {
298 mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS - 1;
299 mach64Screen->firstTexHeap = MACH64_CARD_HEAP;
300 mach64Screen->texOffset[MACH64_AGP_HEAP] = 0;
301 mach64Screen->texSize[MACH64_AGP_HEAP] = 0;
302 mach64Screen->logTexGranularity[MACH64_AGP_HEAP] = 0;
303 } else {
304 if (mach64Screen->texSize[MACH64_CARD_HEAP] > 0) {
305 mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS;
306 mach64Screen->firstTexHeap = MACH64_CARD_HEAP;
307 } else {
308 mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS - 1;
309 mach64Screen->firstTexHeap = MACH64_AGP_HEAP;
310 }
311 mach64Screen->texOffset[MACH64_AGP_HEAP] = serverInfo->agpTextureOffset;
312 mach64Screen->texSize[MACH64_AGP_HEAP] = serverInfo->agpSize;
313 mach64Screen->logTexGranularity[MACH64_AGP_HEAP] = serverInfo->logAgpTextureGranularity;
314 }
315
316 mach64Screen->driScreen = sPriv;
317 #ifndef _SOLO
318 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
319 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
320 (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
321 void * const psc = sPriv->psc->screenConfigs;
322
323 if ( glx_enable_extension != NULL ) {
324 if ( mach64Screen->irq != 0 ) {
325 (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
326 (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
327 (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
328 }
329
330 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
331 }
332 }
333 #endif
334 return mach64Screen;
335 }
336
337 /* Destroy the device specific screen private data struct.
338 */
339 static void
340 mach64DestroyScreen( __DRIscreenPrivate *driScreen )
341 {
342 mach64ScreenRec *mach64Screen = (mach64ScreenRec *) driScreen->private;
343
344 if ( !mach64Screen )
345 return;
346
347 if ( MACH64_DEBUG & DEBUG_VERBOSE_DRI )
348 fprintf( stderr, "%s\n", __FUNCTION__ );
349
350 if ( !mach64Screen->IsPCI ) {
351 drmUnmap( (drmAddress)mach64Screen->agpTextures.map,
352 mach64Screen->agpTextures.size );
353 }
354
355 drmUnmapBufs( mach64Screen->buffers );
356 drmUnmap( (drmAddress)mach64Screen->mmio.map, mach64Screen->mmio.size );
357
358 FREE( mach64Screen );
359 driScreen->private = NULL;
360 }
361
362 /* Create and initialize the Mesa and driver specific pixmap buffer
363 * data.
364 */
365 static GLboolean
366 mach64CreateBuffer( __DRIscreenPrivate *driScrnPriv,
367 __DRIdrawablePrivate *driDrawPriv,
368 const __GLcontextModes *mesaVis,
369 GLboolean isPixmap )
370 {
371 if (isPixmap) {
372 return GL_FALSE; /* not implemented */
373 }
374 else {
375 driDrawPriv->driverPrivate = (void *)
376 _mesa_create_framebuffer( mesaVis,
377 GL_FALSE, /* software depth buffer? */
378 mesaVis->stencilBits > 0,
379 mesaVis->accumRedBits > 0,
380 mesaVis->alphaBits > 0 );
381 return (driDrawPriv->driverPrivate != NULL);
382 }
383 }
384
385
386 static void
387 mach64DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
388 {
389 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
390 }
391
392
393 /* Copy the back color buffer to the front color buffer */
394 static void
395 mach64SwapBuffers(__DRIdrawablePrivate *dPriv)
396 {
397 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
398 mach64ContextPtr mmesa;
399 GLcontext *ctx;
400 mmesa = (mach64ContextPtr) dPriv->driContextPriv->driverPrivate;
401 ctx = mmesa->glCtx;
402 if (ctx->Visual.doubleBufferMode) {
403 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
404 mach64CopyBuffer( dPriv );
405 }
406 }
407 else {
408 /* XXX this shouldn't be an error but we can't handle it for now */
409 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
410 }
411 }
412
413
414 /* Initialize the driver specific screen private data.
415 */
416 static GLboolean
417 mach64InitDriver( __DRIscreenPrivate *driScreen )
418 {
419 driScreen->private = (void *) mach64CreateScreen( driScreen );
420
421 if ( !driScreen->private ) {
422 mach64DestroyScreen( driScreen );
423 return GL_FALSE;
424 }
425
426 return GL_TRUE;
427 }
428
429
430 static struct __DriverAPIRec mach64API = {
431 .InitDriver = mach64InitDriver,
432 .DestroyScreen = mach64DestroyScreen,
433 .CreateContext = mach64CreateContext,
434 .DestroyContext = mach64DestroyContext,
435 .CreateBuffer = mach64CreateBuffer,
436 .DestroyBuffer = mach64DestroyBuffer,
437 .SwapBuffers = mach64SwapBuffers,
438 .MakeCurrent = mach64MakeCurrent,
439 .UnbindContext = mach64UnbindContext,
440 .GetSwapInfo = NULL,
441 .GetMSC = driGetMSC32,
442 .WaitForMSC = driWaitForMSC32,
443 .WaitForSBC = NULL,
444 .SwapBuffersMSC = NULL
445 };
446
447
448 /*
449 * This is the bootstrap function for the driver.
450 * The __driCreateScreen name is the symbol that libGL.so fetches.
451 * Return: pointer to a __DRIscreenPrivate.
452 */
453 #if !defined(DRI_NEW_INTERFACE_ONLY)
454 #ifndef _SOLO
455 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
456 int numConfigs, __GLXvisualConfig *config)
457 {
458 __DRIscreenPrivate *psp;
459 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &mach64API);
460 return (void *) psp;
461 }
462 #else
463 void *__driCreateScreen(struct DRIDriverRec *driver,
464 struct DRIDriverContextRec *driverContext)
465 {
466 __DRIscreenPrivate *psp;
467 psp = __driUtilCreateScreen(driver, driverContext, &mach64API);
468 return (void *) psp;
469 }
470 #endif
471 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
472
473 /**
474 * This is the bootstrap function for the driver. libGL supplies all of the
475 * requisite information about the system, and the driver initializes itself.
476 * This routine also fills in the linked list pointed to by \c driver_modes
477 * with the \c __GLcontextModes that the driver can support for windows or
478 * pbuffers.
479 *
480 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
481 * failure.
482 */
483 #ifdef USE_NEW_INTERFACE
484 void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
485 const __GLcontextModes * modes,
486 const __DRIversion * ddx_version,
487 const __DRIversion * dri_version,
488 const __DRIversion * drm_version,
489 const __DRIframebuffer * frame_buffer,
490 drmAddress pSAREA, int fd,
491 int internal_api_version,
492 __GLcontextModes ** driver_modes )
493
494 {
495 __DRIscreenPrivate *psp;
496 static const __DRIversion ddx_expected = { 4, 0, 0 };
497 static const __DRIversion dri_expected = { 6, 4, 0 };
498 static const __DRIversion drm_expected = { 1, 0, 0 };
499
500 if ( ! driCheckDriDdxDrmVersions2( "Mach64",
501 dri_version, & dri_expected,
502 ddx_version, & ddx_expected,
503 drm_version, & drm_expected ) ) {
504 return NULL;
505 }
506
507 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
508 ddx_version, dri_version, drm_version,
509 frame_buffer, pSAREA, fd,
510 internal_api_version, &mach64API);
511 if ( psp != NULL ) {
512 create_context_modes = (PFNGLXCREATECONTEXTMODES)
513 glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
514 if ( create_context_modes != NULL ) {
515 ATIDRIPtr dri_priv = (ATIDRIPtr) psp->pDevPriv;
516 *driver_modes = mach64FillInModes( dri_priv->cpp * 8,
517 16,
518 0,
519 1);
520 }
521 }
522
523 return (void *) psp;
524 }
525 #endif /* USE_NEW_INTERFACE */