f4d069d13919cc0abc568012c0096af13b3584d9
[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_tris.h"
41
42 #include "context.h"
43 #include "imports.h"
44
45 #include "utils.h"
46 #include "vblank.h"
47
48 #include "GL/internal/dri_interface.h"
49
50 /* R128 configuration
51 */
52 #include "xmlpool.h"
53
54 const char __driConfigOptions[] =
55 DRI_CONF_BEGIN
56 DRI_CONF_SECTION_PERFORMANCE
57 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
58 DRI_CONF_SECTION_END
59 DRI_CONF_SECTION_QUALITY
60 DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
61 DRI_CONF_SECTION_END
62 DRI_CONF_SECTION_DEBUG
63 DRI_CONF_NO_RAST(false)
64 #if ENABLE_PERF_BOXES
65 DRI_CONF_PERFORMANCE_BOXES(false)
66 #endif
67 DRI_CONF_SECTION_END
68 DRI_CONF_END;
69 #if ENABLE_PERF_BOXES
70 static const GLuint __driNConfigOptions = 4;
71 #else
72 static const GLuint __driNConfigOptions = 3;
73 #endif
74
75 #if 1
76 /* Including xf86PciInfo.h introduces a bunch of errors...
77 */
78 #define PCI_CHIP_RAGE128LE 0x4C45
79 #define PCI_CHIP_RAGE128LF 0x4C46
80 #define PCI_CHIP_RAGE128PF 0x5046
81 #define PCI_CHIP_RAGE128PR 0x5052
82 #define PCI_CHIP_RAGE128RE 0x5245
83 #define PCI_CHIP_RAGE128RF 0x5246
84 #define PCI_CHIP_RAGE128RK 0x524B
85 #define PCI_CHIP_RAGE128RL 0x524C
86 #endif
87
88 #ifdef USE_NEW_INTERFACE
89 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
90 #endif /* USE_NEW_INTERFACE */
91
92 /* Create the device specific screen private data struct.
93 */
94 static r128ScreenPtr
95 r128CreateScreen( __DRIscreenPrivate *sPriv )
96 {
97 r128ScreenPtr r128Screen;
98 R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
99
100
101 /* Allocate the private area */
102 r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
103 if ( !r128Screen ) return NULL;
104
105 /* parse information in __driConfigOptions */
106 driParseOptionInfo (&r128Screen->optionCache,
107 __driConfigOptions, __driNConfigOptions);
108
109 /* This is first since which regions we map depends on whether or
110 * not we are using a PCI card.
111 */
112 r128Screen->IsPCI = r128DRIPriv->IsPCI;
113 r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
114
115 if (sPriv->drmMinor >= 3) {
116 drm_r128_getparam_t gp;
117 int ret;
118
119 gp.param = R128_PARAM_IRQ_NR;
120 gp.value = &r128Screen->irq;
121
122 ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
123 &gp, sizeof(gp));
124 if (ret) {
125 fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
126 FREE( r128Screen );
127 return NULL;
128 }
129 }
130
131 r128Screen->mmio.handle = r128DRIPriv->registerHandle;
132 r128Screen->mmio.size = r128DRIPriv->registerSize;
133 if ( drmMap( sPriv->fd,
134 r128Screen->mmio.handle,
135 r128Screen->mmio.size,
136 (drmAddressPtr)&r128Screen->mmio.map ) ) {
137 FREE( r128Screen );
138 return NULL;
139 }
140
141 r128Screen->buffers = drmMapBufs( sPriv->fd );
142 if ( !r128Screen->buffers ) {
143 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
144 FREE( r128Screen );
145 return NULL;
146 }
147
148 if ( !r128Screen->IsPCI ) {
149 r128Screen->agpTextures.handle = r128DRIPriv->agpTexHandle;
150 r128Screen->agpTextures.size = r128DRIPriv->agpTexMapSize;
151 if ( drmMap( sPriv->fd,
152 r128Screen->agpTextures.handle,
153 r128Screen->agpTextures.size,
154 (drmAddressPtr)&r128Screen->agpTextures.map ) ) {
155 drmUnmapBufs( r128Screen->buffers );
156 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
157 FREE( r128Screen );
158 return NULL;
159 }
160 }
161
162 switch ( r128DRIPriv->deviceID ) {
163 case PCI_CHIP_RAGE128RE:
164 case PCI_CHIP_RAGE128RF:
165 case PCI_CHIP_RAGE128RK:
166 case PCI_CHIP_RAGE128RL:
167 r128Screen->chipset = R128_CARD_TYPE_R128;
168 break;
169 case PCI_CHIP_RAGE128PF:
170 r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
171 break;
172 case PCI_CHIP_RAGE128LE:
173 case PCI_CHIP_RAGE128LF:
174 r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
175 break;
176 default:
177 r128Screen->chipset = R128_CARD_TYPE_R128;
178 break;
179 }
180
181 r128Screen->cpp = r128DRIPriv->bpp / 8;
182 r128Screen->AGPMode = r128DRIPriv->AGPMode;
183
184 r128Screen->frontOffset = r128DRIPriv->frontOffset;
185 r128Screen->frontPitch = r128DRIPriv->frontPitch;
186 r128Screen->backOffset = r128DRIPriv->backOffset;
187 r128Screen->backPitch = r128DRIPriv->backPitch;
188 r128Screen->depthOffset = r128DRIPriv->depthOffset;
189 r128Screen->depthPitch = r128DRIPriv->depthPitch;
190 r128Screen->spanOffset = r128DRIPriv->spanOffset;
191
192 r128Screen->texOffset[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureOffset;
193 r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureSize;
194 r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] = r128DRIPriv->log2TexGran;
195
196 if ( r128Screen->IsPCI ) {
197 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
198 r128Screen->texOffset[R128_AGP_TEX_HEAP] = 0;
199 r128Screen->texSize[R128_AGP_TEX_HEAP] = 0;
200 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] = 0;
201 } else {
202 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
203 r128Screen->texOffset[R128_AGP_TEX_HEAP] =
204 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
205 r128Screen->texSize[R128_AGP_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
206 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] =
207 r128DRIPriv->log2AGPTexGran;
208 }
209
210 r128Screen->driScreen = sPriv;
211 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
212 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
213 (PFNGLXSCRENABLEEXTENSIONPROC) glXGetProcAddress( (const GLubyte *) "__glXScrEnableExtension" );
214 void * const psc = sPriv->psc->screenConfigs;
215
216 if ( glx_enable_extension != NULL ) {
217 if ( r128Screen->irq != 0 ) {
218 (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
219 (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
220 (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
221 }
222
223 (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
224 }
225 }
226 return r128Screen;
227 }
228
229 /* Destroy the device specific screen private data struct.
230 */
231 static void
232 r128DestroyScreen( __DRIscreenPrivate *sPriv )
233 {
234 r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
235
236 if ( !r128Screen )
237 return;
238
239 if ( !r128Screen->IsPCI ) {
240 drmUnmap( (drmAddress)r128Screen->agpTextures.map,
241 r128Screen->agpTextures.size );
242 }
243 drmUnmapBufs( r128Screen->buffers );
244 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
245
246 /* free all option information */
247 driDestroyOptionInfo (&r128Screen->optionCache);
248
249 FREE( r128Screen );
250 sPriv->private = NULL;
251 }
252
253
254 /* Create and initialize the Mesa and driver specific pixmap buffer
255 * data.
256 */
257 static GLboolean
258 r128CreateBuffer( __DRIscreenPrivate *driScrnPriv,
259 __DRIdrawablePrivate *driDrawPriv,
260 const __GLcontextModes *mesaVis,
261 GLboolean isPixmap )
262 {
263 if (isPixmap) {
264 return GL_FALSE; /* not implemented */
265 }
266 else {
267 driDrawPriv->driverPrivate = (void *)
268 _mesa_create_framebuffer( mesaVis,
269 GL_FALSE, /* software depth buffer? */
270 mesaVis->stencilBits > 0,
271 mesaVis->accumRedBits > 0,
272 mesaVis->alphaBits > 0 );
273 return (driDrawPriv->driverPrivate != NULL);
274 }
275 }
276
277
278 static void
279 r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
280 {
281 _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
282 }
283
284
285 /* Copy the back color buffer to the front color buffer */
286 static void
287 r128SwapBuffers(__DRIdrawablePrivate *dPriv)
288 {
289 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
290 r128ContextPtr rmesa;
291 GLcontext *ctx;
292 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
293 ctx = rmesa->glCtx;
294 if (ctx->Visual.doubleBufferMode) {
295 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
296 if ( rmesa->doPageFlip ) {
297 r128PageFlip( dPriv );
298 }
299 else {
300 r128CopyBuffer( dPriv );
301 }
302 }
303 }
304 else {
305 /* XXX this shouldn't be an error but we can't handle it for now */
306 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
307 }
308 }
309
310
311 /* Initialize the driver specific screen private data.
312 */
313 static GLboolean
314 r128InitDriver( __DRIscreenPrivate *sPriv )
315 {
316 sPriv->private = (void *) r128CreateScreen( sPriv );
317
318 if ( !sPriv->private ) {
319 r128DestroyScreen( sPriv );
320 return GL_FALSE;
321 }
322
323 return GL_TRUE;
324 }
325
326
327 static struct __DriverAPIRec r128API = {
328 .InitDriver = r128InitDriver,
329 .DestroyScreen = r128DestroyScreen,
330 .CreateContext = r128CreateContext,
331 .DestroyContext = r128DestroyContext,
332 .CreateBuffer = r128CreateBuffer,
333 .DestroyBuffer = r128DestroyBuffer,
334 .SwapBuffers = r128SwapBuffers,
335 .MakeCurrent = r128MakeCurrent,
336 .UnbindContext = r128UnbindContext,
337 .GetSwapInfo = NULL,
338 .GetMSC = driGetMSC32,
339 .WaitForMSC = driWaitForMSC32,
340 .WaitForSBC = NULL,
341 .SwapBuffersMSC = NULL
342
343 };
344
345
346 #ifndef DRI_NEW_INTERFACE_ONLY
347 /*
348 * This is the bootstrap function for the driver.
349 * The __driCreateScreen name is the symbol that libGL.so fetches.
350 * Return: pointer to a __DRIscreenPrivate.
351 */
352 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
353 int numConfigs, __GLXvisualConfig *config)
354 {
355 __DRIscreenPrivate *psp;
356 psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &r128API);
357 return (void *) psp;
358 }
359 #endif /* DRI_NEW_INTERFACE_ONLY */
360
361
362 #ifdef USE_NEW_INTERFACE
363 static __GLcontextModes *
364 r128FillInModes( unsigned pixel_bits, unsigned depth_bits,
365 unsigned stencil_bits, GLboolean have_back_buffer )
366 {
367 __GLcontextModes * modes;
368 __GLcontextModes * m;
369 unsigned num_modes;
370 unsigned depth_buffer_factor;
371 unsigned back_buffer_factor;
372 GLenum fb_format;
373 GLenum fb_type;
374
375 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
376 * enough to add support. Basically, if a context is created with an
377 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
378 * will never be used.
379 */
380 static const GLenum back_buffer_modes[] = {
381 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
382 };
383
384 uint8_t depth_bits_array[2];
385 uint8_t stencil_bits_array[2];
386
387
388 depth_bits_array[0] = depth_bits;
389 depth_bits_array[1] = depth_bits;
390
391 /* Just like with the accumulation buffer, always provide some modes
392 * with a stencil buffer. It will be a sw fallback, but some apps won't
393 * care about that.
394 */
395 stencil_bits_array[0] = 0;
396 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
397
398 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
399 back_buffer_factor = (have_back_buffer) ? 2 : 1;
400
401 num_modes = depth_buffer_factor * back_buffer_factor * 4;
402
403 if ( pixel_bits == 16 ) {
404 fb_format = GL_RGB;
405 fb_type = GL_UNSIGNED_SHORT_5_6_5;
406 }
407 else {
408 fb_format = GL_BGR;
409 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
410 }
411
412 modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
413 m = modes;
414 if ( ! driFillInModes( & m, fb_format, fb_type,
415 depth_bits_array, stencil_bits_array, depth_buffer_factor,
416 back_buffer_modes, back_buffer_factor,
417 GLX_TRUE_COLOR ) ) {
418 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
419 __func__, __LINE__ );
420 return NULL;
421 }
422
423 if ( ! driFillInModes( & m, fb_format, fb_type,
424 depth_bits_array, stencil_bits_array, depth_buffer_factor,
425 back_buffer_modes, back_buffer_factor,
426 GLX_DIRECT_COLOR ) ) {
427 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
428 __func__, __LINE__ );
429 return NULL;
430 }
431
432 /* Mark the visual as slow if there are "fake" stencil bits.
433 */
434 for ( m = modes ; m != NULL ; m = m->next ) {
435 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
436 m->visualRating = GLX_SLOW_CONFIG;
437 }
438 }
439
440 return modes;
441 }
442
443
444 /**
445 * This is the bootstrap function for the driver. libGL supplies all of the
446 * requisite information about the system, and the driver initializes itself.
447 * This routine also fills in the linked list pointed to by \c driver_modes
448 * with the \c __GLcontextModes that the driver can support for windows or
449 * pbuffers.
450 *
451 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
452 * failure.
453 */
454 void * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
455 const __GLcontextModes * modes,
456 const __DRIversion * ddx_version,
457 const __DRIversion * dri_version,
458 const __DRIversion * drm_version,
459 const __DRIframebuffer * frame_buffer,
460 drmAddress pSAREA, int fd,
461 int internal_api_version,
462 __GLcontextModes ** driver_modes )
463
464 {
465 __DRIscreenPrivate *psp;
466 static const __DRIversion ddx_expected = { 4, 0, 0 };
467 static const __DRIversion dri_expected = { 4, 0, 0 };
468 static const __DRIversion drm_expected = { 2, 2, 0 };
469
470
471 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
472 dri_version, & dri_expected,
473 ddx_version, & ddx_expected,
474 drm_version, & drm_expected ) ) {
475 return NULL;
476 }
477
478 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
479 ddx_version, dri_version, drm_version,
480 frame_buffer, pSAREA, fd,
481 internal_api_version, &r128API);
482 if ( psp != NULL ) {
483 create_context_modes = (PFNGLXCREATECONTEXTMODES)
484 glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
485 if ( create_context_modes != NULL ) {
486 R128DRIPtr dri_priv = (R128DRIPtr) psp->pDevPriv;
487 *driver_modes = r128FillInModes( dri_priv->bpp,
488 (dri_priv->bpp == 16) ? 16 : 24,
489 (dri_priv->bpp == 16) ? 0 : 8,
490 (dri_priv->backOffset != dri_priv->depthOffset) );
491 }
492 }
493
494 return (void *) psp;
495 }
496 #endif /* USE_NEW_INTERFACE */