Tizen 2.0 Release
[profile/ivi/osmesa.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
41 #include "main/context.h"
42 #include "main/imports.h"
43 #include "main/framebuffer.h"
44 #include "main/renderbuffer.h"
45
46 #include "utils.h"
47 #include "vblank.h"
48
49 #include "GL/internal/dri_interface.h"
50
51 /* R128 configuration
52  */
53 #include "xmlpool.h"
54
55 PUBLIC const char __driConfigOptions[] =
56 DRI_CONF_BEGIN
57     DRI_CONF_SECTION_PERFORMANCE
58         DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
59     DRI_CONF_SECTION_END
60     DRI_CONF_SECTION_QUALITY
61         DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
62     DRI_CONF_SECTION_END
63     DRI_CONF_SECTION_DEBUG
64         DRI_CONF_NO_RAST(false)
65 #if ENABLE_PERF_BOXES
66         DRI_CONF_PERFORMANCE_BOXES(false)
67 #endif
68     DRI_CONF_SECTION_END
69 DRI_CONF_END;
70 #if ENABLE_PERF_BOXES
71 static const GLuint __driNConfigOptions = 4;
72 #else
73 static const GLuint __driNConfigOptions = 3;
74 #endif
75
76 #if 1
77 /* Including xf86PciInfo.h introduces a bunch of errors...
78  */
79 #define PCI_CHIP_RAGE128LE      0x4C45
80 #define PCI_CHIP_RAGE128LF      0x4C46
81 #define PCI_CHIP_RAGE128PF      0x5046
82 #define PCI_CHIP_RAGE128PR      0x5052
83 #define PCI_CHIP_RAGE128RE      0x5245
84 #define PCI_CHIP_RAGE128RF      0x5246
85 #define PCI_CHIP_RAGE128RK      0x524B
86 #define PCI_CHIP_RAGE128RL      0x524C
87 #endif
88
89
90 /* Create the device specific screen private data struct.
91  */
92 static r128ScreenPtr
93 r128CreateScreen( __DRIscreen *sPriv )
94 {
95    r128ScreenPtr r128Screen;
96    R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
97    int i;
98
99    if (sPriv->devPrivSize != sizeof(R128DRIRec)) {
100       fprintf(stderr,"\nERROR!  sizeof(R128DRIRec) does not match passed size from device driver\n");
101       return GL_FALSE;
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->drm_version.minor >= 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    if ( r128DRIPriv->textureSize == 0 ) {
196       r128Screen->texOffset[R128_LOCAL_TEX_HEAP] =
197          r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
198       r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
199       r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] =
200          r128DRIPriv->log2AGPTexGran;
201    } else {
202       r128Screen->texOffset[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureOffset;
203       r128Screen->texSize[R128_LOCAL_TEX_HEAP] = r128DRIPriv->textureSize;
204       r128Screen->logTexGranularity[R128_LOCAL_TEX_HEAP] = r128DRIPriv->log2TexGran;
205    }
206
207    if ( !r128Screen->agpTextures.map || r128DRIPriv->textureSize == 0 ) {
208       r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
209       r128Screen->texOffset[R128_AGP_TEX_HEAP] = 0;
210       r128Screen->texSize[R128_AGP_TEX_HEAP] = 0;
211       r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] = 0;
212    } else {
213       r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
214       r128Screen->texOffset[R128_AGP_TEX_HEAP] =
215          r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
216       r128Screen->texSize[R128_AGP_TEX_HEAP] = r128DRIPriv->agpTexMapSize;
217       r128Screen->logTexGranularity[R128_AGP_TEX_HEAP] =
218          r128DRIPriv->log2AGPTexGran;
219    }
220
221    r128Screen->driScreen = sPriv;
222
223    i = 0;
224    if ( r128Screen->irq != 0 ) {
225        r128Screen->extensions[i++] = &driSwapControlExtension.base;
226        r128Screen->extensions[i++] = &driMediaStreamCounterExtension.base;
227    }
228    r128Screen->extensions[i++] = NULL;
229    sPriv->extensions = r128Screen->extensions;
230
231    return r128Screen;
232 }
233
234 /* Destroy the device specific screen private data struct.
235  */
236 static void
237 r128DestroyScreen( __DRIscreen *sPriv )
238 {
239    r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
240
241    if ( !r128Screen )
242       return;
243
244    if ( !r128Screen->IsPCI ) {
245       drmUnmap( (drmAddress)r128Screen->agpTextures.map,
246                 r128Screen->agpTextures.size );
247    }
248    drmUnmapBufs( r128Screen->buffers );
249    drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
250
251    /* free all option information */
252    driDestroyOptionInfo (&r128Screen->optionCache);
253
254    FREE( r128Screen );
255    sPriv->private = NULL;
256 }
257
258
259 /* Create and initialize the Mesa and driver specific pixmap buffer
260  * data.
261  */
262 static GLboolean
263 r128CreateBuffer( __DRIscreen *driScrnPriv,
264                   __DRIdrawable *driDrawPriv,
265                   const struct gl_config *mesaVis,
266                   GLboolean isPixmap )
267 {
268    r128ScreenPtr screen = (r128ScreenPtr) driScrnPriv->private;
269
270    if (isPixmap) {
271       return GL_FALSE; /* not implemented */
272    }
273    else {
274       const GLboolean swDepth = GL_FALSE;
275       const GLboolean swAlpha = GL_FALSE;
276       const GLboolean swAccum = mesaVis->accumRedBits > 0;
277       const GLboolean swStencil = mesaVis->stencilBits > 0 &&
278          mesaVis->depthBits != 24;
279       struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
280
281       {
282          driRenderbuffer *frontRb
283             = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
284                                  NULL,
285                                  screen->cpp,
286                                  screen->frontOffset, screen->frontPitch,
287                                  driDrawPriv);
288          r128SetSpanFunctions(frontRb, mesaVis);
289          _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
290       }
291
292       if (mesaVis->doubleBufferMode) {
293          driRenderbuffer *backRb
294             = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
295                                  NULL,
296                                  screen->cpp,
297                                  screen->backOffset, screen->backPitch,
298                                  driDrawPriv);
299          r128SetSpanFunctions(backRb, mesaVis);
300          _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
301       }
302
303       if (mesaVis->depthBits == 16) {
304          driRenderbuffer *depthRb
305             = driNewRenderbuffer(MESA_FORMAT_Z16,
306                                  NULL,
307                                  screen->cpp,
308                                  screen->depthOffset, screen->depthPitch,
309                                  driDrawPriv);
310          r128SetSpanFunctions(depthRb, mesaVis);
311          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
312       }
313       else if (mesaVis->depthBits == 24) {
314          driRenderbuffer *depthRb
315             = driNewRenderbuffer(MESA_FORMAT_S8_Z24,
316                                  NULL,
317                                  screen->cpp,
318                                  screen->depthOffset, screen->depthPitch,
319                                  driDrawPriv);
320          r128SetSpanFunctions(depthRb, mesaVis);
321          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
322       }
323
324       if (mesaVis->stencilBits > 0 && !swStencil) {
325          driRenderbuffer *stencilRb
326             = driNewRenderbuffer(MESA_FORMAT_S8,
327                                  NULL,
328                                  screen->cpp,
329                                  screen->depthOffset, screen->depthPitch,
330                                  driDrawPriv);
331          r128SetSpanFunctions(stencilRb, mesaVis);
332          _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
333       }
334
335       _mesa_add_soft_renderbuffers(fb,
336                                    GL_FALSE, /* color */
337                                    swDepth,
338                                    swStencil,
339                                    swAccum,
340                                    swAlpha,
341                                    GL_FALSE /* aux */);
342       driDrawPriv->driverPrivate = (void *) fb;
343
344       return (driDrawPriv->driverPrivate != NULL);
345    }
346 }
347
348
349 static void
350 r128DestroyBuffer(__DRIdrawable *driDrawPriv)
351 {
352    _mesa_reference_framebuffer((struct gl_framebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
353 }
354
355
356 /* Copy the back color buffer to the front color buffer */
357 static void
358 r128SwapBuffers(__DRIdrawable *dPriv)
359 {
360    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
361       r128ContextPtr rmesa;
362       struct gl_context *ctx;
363       rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
364       ctx = rmesa->glCtx;
365       if (ctx->Visual.doubleBufferMode) {
366          _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
367          if ( rmesa->doPageFlip ) {
368             r128PageFlip( dPriv );
369          }
370          else {
371             r128CopyBuffer( dPriv );
372          }
373       }
374    }
375    else {
376       /* XXX this shouldn't be an error but we can't handle it for now */
377       _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
378    }
379 }
380
381
382 /* Initialize the driver specific screen private data.
383  */
384 static GLboolean
385 r128InitDriver( __DRIscreen *sPriv )
386 {
387    sPriv->private = (void *) r128CreateScreen( sPriv );
388
389    if ( !sPriv->private ) {
390       r128DestroyScreen( sPriv );
391       return GL_FALSE;
392    }
393
394    return GL_TRUE;
395 }
396
397 static const __DRIconfig **
398 r128FillInModes( __DRIscreen *psp,
399                  unsigned pixel_bits, unsigned depth_bits,
400                  unsigned stencil_bits, GLboolean have_back_buffer )
401 {
402     __DRIconfig **configs;
403     struct gl_config * m;
404     unsigned depth_buffer_factor;
405     unsigned back_buffer_factor;
406     GLenum fb_format;
407     GLenum fb_type;
408     int i;
409
410     /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
411      * enough to add support.  Basically, if a context is created with an
412      * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
413      * will never be used.
414      */
415     static const GLenum back_buffer_modes[] = {
416         GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
417     };
418
419     uint8_t depth_bits_array[2];
420     uint8_t stencil_bits_array[2];
421     uint8_t msaa_samples_array[1];
422
423     depth_bits_array[0] = depth_bits;
424     depth_bits_array[1] = depth_bits;
425     
426     /* Just like with the accumulation buffer, always provide some modes
427      * with a stencil buffer.  It will be a sw fallback, but some apps won't
428      * care about that.
429      */
430     stencil_bits_array[0] = 0;
431     stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
432
433     msaa_samples_array[0] = 0;
434
435     depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
436     back_buffer_factor  = (have_back_buffer) ? 2 : 1;
437
438     if ( pixel_bits == 16 ) {
439         fb_format = GL_RGB;
440         fb_type = GL_UNSIGNED_SHORT_5_6_5;
441     }
442     else {
443         fb_format = GL_BGR;
444         fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
445     }
446
447     configs = driCreateConfigs(fb_format, fb_type,
448                                depth_bits_array, stencil_bits_array,
449                                depth_buffer_factor, back_buffer_modes,
450                                back_buffer_factor,
451                                msaa_samples_array, 1, GL_TRUE);
452     if (configs == NULL) {
453         fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
454                 __LINE__);
455         return NULL;
456     }
457
458     /* Mark the visual as slow if there are "fake" stencil bits.
459      */
460     for (i = 0; configs[i]; i++) {
461         m = &configs[i]->modes;
462         if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
463             m->visualRating = GLX_SLOW_CONFIG;
464         }
465     }
466
467     return (const __DRIconfig **) configs;
468 }
469
470
471 /**
472  * This is the driver specific part of the createNewScreen entry point.
473  * 
474  * \todo maybe fold this into intelInitDriver
475  *
476  * \return the struct gl_config supported by this driver
477  */
478 static const __DRIconfig **
479 r128InitScreen(__DRIscreen *psp)
480 {
481    static const __DRIversion ddx_expected = { 4, 0, 0 };
482    static const __DRIversion dri_expected = { 4, 0, 0 };
483    static const __DRIversion drm_expected = { 2, 2, 0 };
484    R128DRIPtr dri_priv = (R128DRIPtr) psp->pDevPriv;
485
486    if ( ! driCheckDriDdxDrmVersions2( "Rage128",
487                                       &psp->dri_version, & dri_expected,
488                                       &psp->ddx_version, & ddx_expected,
489                                       &psp->drm_version, & drm_expected ) )
490       return NULL;
491
492    if (!r128InitDriver(psp))
493        return NULL;
494
495    return r128FillInModes( psp,
496                            dri_priv->bpp,
497                            (dri_priv->bpp == 16) ? 16 : 24,
498                            (dri_priv->bpp == 16) ? 0  : 8,
499                            (dri_priv->backOffset != dri_priv->depthOffset) );
500 }
501
502 const struct __DriverAPIRec driDriverAPI = {
503    .InitScreen      = r128InitScreen,
504    .DestroyScreen   = r128DestroyScreen,
505    .CreateContext   = r128CreateContext,
506    .DestroyContext  = r128DestroyContext,
507    .CreateBuffer    = r128CreateBuffer,
508    .DestroyBuffer   = r128DestroyBuffer,
509    .SwapBuffers     = r128SwapBuffers,
510    .MakeCurrent     = r128MakeCurrent,
511    .UnbindContext   = r128UnbindContext,
512    .GetSwapInfo     = NULL,
513    .GetDrawableMSC  = driDrawableGetMSC32,
514    .WaitForMSC      = driWaitForMSC32,
515    .WaitForSBC      = NULL,
516    .SwapBuffersMSC  = NULL
517 };
518
519 /* This is the table of extensions that the loader will dlsym() for. */
520 PUBLIC const __DRIextension *__driDriverExtensions[] = {
521     &driCoreExtension.base,
522     &driLegacyExtension.base,
523     NULL
524 };