Merge branch 'nouveau-import'
[mesa.git] / src / mesa / drivers / dri / r128 / r128_screen.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_screen.c,v 1.9 2003/03/26 20:43:49 tsi Exp $ */
2 /**************************************************************************
3
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
5 Cedar Park, Texas.
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Gareth Hughes <gareth@valinux.com>
32 * Kevin E. Martin <martin@valinux.com>
33 *
34 */
35
36 #include "r128_dri.h"
37
38 #include "r128_context.h"
39 #include "r128_ioctl.h"
40 #include "r128_span.h"
41 #include "r128_tris.h"
42
43 #include "context.h"
44 #include "imports.h"
45 #include "framebuffer.h"
46 #include "renderbuffer.h"
47
48 #include "utils.h"
49 #include "vblank.h"
50
51 #include "GL/internal/dri_interface.h"
52
53 /* R128 configuration
54 */
55 #include "xmlpool.h"
56
57 PUBLIC const char __driConfigOptions[] =
58 DRI_CONF_BEGIN
59 DRI_CONF_SECTION_PERFORMANCE
60 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
61 DRI_CONF_SECTION_END
62 DRI_CONF_SECTION_QUALITY
63 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
64 DRI_CONF_SECTION_END
65 DRI_CONF_SECTION_DEBUG
66 DRI_CONF_NO_RAST(false)
67 #if ENABLE_PERF_BOXES
68 DRI_CONF_PERFORMANCE_BOXES(false)
69 #endif
70 DRI_CONF_SECTION_END
71 DRI_CONF_END;
72 #if ENABLE_PERF_BOXES
73 static const GLuint __driNConfigOptions = 4;
74 #else
75 static const GLuint __driNConfigOptions = 3;
76 #endif
77
78 extern const struct dri_extension card_extensions[];
79
80 #if 1
81 /* Including xf86PciInfo.h introduces a bunch of errors...
82 */
83 #define PCI_CHIP_RAGE128LE 0x4C45
84 #define PCI_CHIP_RAGE128LF 0x4C46
85 #define PCI_CHIP_RAGE128PF 0x5046
86 #define PCI_CHIP_RAGE128PR 0x5052
87 #define PCI_CHIP_RAGE128RE 0x5245
88 #define PCI_CHIP_RAGE128RF 0x5246
89 #define PCI_CHIP_RAGE128RK 0x524B
90 #define PCI_CHIP_RAGE128RL 0x524C
91 #endif
92
93
94 /* Create the device specific screen private data struct.
95 */
96 static r128ScreenPtr
97 r128CreateScreen( __DRIscreenPrivate *sPriv )
98 {
99 r128ScreenPtr r128Screen;
100 R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
101 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
102 (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension"));
103 void * const psc = sPriv->psc->screenConfigs;
104
105 if (sPriv->devPrivSize != sizeof(R128DRIRec)) {
106 fprintf(stderr,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
107 return GL_FALSE;
108 }
109
110 /* Allocate the private area */
111 r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
112 if ( !r128Screen ) return NULL;
113
114 /* parse information in __driConfigOptions */
115 driParseOptionInfo (&r128Screen->optionCache,
116 __driConfigOptions, __driNConfigOptions);
117
118 /* This is first since which regions we map depends on whether or
119 * not we are using a PCI card.
120 */
121 r128Screen->IsPCI = r128DRIPriv->IsPCI;
122 r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
123
124 if (sPriv->drmMinor >= 3) {
125 drm_r128_getparam_t gp;
126 int ret;
127
128 gp.param = R128_PARAM_IRQ_NR;
129 gp.value = &r128Screen->irq;
130
131 ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
132 &gp, sizeof(gp));
133 if (ret) {
134 fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
135 FREE( r128Screen );
136 return NULL;
137 }
138 }
139
140 r128Screen->mmio.handle = r128DRIPriv->registerHandle;
141 r128Screen->mmio.size = r128DRIPriv->registerSize;
142 if ( drmMap( sPriv->fd,
143 r128Screen->mmio.handle,
144 r128Screen->mmio.size,
145 (drmAddressPtr)&r128Screen->mmio.map ) ) {
146 FREE( r128Screen );
147 return NULL;
148 }
149
150 r128Screen->buffers = drmMapBufs( sPriv->fd );
151 if ( !r128Screen->buffers ) {
152 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
153 FREE( r128Screen );
154 return NULL;
155 }
156
157 if ( !r128Screen->IsPCI ) {
158 r128Screen->agpTextures.handle = r128DRIPriv->agpTexHandle;
159 r128Screen->agpTextures.size = r128DRIPriv->agpTexMapSize;
160 if ( drmMap( sPriv->fd,
161 r128Screen->agpTextures.handle,
162 r128Screen->agpTextures.size,
163 (drmAddressPtr)&r128Screen->agpTextures.map ) ) {
164 drmUnmapBufs( r128Screen->buffers );
165 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
166 FREE( r128Screen );
167 return NULL;
168 }
169 }
170
171 switch ( r128DRIPriv->deviceID ) {
172 case PCI_CHIP_RAGE128RE:
173 case PCI_CHIP_RAGE128RF:
174 case PCI_CHIP_RAGE128RK:
175 case PCI_CHIP_RAGE128RL:
176 r128Screen->chipset = R128_CARD_TYPE_R128;
177 break;
178 case PCI_CHIP_RAGE128PF:
179 r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
180 break;
181 case PCI_CHIP_RAGE128LE:
182 case PCI_CHIP_RAGE128LF:
183 r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
184 break;
185 default:
186 r128Screen->chipset = R128_CARD_TYPE_R128;
187 break;
188 }
189
190 r128Screen->cpp = r128DRIPriv->bpp / 8;
191 r128Screen->AGPMode = r128DRIPriv->AGPMode;
192
193 r128Screen->frontOffset = r128DRIPriv->frontOffset;
194 r128Screen->frontPitch = r128DRIPriv->frontPitch;
195 r128Screen->backOffset = r128DRIPriv->backOffset;
196 r128Screen->backPitch = r128DRIPriv->backPitch;
197 r128Screen->depthOffset = r128DRIPriv->depthOffset;
198 r128Screen->depthPitch = r128DRIPriv->depthPitch;
199 r128Screen->spanOffset = r128DRIPriv->spanOffset;
200
201 if ( r128DRIPriv->textureSize == 0 ) {
202 r128Screen->texOffset[R128_LOCAL_TEX_HEAP] =
203 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
204 r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
205 r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] =
206 r128DRIPriv->log2AGPTexGran;
207 } else {
208 r128Screen->texOffset[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureOffset;
209 r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureSize;
210 r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] = r128DRIPriv->log2TexGran;
211 }
212
213 if ( !r128Screen->agpTextures.map || r128DRIPriv->textureSize == 0 ) {
214 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
215 r128Screen->texOffset[R128_AGP_TEX_HEAP] = 0;
216 r128Screen->texSize[R128_AGP_TEX_HEAP] = 0;
217 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] = 0;
218 } else {
219 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
220 r128Screen->texOffset[R128_AGP_TEX_HEAP] =
221 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
222 r128Screen->texSize[R128_AGP_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
223 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] =
224 r128DRIPriv->log2AGPTexGran;
225 }
226
227 r128Screen->driScreen = sPriv;
228
229 if ( glx_enable_extension != NULL ) {
230 if ( r128Screen->irq != 0 ) {
231 (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
232 (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
233 (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
234 }
235
236 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
237 }
238
239 return r128Screen;
240 }
241
242 /* Destroy the device specific screen private data struct.
243 */
244 static void
245 r128DestroyScreen( __DRIscreenPrivate *sPriv )
246 {
247 r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
248
249 if ( !r128Screen )
250 return;
251
252 if ( !r128Screen->IsPCI ) {
253 drmUnmap( (drmAddress)r128Screen->agpTextures.map,
254 r128Screen->agpTextures.size );
255 }
256 drmUnmapBufs( r128Screen->buffers );
257 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
258
259 /* free all option information */
260 driDestroyOptionInfo (&r128Screen->optionCache);
261
262 FREE( r128Screen );
263 sPriv->private = NULL;
264 }
265
266
267 /* Create and initialize the Mesa and driver specific pixmap buffer
268 * data.
269 */
270 static GLboolean
271 r128CreateBuffer( __DRIscreenPrivate *driScrnPriv,
272 __DRIdrawablePrivate *driDrawPriv,
273 const __GLcontextModes *mesaVis,
274 GLboolean isPixmap )
275 {
276 r128ScreenPtr screen = (r128ScreenPtr) driScrnPriv->private;
277
278 if (isPixmap) {
279 return GL_FALSE; /* not implemented */
280 }
281 else {
282 const GLboolean swDepth = GL_FALSE;
283 const GLboolean swAlpha = GL_FALSE;
284 const GLboolean swAccum = mesaVis->accumRedBits > 0;
285 const GLboolean swStencil = mesaVis->stencilBits > 0 &&
286 mesaVis->depthBits != 24;
287 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
288
289 {
290 driRenderbuffer *frontRb
291 = driNewRenderbuffer(GL_RGBA,
292 NULL,
293 screen->cpp,
294 screen->frontOffset, screen->frontPitch,
295 driDrawPriv);
296 r128SetSpanFunctions(frontRb, mesaVis);
297 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
298 }
299
300 if (mesaVis->doubleBufferMode) {
301 driRenderbuffer *backRb
302 = driNewRenderbuffer(GL_RGBA,
303 NULL,
304 screen->cpp,
305 screen->backOffset, screen->backPitch,
306 driDrawPriv);
307 r128SetSpanFunctions(backRb, mesaVis);
308 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
309 }
310
311 if (mesaVis->depthBits == 16) {
312 driRenderbuffer *depthRb
313 = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
314 NULL,
315 screen->cpp,
316 screen->depthOffset, screen->depthPitch,
317 driDrawPriv);
318 r128SetSpanFunctions(depthRb, mesaVis);
319 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
320 }
321 else if (mesaVis->depthBits == 24) {
322 driRenderbuffer *depthRb
323 = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
324 NULL,
325 screen->cpp,
326 screen->depthOffset, screen->depthPitch,
327 driDrawPriv);
328 r128SetSpanFunctions(depthRb, mesaVis);
329 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
330 }
331
332 if (mesaVis->stencilBits > 0 && !swStencil) {
333 driRenderbuffer *stencilRb
334 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
335 NULL,
336 screen->cpp,
337 screen->depthOffset, screen->depthPitch,
338 driDrawPriv);
339 r128SetSpanFunctions(stencilRb, mesaVis);
340 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
341 }
342
343 _mesa_add_soft_renderbuffers(fb,
344 GL_FALSE, /* color */
345 swDepth,
346 swStencil,
347 swAccum,
348 swAlpha,
349 GL_FALSE /* aux */);
350 driDrawPriv->driverPrivate = (void *) fb;
351
352 return (driDrawPriv->driverPrivate != NULL);
353 }
354 }
355
356
357 static void
358 r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
359 {
360 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
361 }
362
363
364 /* Copy the back color buffer to the front color buffer */
365 static void
366 r128SwapBuffers(__DRIdrawablePrivate *dPriv)
367 {
368 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
369 r128ContextPtr rmesa;
370 GLcontext *ctx;
371 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
372 ctx = rmesa->glCtx;
373 if (ctx->Visual.doubleBufferMode) {
374 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
375 if ( rmesa->doPageFlip ) {
376 r128PageFlip( dPriv );
377 }
378 else {
379 r128CopyBuffer( dPriv );
380 }
381 }
382 }
383 else {
384 /* XXX this shouldn't be an error but we can't handle it for now */
385 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
386 }
387 }
388
389
390 /* Initialize the driver specific screen private data.
391 */
392 static GLboolean
393 r128InitDriver( __DRIscreenPrivate *sPriv )
394 {
395 sPriv->private = (void *) r128CreateScreen( sPriv );
396
397 if ( !sPriv->private ) {
398 r128DestroyScreen( sPriv );
399 return GL_FALSE;
400 }
401
402 return GL_TRUE;
403 }
404
405
406 static struct __DriverAPIRec r128API = {
407 .InitDriver = r128InitDriver,
408 .DestroyScreen = r128DestroyScreen,
409 .CreateContext = r128CreateContext,
410 .DestroyContext = r128DestroyContext,
411 .CreateBuffer = r128CreateBuffer,
412 .DestroyBuffer = r128DestroyBuffer,
413 .SwapBuffers = r128SwapBuffers,
414 .MakeCurrent = r128MakeCurrent,
415 .UnbindContext = r128UnbindContext,
416 .GetSwapInfo = NULL,
417 .GetMSC = driGetMSC32,
418 .WaitForMSC = driWaitForMSC32,
419 .WaitForSBC = NULL,
420 .SwapBuffersMSC = NULL
421
422 };
423
424
425 static __GLcontextModes *
426 r128FillInModes( unsigned pixel_bits, unsigned depth_bits,
427 unsigned stencil_bits, GLboolean have_back_buffer )
428 {
429 __GLcontextModes * modes;
430 __GLcontextModes * m;
431 unsigned num_modes;
432 unsigned depth_buffer_factor;
433 unsigned back_buffer_factor;
434 GLenum fb_format;
435 GLenum fb_type;
436
437 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
438 * enough to add support. Basically, if a context is created with an
439 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
440 * will never be used.
441 */
442 static const GLenum back_buffer_modes[] = {
443 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
444 };
445
446 u_int8_t depth_bits_array[2];
447 u_int8_t stencil_bits_array[2];
448
449
450 depth_bits_array[0] = depth_bits;
451 depth_bits_array[1] = depth_bits;
452
453 /* Just like with the accumulation buffer, always provide some modes
454 * with a stencil buffer. It will be a sw fallback, but some apps won't
455 * care about that.
456 */
457 stencil_bits_array[0] = 0;
458 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
459
460 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
461 back_buffer_factor = (have_back_buffer) ? 2 : 1;
462
463 num_modes = depth_buffer_factor * back_buffer_factor * 4;
464
465 if ( pixel_bits == 16 ) {
466 fb_format = GL_RGB;
467 fb_type = GL_UNSIGNED_SHORT_5_6_5;
468 }
469 else {
470 fb_format = GL_BGR;
471 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
472 }
473
474 modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
475 m = modes;
476 if ( ! driFillInModes( & m, fb_format, fb_type,
477 depth_bits_array, stencil_bits_array, depth_buffer_factor,
478 back_buffer_modes, back_buffer_factor,
479 GLX_TRUE_COLOR ) ) {
480 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
481 __func__, __LINE__ );
482 return NULL;
483 }
484
485 if ( ! driFillInModes( & m, fb_format, fb_type,
486 depth_bits_array, stencil_bits_array, depth_buffer_factor,
487 back_buffer_modes, back_buffer_factor,
488 GLX_DIRECT_COLOR ) ) {
489 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
490 __func__, __LINE__ );
491 return NULL;
492 }
493
494 /* Mark the visual as slow if there are "fake" stencil bits.
495 */
496 for ( m = modes ; m != NULL ; m = m->next ) {
497 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
498 m->visualRating = GLX_SLOW_CONFIG;
499 }
500 }
501
502 return modes;
503 }
504
505
506 /**
507 * This is the bootstrap function for the driver. libGL supplies all of the
508 * requisite information about the system, and the driver initializes itself.
509 * This routine also fills in the linked list pointed to by \c driver_modes
510 * with the \c __GLcontextModes that the driver can support for windows or
511 * pbuffers.
512 *
513 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
514 * failure.
515 */
516 PUBLIC
517 void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
518 const __GLcontextModes * modes,
519 const __DRIversion * ddx_version,
520 const __DRIversion * dri_version,
521 const __DRIversion * drm_version,
522 const __DRIframebuffer * frame_buffer,
523 drmAddress pSAREA, int fd,
524 int internal_api_version,
525 const __DRIinterfaceMethods * interface,
526 __GLcontextModes ** driver_modes )
527
528 {
529 __DRIscreenPrivate *psp;
530 static const __DRIversion ddx_expected = { 4, 0, 0 };
531 static const __DRIversion dri_expected = { 4, 0, 0 };
532 static const __DRIversion drm_expected = { 2, 2, 0 };
533
534
535 dri_interface = interface;
536
537 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
538 dri_version, & dri_expected,
539 ddx_version, & ddx_expected,
540 drm_version, & drm_expected ) ) {
541 return NULL;
542 }
543
544 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
545 ddx_version, dri_version, drm_version,
546 frame_buffer, pSAREA, fd,
547 internal_api_version, &r128API);
548 if ( psp != NULL ) {
549 R128DRIPtr dri_priv = (R128DRIPtr) psp->pDevPriv;
550 *driver_modes = r128FillInModes( dri_priv->bpp,
551 (dri_priv->bpp == 16) ? 16 : 24,
552 (dri_priv->bpp == 16) ? 0 : 8,
553 (dri_priv->backOffset != dri_priv->depthOffset) );
554
555 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
556 * enable the extensions. It just makes sure that all the dispatch offsets for all
557 * the extensions that *might* be enables are known. This is needed because the
558 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
559 * enable the extensions until we have a context pointer.
560 *
561 * Hello chicken. Hello egg. How are you two today?
562 */
563 driInitExtensions( NULL, card_extensions, GL_FALSE );
564 }
565
566 return (void *) psp;
567 }