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