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