Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / unichrome / via_screen.c
1 /*
2  * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3  * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sub license,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19  * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <stdio.h>
26
27 #include "dri_util.h"
28 #include "utils.h"
29 #include "main/glheader.h"
30 #include "main/context.h"
31 #include "main/framebuffer.h"
32 #include "main/renderbuffer.h"
33 #include "main/simple_list.h"
34 #include "vblank.h"
35
36 #include "via_state.h"
37 #include "via_tex.h"
38 #include "via_span.h"
39 #include "via_screen.h"
40 #include "via_dri.h"
41
42 #include "GL/internal/dri_interface.h"
43 #include "drirenderbuffer.h"
44
45 #include "xmlpool.h"
46
47 PUBLIC const char __driConfigOptions[] =
48 DRI_CONF_BEGIN
49     DRI_CONF_SECTION_PERFORMANCE
50         DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
51     DRI_CONF_SECTION_END
52     DRI_CONF_SECTION_QUALITY
53         DRI_CONF_EXCESS_MIPMAP(false)
54     DRI_CONF_SECTION_END
55     DRI_CONF_SECTION_DEBUG
56         DRI_CONF_NO_RAST(false)
57     DRI_CONF_SECTION_END
58 DRI_CONF_END;
59 static const GLuint __driNConfigOptions = 3;
60
61 static drmBufMapPtr via_create_empty_buffers(void)
62 {
63     drmBufMapPtr retval;
64
65     retval = (drmBufMapPtr)MALLOC(sizeof(drmBufMap));
66     if (retval == NULL) return NULL;
67     memset(retval, 0, sizeof(drmBufMap));
68
69     retval->list = (drmBufPtr)MALLOC(sizeof(drmBuf) * VIA_DMA_BUF_NR);
70     if (retval->list == NULL) {
71        FREE(retval);
72        return NULL;
73     }
74     memset(retval->list, 0, sizeof(drmBuf) * VIA_DMA_BUF_NR);
75     return retval;
76 }
77
78 static void via_free_empty_buffers( drmBufMapPtr bufs )
79 {
80    if (bufs && bufs->list)
81       FREE(bufs->list);
82
83    if (bufs)
84       FREE(bufs);
85 }
86
87
88 static GLboolean
89 viaInitDriver(__DRIscreen *sPriv)
90 {
91     viaScreenPrivate *viaScreen;
92     VIADRIPtr gDRIPriv = (VIADRIPtr)sPriv->pDevPriv;
93     int i;
94
95     if (sPriv->devPrivSize != sizeof(VIADRIRec)) {
96       fprintf(stderr,"\nERROR!  sizeof(VIADRIRec) does not match passed size from device driver\n");
97       return GL_FALSE;
98     }
99
100     /* Allocate the private area */
101     viaScreen = (viaScreenPrivate *) CALLOC(sizeof(viaScreenPrivate));
102     if (!viaScreen) {
103         __driUtilMessage("viaInitDriver: alloc viaScreenPrivate struct failed");
104         return GL_FALSE;
105     }
106
107     /* parse information in __driConfigOptions */
108     driParseOptionInfo (&viaScreen->optionCache,
109                         __driConfigOptions, __driNConfigOptions);
110
111
112     viaScreen->driScrnPriv = sPriv;
113     sPriv->private = (void *)viaScreen;
114
115     viaScreen->deviceID = gDRIPriv->deviceID;
116     viaScreen->width = gDRIPriv->width;
117     viaScreen->height = gDRIPriv->height;
118     viaScreen->mem = gDRIPriv->mem;
119     viaScreen->bitsPerPixel = gDRIPriv->bytesPerPixel * 8;
120     viaScreen->bytesPerPixel = gDRIPriv->bytesPerPixel;
121     viaScreen->fbOffset = 0;
122     viaScreen->fbSize = gDRIPriv->fbSize;
123     viaScreen->irqEnabled = gDRIPriv->irqEnabled;
124
125     if (VIA_DEBUG & DEBUG_DRI) {
126         fprintf(stderr, "deviceID = %08x\n", viaScreen->deviceID);
127         fprintf(stderr, "width = %08x\n", viaScreen->width);    
128         fprintf(stderr, "height = %08x\n", viaScreen->height);  
129         fprintf(stderr, "cpp = %08x\n", viaScreen->cpp);        
130         fprintf(stderr, "fbOffset = %08x\n", viaScreen->fbOffset);      
131     }
132
133     viaScreen->bufs = via_create_empty_buffers();
134     if (viaScreen->bufs == NULL) {
135         __driUtilMessage("viaInitDriver: via_create_empty_buffers() failed");
136         FREE(viaScreen);
137         return GL_FALSE;
138     }
139
140     if (drmMap(sPriv->fd,
141                gDRIPriv->regs.handle,
142                gDRIPriv->regs.size,
143                &viaScreen->reg) != 0) {
144         FREE(viaScreen);
145         sPriv->private = NULL;
146         __driUtilMessage("viaInitDriver: drmMap regs failed");
147         return GL_FALSE;
148     }
149
150     if (gDRIPriv->agp.size) {
151         if (drmMap(sPriv->fd,
152                    gDRIPriv->agp.handle,
153                    gDRIPriv->agp.size,
154                    (drmAddress *)&viaScreen->agpLinearStart) != 0) {
155             drmUnmap(viaScreen->reg, gDRIPriv->regs.size);
156             FREE(viaScreen);
157             sPriv->private = NULL;
158             __driUtilMessage("viaInitDriver: drmMap agp failed");
159             return GL_FALSE;
160         }
161
162         viaScreen->agpBase = drmAgpBase(sPriv->fd);
163     } else
164         viaScreen->agpLinearStart = 0;
165
166     viaScreen->sareaPrivOffset = gDRIPriv->sarea_priv_offset;
167
168     i = 0;
169     viaScreen->extensions[i++] = &driReadDrawableExtension;
170     if ( viaScreen->irqEnabled ) {
171         viaScreen->extensions[i++] = &driSwapControlExtension.base;
172         viaScreen->extensions[i++] = &driMediaStreamCounterExtension.base;
173     }
174
175     viaScreen->extensions[i++] = NULL;
176     sPriv->extensions = viaScreen->extensions;
177
178     return GL_TRUE;
179 }
180
181 static void
182 viaDestroyScreen(__DRIscreen *sPriv)
183 {
184     viaScreenPrivate *viaScreen = (viaScreenPrivate *)sPriv->private;
185     VIADRIPtr gDRIPriv = (VIADRIPtr)sPriv->pDevPriv;
186
187     drmUnmap(viaScreen->reg, gDRIPriv->regs.size);
188     if (gDRIPriv->agp.size)
189         drmUnmap(viaScreen->agpLinearStart, gDRIPriv->agp.size);
190
191     via_free_empty_buffers(viaScreen->bufs);
192
193     driDestroyOptionInfo(&viaScreen->optionCache);
194
195     FREE(viaScreen);
196     sPriv->private = NULL;
197 }
198
199
200 static GLboolean
201 viaCreateBuffer(__DRIscreen *driScrnPriv,
202                 __DRIdrawable *driDrawPriv,
203                 const struct gl_config *mesaVis,
204                 GLboolean isPixmap)
205 {
206 #if 0
207     viaScreenPrivate *screen = (viaScreenPrivate *) driScrnPriv->private;
208 #endif
209
210     GLboolean swStencil = (mesaVis->stencilBits > 0 && 
211                            mesaVis->depthBits != 24);
212     GLboolean swAccum = mesaVis->accumRedBits > 0;
213
214     if (isPixmap) {
215        /* KW: This needs work, disabled for now:
216         */
217 #if 0
218         driDrawPriv->driverPrivate = (void *)
219             _mesa_create_framebuffer(mesaVis,
220                                      GL_FALSE,  /* software depth buffer? */
221                                      swStencil,
222                                      mesaVis->accumRedBits > 0,
223                                      GL_FALSE   /* s/w alpha planes */);
224
225         return (driDrawPriv->driverPrivate != NULL);
226 #endif
227         return GL_FALSE;
228     }
229     else {
230       struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
231
232       /* The front color, back color and depth renderbuffers are
233        * set up later in calculate_buffer_parameters().
234        * Only create/connect software-based buffers here.
235        */
236
237 #if 000
238       /* This code _should_ be put to use.  We have to move the
239        * viaRenderbuffer members out of the via_context structure.
240        * Those members should just be the renderbuffers hanging off the
241        * gl_framebuffer object.
242        */
243       /* XXX check/fix the offset/pitch parameters! */
244       {
245          driRenderbuffer *frontRb
246             = driNewRenderbuffer(MESA_FORMAT_ARGB8888, NULL,
247                                  screen->bytesPerPixel,
248                                  0, screen->width, driDrawPriv);
249          viaSetSpanFunctions(frontRb, mesaVis);
250          _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
251       }
252
253       if (mesaVis->doubleBufferMode) {
254          driRenderbuffer *backRb
255             = driNewRenderbuffer(MESA_FORMAT_ARGB8888, NULL,
256                                  screen->bytesPerPixel,
257                                  0, screen->width, driDrawPriv);
258          viaSetSpanFunctions(backRb, mesaVis);
259          _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
260       }
261
262       if (mesaVis->depthBits == 16) {
263          driRenderbuffer *depthRb
264             = driNewRenderbuffer(MESA_FORMAT_Z16, NULL,
265                                  screen->bytesPerPixel,
266                                  0, screen->width, driDrawPriv);
267          viaSetSpanFunctions(depthRb, mesaVis);
268          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
269       }
270       else if (mesaVis->depthBits == 24) {
271          driRenderbuffer *depthRb
272             = driNewRenderbuffer(MESA_FORMAT_Z24_S8, NULL,
273                                  screen->bytesPerPixel,
274                                  0, screen->width, driDrawPriv);
275          viaSetSpanFunctions(depthRb, mesaVis);
276          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
277       }
278       else if (mesaVis->depthBits == 32) {
279          driRenderbuffer *depthRb
280             = driNewRenderbuffer(MESA_FORMAT_Z32, NULL,
281                                  screen->bytesPerPixel,
282                                  0, screen->width, driDrawPriv);
283          viaSetSpanFunctions(depthRb, mesaVis);
284          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
285       }
286
287       if (mesaVis->stencilBits > 0 && !swStencil) {
288          driRenderbuffer *stencilRb
289             = driNewRenderbuffer(MESA_FORMAT_S8, NULL,
290                                  screen->bytesPerPixel,
291                                  0, screen->width, driDrawPriv);
292          viaSetSpanFunctions(stencilRb, mesaVis);
293          _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
294       }
295 #endif
296
297       _mesa_add_soft_renderbuffers(fb,
298                                    GL_FALSE, /* color */
299                                    GL_FALSE, /* depth */
300                                    swStencil,
301                                    swAccum,
302                                    GL_FALSE, /* alpha */
303                                    GL_FALSE /* aux */);
304       driDrawPriv->driverPrivate = (void *) fb;
305
306       return (driDrawPriv->driverPrivate != NULL);
307    }
308 }
309
310
311 static void
312 viaDestroyBuffer(__DRIdrawable *driDrawPriv)
313 {
314    _mesa_reference_framebuffer((struct gl_framebuffer **)(&(driDrawPriv->driverPrivate)), NULL);
315 }
316
317 static const __DRIconfig **
318 viaFillInModes( __DRIscreen *psp,
319                 unsigned pixel_bits, GLboolean have_back_buffer )
320 {
321     __DRIconfig **configs;
322     const unsigned back_buffer_factor = (have_back_buffer) ? 2 : 1;
323     GLenum fb_format;
324     GLenum fb_type;
325
326     /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
327      * enough to add support.  Basically, if a context is created with an
328      * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
329      * will never be used.
330      */
331     static const GLenum back_buffer_modes[] = {
332         GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
333     };
334
335     /* The 32-bit depth-buffer mode isn't supported yet, so don't actually
336      * enable it.
337      */
338     static const uint8_t depth_bits_array[4]   = { 0, 16, 24, 32 };
339     static const uint8_t stencil_bits_array[4] = { 0,  0,  8,  0 };
340     uint8_t msaa_samples_array[1] = { 0 };
341     const unsigned depth_buffer_factor = 3;
342
343     if ( pixel_bits == 16 ) {
344         fb_format = GL_RGB;
345         fb_type = GL_UNSIGNED_SHORT_5_6_5;
346     }
347     else {
348         fb_format = GL_BGRA;
349         fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
350     }
351
352     configs = driCreateConfigs(fb_format, fb_type,
353                                depth_bits_array, stencil_bits_array,
354                                depth_buffer_factor, back_buffer_modes,
355                                back_buffer_factor,
356                                msaa_samples_array, 1, GL_TRUE);
357     if (configs == NULL) {
358         fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
359                 __LINE__);
360         return NULL;
361     }
362
363     return (const __DRIconfig **) configs;
364 }
365
366
367 /**
368  * This is the driver specific part of the createNewScreen entry point.
369  * 
370  * \todo maybe fold this into intelInitDriver
371  *
372  * \return the struct gl_config supported by this driver
373  */
374 static const __DRIconfig **
375 viaInitScreen(__DRIscreen *psp)
376 {
377    static const __DRIversion ddx_expected = { VIA_DRIDDX_VERSION_MAJOR,
378                                               VIA_DRIDDX_VERSION_MINOR,
379                                               VIA_DRIDDX_VERSION_PATCH };
380    static const __DRIversion dri_expected = { 4, 0, 0 };
381    static const __DRIversion drm_expected = { 2, 3, 0 };
382    static const char *driver_name = "Unichrome";
383    VIADRIPtr dri_priv = (VIADRIPtr) psp->pDevPriv;
384
385    if ( ! driCheckDriDdxDrmVersions2( driver_name,
386                                       &psp->dri_version, & dri_expected,
387                                       &psp->ddx_version, & ddx_expected,
388                                       &psp->drm_version, & drm_expected) )
389       return NULL;
390
391    if (!viaInitDriver(psp))
392        return NULL;
393
394    return viaFillInModes( psp, dri_priv->bytesPerPixel * 8, GL_TRUE );
395
396 }
397
398
399 /**
400  * Get information about previous buffer swaps.
401  */
402 static int
403 getSwapInfo( __DRIdrawable *dPriv, __DRIswapInfo * sInfo )
404 {
405    struct via_context *vmesa;
406
407    if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
408         || (dPriv->driContextPriv->driverPrivate == NULL)
409         || (sInfo == NULL) ) {
410       return -1;
411    }
412
413    vmesa = (struct via_context *) dPriv->driContextPriv->driverPrivate;
414    sInfo->swap_count = vmesa->swap_count;
415    sInfo->swap_ust = vmesa->swap_ust;
416    sInfo->swap_missed_count = vmesa->swap_missed_count;
417
418    sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
419        ? driCalculateSwapUsage( dPriv, 0, vmesa->swap_missed_ust )
420        : 0.0;
421
422    return 0;
423 }
424
425 const struct __DriverAPIRec driDriverAPI = {
426    .InitScreen      = viaInitScreen,
427    .DestroyScreen   = viaDestroyScreen,
428    .CreateContext   = viaCreateContext,
429    .DestroyContext  = viaDestroyContext,
430    .CreateBuffer    = viaCreateBuffer,
431    .DestroyBuffer   = viaDestroyBuffer,
432    .SwapBuffers     = viaSwapBuffers,
433    .MakeCurrent     = viaMakeCurrent,
434    .UnbindContext   = viaUnbindContext,
435    .GetSwapInfo     = getSwapInfo,
436    .GetDrawableMSC  = driDrawableGetMSC32,
437    .WaitForMSC      = driWaitForMSC32,
438    .WaitForSBC      = NULL,
439    .SwapBuffersMSC  = NULL
440 };
441
442 /* This is the table of extensions that the loader will dlsym() for. */
443 PUBLIC const __DRIextension *__driDriverExtensions[] = {
444     &driCoreExtension.base,
445     &driLegacyExtension.base,
446     NULL
447 };