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