Move media stream counter entry points to new extension.
[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 int i;
102
103 if (sPriv->devPrivSize != sizeof(R128DRIRec)) {
104 fprintf(stderr,"\nERROR! sizeof(R128DRIRec) does not match passed size from device driver\n");
105 return GL_FALSE;
106 }
107
108 /* Allocate the private area */
109 r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
110 if ( !r128Screen ) return NULL;
111
112 /* parse information in __driConfigOptions */
113 driParseOptionInfo (&r128Screen->optionCache,
114 __driConfigOptions, __driNConfigOptions);
115
116 /* This is first since which regions we map depends on whether or
117 * not we are using a PCI card.
118 */
119 r128Screen->IsPCI = r128DRIPriv->IsPCI;
120 r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
121
122 if (sPriv->drm_version.minor >= 3) {
123 drm_r128_getparam_t gp;
124 int ret;
125
126 gp.param = R128_PARAM_IRQ_NR;
127 gp.value = &r128Screen->irq;
128
129 ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
130 &gp, sizeof(gp));
131 if (ret) {
132 fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
133 FREE( r128Screen );
134 return NULL;
135 }
136 }
137
138 r128Screen->mmio.handle = r128DRIPriv->registerHandle;
139 r128Screen->mmio.size = r128DRIPriv->registerSize;
140 if ( drmMap( sPriv->fd,
141 r128Screen->mmio.handle,
142 r128Screen->mmio.size,
143 (drmAddressPtr)&r128Screen->mmio.map ) ) {
144 FREE( r128Screen );
145 return NULL;
146 }
147
148 r128Screen->buffers = drmMapBufs( sPriv->fd );
149 if ( !r128Screen->buffers ) {
150 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
151 FREE( r128Screen );
152 return NULL;
153 }
154
155 if ( !r128Screen->IsPCI ) {
156 r128Screen->agpTextures.handle = r128DRIPriv->agpTexHandle;
157 r128Screen->agpTextures.size = r128DRIPriv->agpTexMapSize;
158 if ( drmMap( sPriv->fd,
159 r128Screen->agpTextures.handle,
160 r128Screen->agpTextures.size,
161 (drmAddressPtr)&r128Screen->agpTextures.map ) ) {
162 drmUnmapBufs( r128Screen->buffers );
163 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
164 FREE( r128Screen );
165 return NULL;
166 }
167 }
168
169 switch ( r128DRIPriv->deviceID ) {
170 case PCI_CHIP_RAGE128RE:
171 case PCI_CHIP_RAGE128RF:
172 case PCI_CHIP_RAGE128RK:
173 case PCI_CHIP_RAGE128RL:
174 r128Screen->chipset = R128_CARD_TYPE_R128;
175 break;
176 case PCI_CHIP_RAGE128PF:
177 r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
178 break;
179 case PCI_CHIP_RAGE128LE:
180 case PCI_CHIP_RAGE128LF:
181 r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
182 break;
183 default:
184 r128Screen->chipset = R128_CARD_TYPE_R128;
185 break;
186 }
187
188 r128Screen->cpp = r128DRIPriv->bpp / 8;
189 r128Screen->AGPMode = r128DRIPriv->AGPMode;
190
191 r128Screen->frontOffset = r128DRIPriv->frontOffset;
192 r128Screen->frontPitch = r128DRIPriv->frontPitch;
193 r128Screen->backOffset = r128DRIPriv->backOffset;
194 r128Screen->backPitch = r128DRIPriv->backPitch;
195 r128Screen->depthOffset = r128DRIPriv->depthOffset;
196 r128Screen->depthPitch = r128DRIPriv->depthPitch;
197 r128Screen->spanOffset = r128DRIPriv->spanOffset;
198
199 if ( r128DRIPriv->textureSize == 0 ) {
200 r128Screen->texOffset[R128_LOCAL_TEX_HEAP] =
201 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
202 r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
203 r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] =
204 r128DRIPriv->log2AGPTexGran;
205 } else {
206 r128Screen->texOffset[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureOffset;
207 r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureSize;
208 r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] = r128DRIPriv->log2TexGran;
209 }
210
211 if ( !r128Screen->agpTextures.map || r128DRIPriv->textureSize == 0 ) {
212 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
213 r128Screen->texOffset[R128_AGP_TEX_HEAP] = 0;
214 r128Screen->texSize[R128_AGP_TEX_HEAP] = 0;
215 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] = 0;
216 } else {
217 r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
218 r128Screen->texOffset[R128_AGP_TEX_HEAP] =
219 r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
220 r128Screen->texSize[R128_AGP_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
221 r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] =
222 r128DRIPriv->log2AGPTexGran;
223 }
224
225 r128Screen->driScreen = sPriv;
226
227 i = 0;
228 r128Screen->extensions[i++] = &driFrameTrackingExtension.base;
229 if ( r128Screen->irq != 0 ) {
230 r128Screen->extensions[i++] = &driSwapControlExtension.base;
231 r128Screen->extensions[i++] = &driMediaStreamCounterExtension.base;
232 }
233 r128Screen->extensions[i++] = NULL;
234 sPriv->extensions = r128Screen->extensions;
235
236 return r128Screen;
237 }
238
239 /* Destroy the device specific screen private data struct.
240 */
241 static void
242 r128DestroyScreen( __DRIscreenPrivate *sPriv )
243 {
244 r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
245
246 if ( !r128Screen )
247 return;
248
249 if ( !r128Screen->IsPCI ) {
250 drmUnmap( (drmAddress)r128Screen->agpTextures.map,
251 r128Screen->agpTextures.size );
252 }
253 drmUnmapBufs( r128Screen->buffers );
254 drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
255
256 /* free all option information */
257 driDestroyOptionInfo (&r128Screen->optionCache);
258
259 FREE( r128Screen );
260 sPriv->private = NULL;
261 }
262
263
264 /* Create and initialize the Mesa and driver specific pixmap buffer
265 * data.
266 */
267 static GLboolean
268 r128CreateBuffer( __DRIscreenPrivate *driScrnPriv,
269 __DRIdrawablePrivate *driDrawPriv,
270 const __GLcontextModes *mesaVis,
271 GLboolean isPixmap )
272 {
273 r128ScreenPtr screen = (r128ScreenPtr) driScrnPriv->private;
274
275 if (isPixmap) {
276 return GL_FALSE; /* not implemented */
277 }
278 else {
279 const GLboolean swDepth = GL_FALSE;
280 const GLboolean swAlpha = GL_FALSE;
281 const GLboolean swAccum = mesaVis->accumRedBits > 0;
282 const GLboolean swStencil = mesaVis->stencilBits > 0 &&
283 mesaVis->depthBits != 24;
284 struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
285
286 {
287 driRenderbuffer *frontRb
288 = driNewRenderbuffer(GL_RGBA,
289 NULL,
290 screen->cpp,
291 screen->frontOffset, screen->frontPitch,
292 driDrawPriv);
293 r128SetSpanFunctions(frontRb, mesaVis);
294 _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
295 }
296
297 if (mesaVis->doubleBufferMode) {
298 driRenderbuffer *backRb
299 = driNewRenderbuffer(GL_RGBA,
300 NULL,
301 screen->cpp,
302 screen->backOffset, screen->backPitch,
303 driDrawPriv);
304 r128SetSpanFunctions(backRb, mesaVis);
305 _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
306 }
307
308 if (mesaVis->depthBits == 16) {
309 driRenderbuffer *depthRb
310 = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
311 NULL,
312 screen->cpp,
313 screen->depthOffset, screen->depthPitch,
314 driDrawPriv);
315 r128SetSpanFunctions(depthRb, mesaVis);
316 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
317 }
318 else if (mesaVis->depthBits == 24) {
319 driRenderbuffer *depthRb
320 = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
321 NULL,
322 screen->cpp,
323 screen->depthOffset, screen->depthPitch,
324 driDrawPriv);
325 r128SetSpanFunctions(depthRb, mesaVis);
326 _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
327 }
328
329 if (mesaVis->stencilBits > 0 && !swStencil) {
330 driRenderbuffer *stencilRb
331 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
332 NULL,
333 screen->cpp,
334 screen->depthOffset, screen->depthPitch,
335 driDrawPriv);
336 r128SetSpanFunctions(stencilRb, mesaVis);
337 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
338 }
339
340 _mesa_add_soft_renderbuffers(fb,
341 GL_FALSE, /* color */
342 swDepth,
343 swStencil,
344 swAccum,
345 swAlpha,
346 GL_FALSE /* aux */);
347 driDrawPriv->driverPrivate = (void *) fb;
348
349 return (driDrawPriv->driverPrivate != NULL);
350 }
351 }
352
353
354 static void
355 r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
356 {
357 _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
358 }
359
360
361 /* Copy the back color buffer to the front color buffer */
362 static void
363 r128SwapBuffers(__DRIdrawablePrivate *dPriv)
364 {
365 if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
366 r128ContextPtr rmesa;
367 GLcontext *ctx;
368 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
369 ctx = rmesa->glCtx;
370 if (ctx->Visual.doubleBufferMode) {
371 _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
372 if ( rmesa->doPageFlip ) {
373 r128PageFlip( dPriv );
374 }
375 else {
376 r128CopyBuffer( dPriv );
377 }
378 }
379 }
380 else {
381 /* XXX this shouldn't be an error but we can't handle it for now */
382 _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
383 }
384 }
385
386
387 /* Initialize the driver specific screen private data.
388 */
389 static GLboolean
390 r128InitDriver( __DRIscreenPrivate *sPriv )
391 {
392 sPriv->private = (void *) r128CreateScreen( sPriv );
393
394 if ( !sPriv->private ) {
395 r128DestroyScreen( sPriv );
396 return GL_FALSE;
397 }
398
399 return GL_TRUE;
400 }
401
402
403 static struct __DriverAPIRec r128API = {
404 .DestroyScreen = r128DestroyScreen,
405 .CreateContext = r128CreateContext,
406 .DestroyContext = r128DestroyContext,
407 .CreateBuffer = r128CreateBuffer,
408 .DestroyBuffer = r128DestroyBuffer,
409 .SwapBuffers = r128SwapBuffers,
410 .MakeCurrent = r128MakeCurrent,
411 .UnbindContext = r128UnbindContext,
412 .GetSwapInfo = NULL,
413 .GetMSC = driGetMSC32,
414 .WaitForMSC = driWaitForMSC32,
415 .WaitForSBC = NULL,
416 .SwapBuffersMSC = NULL
417
418 };
419
420
421 static __GLcontextModes *
422 r128FillInModes( unsigned pixel_bits, unsigned depth_bits,
423 unsigned stencil_bits, GLboolean have_back_buffer )
424 {
425 __GLcontextModes * modes;
426 __GLcontextModes * m;
427 unsigned num_modes;
428 unsigned depth_buffer_factor;
429 unsigned back_buffer_factor;
430 GLenum fb_format;
431 GLenum fb_type;
432
433 /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
434 * enough to add support. Basically, if a context is created with an
435 * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
436 * will never be used.
437 */
438 static const GLenum back_buffer_modes[] = {
439 GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
440 };
441
442 u_int8_t depth_bits_array[2];
443 u_int8_t stencil_bits_array[2];
444
445
446 depth_bits_array[0] = depth_bits;
447 depth_bits_array[1] = depth_bits;
448
449 /* Just like with the accumulation buffer, always provide some modes
450 * with a stencil buffer. It will be a sw fallback, but some apps won't
451 * care about that.
452 */
453 stencil_bits_array[0] = 0;
454 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
455
456 depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
457 back_buffer_factor = (have_back_buffer) ? 2 : 1;
458
459 num_modes = depth_buffer_factor * back_buffer_factor * 4;
460
461 if ( pixel_bits == 16 ) {
462 fb_format = GL_RGB;
463 fb_type = GL_UNSIGNED_SHORT_5_6_5;
464 }
465 else {
466 fb_format = GL_BGR;
467 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
468 }
469
470 modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
471 m = modes;
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_TRUE_COLOR ) ) {
476 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
477 __func__, __LINE__ );
478 return NULL;
479 }
480
481 if ( ! driFillInModes( & m, fb_format, fb_type,
482 depth_bits_array, stencil_bits_array, depth_buffer_factor,
483 back_buffer_modes, back_buffer_factor,
484 GLX_DIRECT_COLOR ) ) {
485 fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
486 __func__, __LINE__ );
487 return NULL;
488 }
489
490 /* Mark the visual as slow if there are "fake" stencil bits.
491 */
492 for ( m = modes ; m != NULL ; m = m->next ) {
493 if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
494 m->visualRating = GLX_SLOW_CONFIG;
495 }
496 }
497
498 return modes;
499 }
500
501
502 /**
503 * This is the driver specific part of the createNewScreen entry point.
504 *
505 * \todo maybe fold this into intelInitDriver
506 *
507 * \return the __GLcontextModes supported by this driver
508 */
509 __GLcontextModes *__driDriverInitScreen(__DRIscreenPrivate *psp)
510 {
511 static const __DRIversion ddx_expected = { 4, 0, 0 };
512 static const __DRIversion dri_expected = { 4, 0, 0 };
513 static const __DRIversion drm_expected = { 2, 2, 0 };
514 R128DRIPtr dri_priv = (R128DRIPtr) psp->pDevPriv;
515
516 psp->DriverAPI = r128API;
517 if ( ! driCheckDriDdxDrmVersions2( "Rage128",
518 &psp->dri_version, & dri_expected,
519 &psp->ddx_version, & ddx_expected,
520 &psp->drm_version, & drm_expected ) )
521 return NULL;
522
523 /* Calling driInitExtensions here, with a NULL context pointer,
524 * does not actually enable the extensions. It just makes sure
525 * that all the dispatch offsets for all the extensions that
526 * *might* be enables are known. This is needed because the
527 * dispatch offsets need to be known when _mesa_context_create is
528 * called, but we can't enable the extensions until we have a
529 * context pointer.
530 *
531 * Hello chicken. Hello egg. How are you two today?
532 */
533 driInitExtensions( NULL, card_extensions, GL_FALSE );
534
535 if (!r128InitDriver(psp))
536 return NULL;
537
538 return r128FillInModes( dri_priv->bpp,
539 (dri_priv->bpp == 16) ? 16 : 24,
540 (dri_priv->bpp == 16) ? 0 : 8,
541 (dri_priv->backOffset != dri_priv->depthOffset) );
542 }