Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / mach64 / mach64_screen.c
1 /* -*- mode: c; c-basic-offset: 3 -*- */
2 /*
3  * Copyright 2000 Gareth Hughes
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 /*
26  * Authors:
27  *      Gareth Hughes <gareth@valinux.com>
28  *      Leif Delgass <ldelgass@retinalburn.net>
29  *      Jos�Fonseca <j_r_fonseca@yahoo.co.uk>
30  */
31
32 #include "mach64_context.h"
33 #include "mach64_ioctl.h"
34 #include "mach64_span.h"
35
36 #include "main/context.h"
37 #include "main/imports.h"
38 #include "main/framebuffer.h"
39 #include "main/renderbuffer.h"
40
41 #include "utils.h"
42 #include "vblank.h"
43
44 #include "GL/internal/dri_interface.h"
45
46 /* Mach64 configuration
47  */
48 #include "xmlpool.h"
49
50 PUBLIC const char __driConfigOptions[] =
51 DRI_CONF_BEGIN
52     DRI_CONF_SECTION_PERFORMANCE
53         DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
54     DRI_CONF_SECTION_END
55     DRI_CONF_SECTION_DEBUG
56         DRI_CONF_NO_RAST(false)
57 #if ENABLE_PERF_BOXES
58         DRI_CONF_PERFORMANCE_BOXES(false)
59 #endif
60     DRI_CONF_SECTION_END
61 DRI_CONF_END;
62 #if ENABLE_PERF_BOXES
63 static const GLuint __driNConfigOptions = 3;
64 #else
65 static const GLuint __driNConfigOptions = 2;
66 #endif
67
68 static const __DRIconfig **
69 mach64FillInModes( __DRIscreen *psp,
70                    unsigned pixel_bits, unsigned depth_bits,
71                    unsigned stencil_bits, GLboolean have_back_buffer )
72 {
73     __DRIconfig **configs;
74     struct gl_config * m;
75     GLenum fb_format;
76     GLenum fb_type;
77     unsigned depth_buffer_factor;
78     unsigned back_buffer_factor;
79     unsigned i;
80
81     /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
82      * enough to add support.  Basically, if a context is created with an
83      * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
84      * will never be used.
85      */
86     static const GLenum back_buffer_modes[] = {
87         GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
88     };
89
90     uint8_t depth_bits_array[2];
91     uint8_t stencil_bits_array[2];
92     uint8_t msaa_samples_array[1];
93
94     depth_bits_array[0] = depth_bits;
95     depth_bits_array[1] = depth_bits;
96     
97     /* Just like with the accumulation buffer, always provide some modes
98      * with a stencil buffer.  It will be a sw fallback, but some apps won't
99      * care about that.
100      */
101     stencil_bits_array[0] = 0;
102     stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
103
104     msaa_samples_array[0] = 0;
105
106     depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
107     back_buffer_factor  = (have_back_buffer) ? 2 : 1;
108
109     if (pixel_bits == 16) {
110        fb_format = GL_RGB;
111        fb_type = GL_UNSIGNED_SHORT_5_6_5;
112     }
113     else {
114        fb_format = GL_BGRA;
115        fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
116     }
117
118     configs = driCreateConfigs(fb_format, fb_type,
119                                depth_bits_array, stencil_bits_array,
120                                depth_buffer_factor, back_buffer_modes,
121                                back_buffer_factor,
122                                msaa_samples_array, 1, GL_TRUE);
123     if (configs == NULL) {
124        fprintf(stderr, "[%s:%u] Error creating FBConfig!\n",
125                __func__, __LINE__);
126        return NULL;
127     }
128
129     /* Mark the visual as slow if there are "fake" stencil bits.
130      */
131     for (i = 0; configs[i]; i++) {
132        m = &configs[i]->modes;
133        if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
134           m->visualRating = GLX_SLOW_CONFIG;
135        }
136     }
137
138     return (const __DRIconfig **) configs;
139 }
140
141
142 /* Create the device specific screen private data struct.
143  */
144 static mach64ScreenRec *
145 mach64CreateScreen( __DRIscreen *sPriv )
146 {
147    mach64ScreenPtr mach64Screen;
148    ATIDRIPtr serverInfo = (ATIDRIPtr)sPriv->pDevPriv;
149    int i;
150
151    if (sPriv->devPrivSize != sizeof(ATIDRIRec)) {
152       fprintf(stderr,"\nERROR!  sizeof(ATIDRIRec) does not match passed size from device driver\n");
153       return GL_FALSE;
154    }
155
156    if ( MACH64_DEBUG & DEBUG_VERBOSE_DRI ) 
157       fprintf( stderr, "%s\n", __FUNCTION__ );
158
159    /* Allocate the private area */
160    mach64Screen = (mach64ScreenPtr) CALLOC( sizeof(*mach64Screen) );
161    if ( !mach64Screen ) return NULL;
162
163    /* parse information in __driConfigOptions */
164    driParseOptionInfo (&mach64Screen->optionCache,
165                        __driConfigOptions, __driNConfigOptions);
166
167    mach64Screen->IsPCI = serverInfo->IsPCI;
168
169    {
170       drm_mach64_getparam_t gp;
171       int ret;
172
173       gp.param = MACH64_PARAM_IRQ_NR;
174       gp.value = (void *) &mach64Screen->irq;
175
176       ret = drmCommandWriteRead( sPriv->fd, DRM_MACH64_GETPARAM,
177                                     &gp, sizeof(gp));
178       if (ret) {
179          fprintf(stderr, "DRM_MACH64_GETPARAM (MACH64_PARAM_IRQ_NR): %d\n", ret);
180          FREE( mach64Screen );
181          return NULL;
182       }
183    }
184
185    mach64Screen->mmio.handle = serverInfo->regs;
186    mach64Screen->mmio.size   = serverInfo->regsSize;
187    if ( drmMap( sPriv->fd,
188                 mach64Screen->mmio.handle,
189                 mach64Screen->mmio.size,
190                 (drmAddressPtr)&mach64Screen->mmio.map ) != 0 ) {
191       FREE( mach64Screen );
192       return NULL;
193    }
194
195    mach64Screen->buffers = drmMapBufs( sPriv->fd );
196    if ( !mach64Screen->buffers ) {
197       drmUnmap( (drmAddress)mach64Screen->mmio.map,
198                 mach64Screen->mmio.size );
199       FREE( mach64Screen );
200       return NULL;
201    }
202
203    if ( !mach64Screen->IsPCI ) {
204       mach64Screen->agpTextures.handle = serverInfo->agp;
205       mach64Screen->agpTextures.size   = serverInfo->agpSize;
206       if ( drmMap( sPriv->fd,
207                    mach64Screen->agpTextures.handle,
208                    mach64Screen->agpTextures.size,
209                    (drmAddressPtr)&mach64Screen->agpTextures.map ) ) {
210          drmUnmapBufs( mach64Screen->buffers );
211          drmUnmap( (drmAddress)mach64Screen->mmio.map, mach64Screen->mmio.size );
212          FREE( mach64Screen );
213          return NULL;
214       }
215    }
216
217    mach64Screen->AGPMode        = serverInfo->AGPMode;
218
219    mach64Screen->chipset        = serverInfo->chipset;
220    mach64Screen->width          = serverInfo->width;
221    mach64Screen->height         = serverInfo->height;
222    mach64Screen->mem            = serverInfo->mem;
223    mach64Screen->cpp            = serverInfo->cpp;
224
225    mach64Screen->frontOffset    = serverInfo->frontOffset;
226    mach64Screen->frontPitch     = serverInfo->frontPitch;
227    mach64Screen->backOffset     = serverInfo->backOffset;
228    mach64Screen->backPitch      = serverInfo->backPitch;
229    mach64Screen->depthOffset    = serverInfo->depthOffset;
230    mach64Screen->depthPitch     = serverInfo->depthPitch;
231
232    mach64Screen->texOffset[MACH64_CARD_HEAP] = serverInfo->textureOffset;
233    mach64Screen->texSize[MACH64_CARD_HEAP] = serverInfo->textureSize;
234    mach64Screen->logTexGranularity[MACH64_CARD_HEAP] =
235       serverInfo->logTextureGranularity;
236
237    if ( mach64Screen->IsPCI ) {
238       mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS - 1;
239       mach64Screen->firstTexHeap = MACH64_CARD_HEAP;
240       mach64Screen->texOffset[MACH64_AGP_HEAP] = 0;
241       mach64Screen->texSize[MACH64_AGP_HEAP] = 0;
242       mach64Screen->logTexGranularity[MACH64_AGP_HEAP] = 0;
243    } else {
244       if (serverInfo->textureSize > 0) {
245          mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS;
246          mach64Screen->firstTexHeap = MACH64_CARD_HEAP;
247       } else {
248          mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS - 1;
249          mach64Screen->firstTexHeap = MACH64_AGP_HEAP;
250       }
251       mach64Screen->texOffset[MACH64_AGP_HEAP] = serverInfo->agpTextureOffset;
252       mach64Screen->texSize[MACH64_AGP_HEAP] = serverInfo->agpSize;
253       mach64Screen->logTexGranularity[MACH64_AGP_HEAP] = serverInfo->logAgpTextureGranularity;
254    }
255
256    mach64Screen->driScreen = sPriv;
257
258    i = 0;
259    if ( mach64Screen->irq != 0 ) {
260       mach64Screen->extensions[i++] = &driSwapControlExtension.base;
261       mach64Screen->extensions[i++] = &driMediaStreamCounterExtension.base;
262    }
263    mach64Screen->extensions[i++] = NULL;
264    sPriv->extensions = mach64Screen->extensions;
265
266    return mach64Screen;
267 }
268
269 /* Destroy the device specific screen private data struct.
270  */
271 static void
272 mach64DestroyScreen( __DRIscreen *driScreen )
273 {
274    mach64ScreenRec *mach64Screen = (mach64ScreenRec *) driScreen->private;
275
276    if ( !mach64Screen )
277       return;
278
279    if ( MACH64_DEBUG & DEBUG_VERBOSE_DRI ) 
280       fprintf( stderr, "%s\n", __FUNCTION__ );
281
282    if ( !mach64Screen->IsPCI ) {
283       drmUnmap( (drmAddress)mach64Screen->agpTextures.map,
284                 mach64Screen->agpTextures.size );
285    }
286
287    drmUnmapBufs( mach64Screen->buffers );
288    drmUnmap( (drmAddress)mach64Screen->mmio.map, mach64Screen->mmio.size );
289
290    FREE( mach64Screen );
291    driScreen->private = NULL;
292 }
293
294
295 /* Create and initialize the Mesa and driver specific pixmap buffer
296  * data.
297  */
298 static GLboolean
299 mach64CreateBuffer( __DRIscreen *driScrnPriv,
300                     __DRIdrawable *driDrawPriv,
301                     const struct gl_config *mesaVis,
302                     GLboolean isPixmap )
303 {
304    mach64ScreenPtr screen = (mach64ScreenPtr) driScrnPriv->private;
305
306    if (isPixmap) {
307       return GL_FALSE; /* not implemented */
308    }
309    else {
310       struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
311
312       {
313          driRenderbuffer *frontRb
314             = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
315                                  NULL,
316                                  screen->cpp,
317                                  screen->frontOffset, screen->frontPitch,
318                                  driDrawPriv);
319          mach64SetSpanFunctions(frontRb, mesaVis);
320          _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
321       }
322
323       if (mesaVis->doubleBufferMode) {
324          driRenderbuffer *backRb
325             = driNewRenderbuffer(MESA_FORMAT_ARGB8888,
326                                  NULL,
327                                  screen->cpp,
328                                  screen->backOffset, screen->backPitch,
329                                  driDrawPriv);
330          mach64SetSpanFunctions(backRb, mesaVis);
331          _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
332       }
333
334       if (mesaVis->depthBits == 16) {
335          driRenderbuffer *depthRb
336             = driNewRenderbuffer(MESA_FORMAT_Z16,
337                                  NULL, screen->cpp,
338                                  screen->depthOffset, screen->depthPitch,
339                                  driDrawPriv);
340          mach64SetSpanFunctions(depthRb, mesaVis);
341          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
342       }
343       else if (mesaVis->depthBits == 24) {
344          /* XXX I don't think 24-bit Z is supported - so this isn't used */
345          driRenderbuffer *depthRb
346             = driNewRenderbuffer(MESA_FORMAT_Z24_S8,
347                                  NULL,
348                                  screen->cpp,
349                                  screen->depthOffset, screen->depthPitch,
350                                  driDrawPriv);
351          mach64SetSpanFunctions(depthRb, mesaVis);
352          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
353       }
354
355       _mesa_add_soft_renderbuffers(fb,
356                                    GL_FALSE, /* color */
357                                    GL_FALSE, /* depth */
358                                    mesaVis->stencilBits > 0,
359                                    mesaVis->accumRedBits > 0,
360                                    GL_FALSE, /* alpha */
361                                    GL_FALSE /* aux */);
362       driDrawPriv->driverPrivate = (void *) fb;
363
364       return (driDrawPriv->driverPrivate != NULL);
365    }
366 }
367
368
369 static void
370 mach64DestroyBuffer(__DRIdrawable *driDrawPriv)
371 {
372    _mesa_reference_framebuffer((struct gl_framebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
373 }
374
375
376 /* Copy the back color buffer to the front color buffer */
377 static void
378 mach64SwapBuffers(__DRIdrawable *dPriv)
379 {
380    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
381       mach64ContextPtr mmesa;
382       struct gl_context *ctx;
383       mmesa = (mach64ContextPtr) dPriv->driContextPriv->driverPrivate;
384       ctx = mmesa->glCtx;
385       if (ctx->Visual.doubleBufferMode) {
386          _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
387          mach64CopyBuffer( dPriv );
388       }
389    }
390    else {
391       /* XXX this shouldn't be an error but we can't handle it for now */
392       _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
393    }
394 }
395
396
397 /* Initialize the driver specific screen private data.
398  */
399 static GLboolean
400 mach64InitDriver( __DRIscreen *driScreen )
401 {
402    driScreen->private = (void *) mach64CreateScreen( driScreen );
403
404    if ( !driScreen->private ) {
405       mach64DestroyScreen( driScreen );
406       return GL_FALSE;
407    }
408
409    return GL_TRUE;
410 }
411
412 /**
413  * This is the driver specific part of the createNewScreen entry point.
414  * 
415  * \todo maybe fold this into intelInitDriver
416  *
417  * \return the struct gl_config supported by this driver
418  */
419 static const __DRIconfig **
420 mach64InitScreen(__DRIscreen *psp)
421 {
422    static const __DRIversion ddx_expected = { 6, 4, 0 };
423    static const __DRIversion dri_expected = { 4, 0, 0 };
424    static const __DRIversion drm_expected = { 2, 0, 0 };
425    ATIDRIPtr dri_priv = (ATIDRIPtr) psp->pDevPriv;
426
427    if ( ! driCheckDriDdxDrmVersions2( "Mach64",
428                                       &psp->dri_version, & dri_expected,
429                                       &psp->ddx_version, & ddx_expected,
430                                       &psp->drm_version, & drm_expected ) ) {
431       return NULL;
432    }
433    
434    if (!mach64InitDriver(psp))
435       return NULL;
436
437    return  mach64FillInModes( psp, dri_priv->cpp * 8, 16, 0, 1);
438 }
439
440 const struct __DriverAPIRec driDriverAPI = {
441    .InitScreen      = mach64InitScreen,
442    .DestroyScreen   = mach64DestroyScreen,
443    .CreateContext   = mach64CreateContext,
444    .DestroyContext  = mach64DestroyContext,
445    .CreateBuffer    = mach64CreateBuffer,
446    .DestroyBuffer   = mach64DestroyBuffer,
447    .SwapBuffers     = mach64SwapBuffers,
448    .MakeCurrent     = mach64MakeCurrent,
449    .UnbindContext   = mach64UnbindContext,
450    .GetSwapInfo     = NULL,
451    .GetDrawableMSC  = driDrawableGetMSC32,
452    .WaitForMSC      = driWaitForMSC32,
453    .WaitForSBC      = NULL,
454    .SwapBuffersMSC  = NULL
455 };
456
457 /* This is the table of extensions that the loader will dlsym() for. */
458 PUBLIC const __DRIextension *__driDriverExtensions[] = {
459     &driCoreExtension.base,
460     &driLegacyExtension.base,
461     NULL
462 };