~ubuntu-branches/ubuntu/maverick/cairo-dock/maverick

« back to all changes in this revision

Viewing changes to src/gldit/cairo-dock-opengl.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthieu Baerts (matttbe)
  • Date: 2010-08-09 23:26:12 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20100809232612-yp4c6ig3jt1bzpdv
Tags: 2.2.0~0beta4-0ubuntu1
* New Upstream Version (LP: #614624)
* Fixed a few bugs on LP:
 - LP: #518453: Dock appears under all windows
                 (Compiz - fullscreen window)
 - LP: #521369: Separator are not removed when closing
                 grouped windows
 - LP: #521762: Some sentences are not correct
 - LP: #526466: Icons of apps with same class shouldn't
                 be stacked by default
 - LP: #535083: Dialogues looks ugly when a lot of them
                 appears at the same time
 - More details on the 'ChangeLog' file
* debian/rules:
 - Autotools has been replaced by CMake
 - Man pages are now included in the source code
* debian/copyright:
 - Updated with the new pathes and new files
* debian/control:
 - Autotools has been replaced by CMake
 - Added libcurl4-gnutls-dev as Build-deps
 - Bump Standard-Version to 3.9.1
* debian/cairo-dock-core.install:
 - Man pages are now included in the source code
 - All sonames are now installed into lib32 or lib64
* debian/cairo-dock-dev.install:
 - pkgconfig is now installed into lib32 or lib64

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
* This file is a part of the Cairo-Dock project
 
3
*
 
4
* Copyright : (C) see the 'copyright' file.
 
5
* E-mail    : see the 'copyright' file.
 
6
*
 
7
* This program is free software; you can redistribute it and/or
 
8
* modify it under the terms of the GNU General Public License
 
9
* as published by the Free Software Foundation; either version 3
 
10
* of the License, or (at your option) any later version.
 
11
*
 
12
* This program is distributed in the hope that it will be useful,
 
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
* GNU General Public License for more details.
 
16
* You should have received a copy of the GNU General Public License
 
17
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include <string.h>
 
21
#include <math.h>
 
22
#include <stdlib.h>
 
23
 
 
24
#include <gdk/gdkx.h>
 
25
#include <gtk/gtkgl.h>
 
26
 
 
27
#include <X11/extensions/Xrender.h>
 
28
#include <GL/glx.h>
 
29
#include <GL/glxext.h>
 
30
#include <GL/glu.h>
 
31
 
 
32
#include "cairo-dock-log.h"
 
33
#include "cairo-dock-dock-factory.h"
 
34
#include "cairo-dock-load.h"
 
35
#include "cairo-dock-internal-icons.h"
 
36
#include "cairo-dock-internal-system.h"
 
37
#include "cairo-dock-draw-opengl.h"
 
38
#include "cairo-dock-X-manager.h"
 
39
#include "cairo-dock-opengl.h"
 
40
 
 
41
CairoDockGLConfig g_openglConfig;
 
42
gboolean g_bUseOpenGL = FALSE;
 
43
 
 
44
extern CairoContainer *g_pPrimaryContainer;
 
45
extern CairoDockDesktopGeometry g_desktopGeometry;
 
46
extern CairoDockDesktopBackground *g_pFakeTransparencyDesktopBg;
 
47
extern gboolean g_bEasterEggs;
 
48
 
 
49
static inline gboolean _check_extension (const char *extName, const gchar *cExtensions)
 
50
{
 
51
        g_return_val_if_fail (cExtensions != NULL, FALSE);
 
52
        /*
 
53
        ** Search for extName in the extensions string.  Use of strstr()
 
54
        ** is not sufficient because extension names can be prefixes of
 
55
        ** other extension names.  Could use strtok() but the constant
 
56
        ** string returned by glGetString can be in read-only memory.
 
57
        */
 
58
        char *p = (char *) cExtensions;
 
59
 
 
60
        char *end;
 
61
        int extNameLen;
 
62
 
 
63
        extNameLen = strlen(extName);
 
64
        end = p + strlen(p);
 
65
 
 
66
        while (p < end)
 
67
        {
 
68
                int n = strcspn(p, " ");
 
69
                if ((extNameLen == n) && (strncmp(extName, p, n) == 0))
 
70
                {
 
71
                        return TRUE;
 
72
                }
 
73
                p += (n + 1);
 
74
        }
 
75
        return FALSE;
 
76
}
 
77
static gboolean _check_gl_extension (const char *extName)
 
78
{
 
79
        const gchar *glExtensions = glGetString (GL_EXTENSIONS);
 
80
        return _check_extension (extName, glExtensions);
 
81
}
 
82
static gboolean _check_client_glx_extension (const char *extName)
 
83
{
 
84
        Display *display = gdk_x11_get_default_xdisplay ();
 
85
        int screen = 0;
 
86
        //const gchar *glxExtensions = glXQueryExtensionsString (display, screen);
 
87
        const gchar *glxExtensions = glXGetClientString (display,GLX_EXTENSIONS);
 
88
        return _check_extension (extName, glxExtensions);
 
89
}
 
90
 
 
91
 
 
92
static inline XVisualInfo *_get_visual_from_fbconfigs (GLXFBConfig *pFBConfigs, int iNumOfFBConfigs, Display *XDisplay)
 
93
{
 
94
        XRenderPictFormat *pPictFormat;
 
95
        XVisualInfo *pVisInfo = NULL;
 
96
        int i;
 
97
        for (i = 0; i < iNumOfFBConfigs; i++)
 
98
        {
 
99
                pVisInfo = glXGetVisualFromFBConfig (XDisplay, pFBConfigs[i]);
 
100
                if (!pVisInfo)
 
101
                {
 
102
                        cd_warning ("this FBConfig has no visual.");
 
103
                        continue;
 
104
                }
 
105
                
 
106
                pPictFormat = XRenderFindVisualFormat (XDisplay, pVisInfo->visual);
 
107
                if (!pPictFormat)
 
108
                {
 
109
                        cd_warning ("this visual has an unknown format.");
 
110
                        XFree (pVisInfo);
 
111
                        pVisInfo = NULL;
 
112
                        continue;
 
113
                }
 
114
                
 
115
                if (pPictFormat->direct.alphaMask > 0)
 
116
                {
 
117
                        cd_message ("Strike, found a GLX visual with alpha-support !");
 
118
                        break;
 
119
                }
 
120
 
 
121
                XFree (pVisInfo);
 
122
                pVisInfo = NULL;
 
123
        }
 
124
        return pVisInfo;
 
125
}
 
126
 
 
127
gboolean cairo_dock_initialize_opengl_backend (gboolean bToggleIndirectRendering, gboolean bForceOpenGL)  // taken from a MacSlow's exemple.
 
128
{
 
129
        memset (&g_openglConfig, 0, sizeof (CairoDockGLConfig));
 
130
        g_bUseOpenGL = FALSE;
 
131
        g_openglConfig.bHasBeenForced = bForceOpenGL;
 
132
        gboolean bStencilBufferAvailable, bAlphaAvailable;
 
133
        Display *XDisplay = gdk_x11_get_default_xdisplay ();
 
134
        
 
135
        //\_________________ On cherche un visual qui reponde a tous les criteres.
 
136
        GLXFBConfig *pFBConfigs;
 
137
        XRenderPictFormat *pPictFormat = NULL;
 
138
        int doubleBufferAttributes[] = {
 
139
                GLX_DRAWABLE_TYPE,      GLX_WINDOW_BIT,
 
140
                GLX_RENDER_TYPE,                GLX_RGBA_BIT,
 
141
                GLX_DOUBLEBUFFER,       True,
 
142
                GLX_RED_SIZE,           1,
 
143
                GLX_GREEN_SIZE,                 1,
 
144
                GLX_BLUE_SIZE,          1,
 
145
                GLX_DEPTH_SIZE,                 1,
 
146
                GLX_ALPHA_SIZE,                 1,
 
147
                GLX_STENCIL_SIZE,       1,
 
148
                /// a tester ...
 
149
                GLX_SAMPLE_BUFFERS_ARB, 1,
 
150
                GLX_SAMPLES_ARB, 4,
 
151
                /*GL_MULTISAMPLEBUFFERS,        1,
 
152
                GL_MULTISAMPLESAMPLES,  2,*/
 
153
                None};
 
154
        
 
155
        XVisualInfo *pVisInfo = NULL;
 
156
        int iNumOfFBConfigs = 0;
 
157
        pFBConfigs = glXChooseFBConfig (XDisplay,
 
158
                DefaultScreen (XDisplay),
 
159
                doubleBufferAttributes,
 
160
                &iNumOfFBConfigs);
 
161
        cd_debug ("got %d FBConfig(s)", iNumOfFBConfigs);
 
162
        bStencilBufferAvailable = TRUE;
 
163
        bAlphaAvailable = TRUE;
 
164
        
 
165
        pVisInfo = _get_visual_from_fbconfigs (pFBConfigs, iNumOfFBConfigs, XDisplay);
 
166
        if (pFBConfigs)
 
167
                XFree (pFBConfigs);
 
168
        
 
169
        //\_________________ Si pas trouve, on en cherche un moins contraignant.
 
170
        if (pVisInfo == NULL)
 
171
        {
 
172
                cd_warning ("couldn't find an appropriate visual, trying to get one without Stencil buffer\n(it may cause some little deterioration in the rendering) ...");
 
173
                doubleBufferAttributes[16] = None;
 
174
                pFBConfigs = glXChooseFBConfig (XDisplay,
 
175
                        DefaultScreen (XDisplay),
 
176
                        doubleBufferAttributes,
 
177
                        &iNumOfFBConfigs);
 
178
                cd_debug ("this time got %d FBConfig(s)", iNumOfFBConfigs);
 
179
                bStencilBufferAvailable = FALSE;
 
180
                bAlphaAvailable = TRUE;
 
181
                
 
182
                pVisInfo = _get_visual_from_fbconfigs (pFBConfigs, iNumOfFBConfigs, XDisplay);
 
183
                if (pFBConfigs)
 
184
                        XFree (pFBConfigs);
 
185
        }
 
186
        
 
187
        //\_________________ Si toujours rien, on essaye avec la methode de gdkgl.
 
188
        if (pVisInfo == NULL)
 
189
        {
 
190
                cd_warning ("still couldn't find an appropriate visual ourself, trying something else, this may not work with some drivers ...");
 
191
                g_openglConfig.pGlConfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB |
 
192
                        GDK_GL_MODE_ALPHA |
 
193
                        GDK_GL_MODE_DEPTH |
 
194
                        GDK_GL_MODE_DOUBLE |
 
195
                        GDK_GL_MODE_STENCIL);
 
196
                bStencilBufferAvailable = TRUE;
 
197
                bAlphaAvailable = TRUE;
 
198
                
 
199
                if (g_openglConfig.pGlConfig == NULL)
 
200
                {
 
201
                        cd_warning ("no luck, trying without double-buffer and stencil ...");
 
202
                        g_openglConfig.pGlConfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB |
 
203
                                GDK_GL_MODE_ALPHA |
 
204
                                GDK_GL_MODE_DEPTH);
 
205
                        bStencilBufferAvailable = FALSE;
 
206
                        bAlphaAvailable = TRUE;
 
207
                }
 
208
        }
 
209
        
 
210
        //\_________________ Si toujours rien et si l'utilisateur n'en demord pas, on en cherche un sans canal alpha.
 
211
        if (pVisInfo == NULL && g_openglConfig.pGlConfig == NULL && bForceOpenGL)
 
212
        {
 
213
                cd_warning ("we could not get an ARGB-visual, trying to get an RGB one (fake transparency will be used in return) ...");
 
214
                g_openglConfig.bAlphaAvailable = FALSE;
 
215
                doubleBufferAttributes[14] = None;
 
216
                int i, iNumOfFBConfigs;
 
217
                pFBConfigs = glXChooseFBConfig (XDisplay,
 
218
                        DefaultScreen (XDisplay),
 
219
                        doubleBufferAttributes,
 
220
                        &iNumOfFBConfigs);
 
221
                bStencilBufferAvailable = FALSE;
 
222
                bAlphaAvailable = FALSE;
 
223
                cd_debug ("got %d FBConfig(s) without alpha channel", iNumOfFBConfigs);
 
224
                for (i = 0; i < iNumOfFBConfigs; i++)
 
225
                {
 
226
                        pVisInfo = glXGetVisualFromFBConfig (XDisplay, pFBConfigs[i]);
 
227
                        if (!pVisInfo)
 
228
                        {
 
229
                                cd_warning ("this FBConfig has no visual.");
 
230
                                XFree (pVisInfo);
 
231
                                pVisInfo = NULL;
 
232
                        }
 
233
                        else
 
234
                                break;
 
235
                }
 
236
                if (pFBConfigs)
 
237
                        XFree (pFBConfigs);
 
238
                
 
239
                if (pVisInfo == NULL)
 
240
                {
 
241
                        cd_warning ("still no visual, this is the last chance");
 
242
                        pVisInfo = glXChooseVisual (XDisplay,
 
243
                                DefaultScreen (XDisplay),
 
244
                                doubleBufferAttributes);
 
245
                }
 
246
        }
 
247
        g_openglConfig.bStencilBufferAvailable = bStencilBufferAvailable;
 
248
        g_openglConfig.bAlphaAvailable = bAlphaAvailable;
 
249
        
 
250
        //\_________________ Si rien de chez rien, on quitte.
 
251
        if (pVisInfo == NULL && g_openglConfig.pGlConfig == NULL)
 
252
        {
 
253
                cd_warning ("couldn't find a suitable GLX Visual, OpenGL can't be used.\n (sorry to say that, but your graphic card and/or its driver is crappy)");
 
254
                return FALSE;
 
255
        }
 
256
        
 
257
        //\_________________ On en deduit une config opengl valide pour les widgets gtk.
 
258
        if (pVisInfo != NULL)
 
259
        {
 
260
                cd_message ("ok, got a visual");
 
261
                g_openglConfig.pGlConfig = gdk_x11_gl_config_new_from_visualid (pVisInfo->visualid);
 
262
                XFree (pVisInfo);
 
263
        }
 
264
        g_return_val_if_fail (g_openglConfig.pGlConfig != NULL, FALSE);
 
265
        g_bUseOpenGL = TRUE;
 
266
        
 
267
        //\_________________ On regarde si le rendu doit etre indirect ou pas.
 
268
        g_openglConfig.bIndirectRendering = bToggleIndirectRendering;
 
269
        /**if (glXQueryVersion(XDisplay, &g_openglConfig.iGlxMajor, &g_openglConfig.iGlxMinor) == False)
 
270
        {
 
271
                cd_warning ("GLX not available !\nFear the worst !");
 
272
        }
 
273
        else
 
274
        {
 
275
                if (g_openglConfig.iGlxMajor <= 1 && g_openglConfig.iGlxMinor < 3)  // on a besoin de GLX >= 1.3 pour les pbuffers; mais si on a l'extension GLX_SGIX_pbuffer et un version inferieure, ca marche quand meme.
 
276
                {
 
277
                        if (! _check_client_glx_extension ("GLX_SGIX_pbuffer"))
 
278
                        {
 
279
                                cd_warning ("No pbuffer extension in GLX.\n this might affect the drawing of some applets which are inside a dock");
 
280
                        }
 
281
                        else
 
282
                        {
 
283
                                cd_warning ("GLX version too old (%d.%d).\nCairo-Dock needs at least GLX 1.3. Indirect rendering will be toggled on/off as a workaround.", g_openglConfig.iGlxMajor, g_openglConfig.iGlxMinor);
 
284
                                g_openglConfig.bPBufferAvailable = TRUE;
 
285
                                g_openglConfig.bIndirectRendering = ! bToggleIndirectRendering;
 
286
                        }
 
287
                }
 
288
                else
 
289
                {
 
290
                        g_openglConfig.bPBufferAvailable = TRUE;
 
291
                }
 
292
        }*/
 
293
        
 
294
        //\_________________ on verifier les capacites des textures.
 
295
        g_openglConfig.bTextureFromPixmapAvailable = _check_client_glx_extension ("GLX_EXT_texture_from_pixmap");
 
296
        if (g_openglConfig.bTextureFromPixmapAvailable)
 
297
        {
 
298
                g_openglConfig.bindTexImage = (gpointer)glXGetProcAddress ("glXBindTexImageEXT");
 
299
                g_openglConfig.releaseTexImage = (gpointer)glXGetProcAddress ("glXReleaseTexImageEXT");
 
300
                g_openglConfig.bTextureFromPixmapAvailable = (g_openglConfig.bindTexImage && g_openglConfig.releaseTexImage);
 
301
        }
 
302
        
 
303
        return TRUE;
 
304
}
 
305
 
 
306
 
 
307
 
 
308
void cairo_dock_create_icon_fbo (void)  // it has been found that you get a speed boost if your textures is the same size and you use 1 FBO for them. => c'est le cas general dans le dock. Du coup on est gagnant a ne faire qu'un seul FBO pour toutes les icones.
 
309
{
 
310
        if (! g_openglConfig.bFboAvailable)
 
311
                return ;
 
312
        g_return_if_fail (g_openglConfig.iFboId == 0);
 
313
        
 
314
        glGenFramebuffersEXT(1, &g_openglConfig.iFboId);
 
315
        
 
316
        int iWidth = 0, iHeight = 0;
 
317
        int i;
 
318
        for (i = 0; i < CAIRO_DOCK_NB_TYPES; i += 2)
 
319
        {
 
320
                iWidth = MAX (iWidth, myIcons.tIconAuthorizedWidth[i]);
 
321
                iHeight = MAX (iHeight, myIcons.tIconAuthorizedHeight[i]);
 
322
        }
 
323
        if (iWidth == 0)
 
324
                iWidth = 48;
 
325
        if (iHeight == 0)
 
326
                iHeight = 48;
 
327
        iWidth *= (1 + myIcons.fAmplitude);
 
328
        iHeight *= (1 + myIcons.fAmplitude);
 
329
        g_openglConfig.iRedirectedTexture = cairo_dock_load_texture_from_raw_data (NULL, iWidth, iHeight);
 
330
}
 
331
 
 
332
void cairo_dock_destroy_icon_fbo (void)
 
333
{
 
334
        if (g_openglConfig.iFboId == 0)
 
335
                return;
 
336
        glDeleteFramebuffersEXT (1, &g_openglConfig.iFboId);
 
337
        g_openglConfig.iFboId = 0;
 
338
        
 
339
        _cairo_dock_delete_texture (g_openglConfig.iRedirectedTexture);
 
340
        g_openglConfig.iRedirectedTexture = 0;
 
341
}
 
342
 
 
343
/**static GLXPbuffer _cairo_dock_create_pbuffer (int iWidth, int iHeight, GLXContext *pContext)
 
344
{
 
345
        Display *XDisplay = gdk_x11_get_default_xdisplay ();
 
346
        
 
347
        GLXFBConfig *pFBConfigs;
 
348
        XRenderPictFormat *pPictFormat = NULL;
 
349
        int visAttribs[] = {
 
350
                GLX_DRAWABLE_TYPE,      GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
 
351
                GLX_RENDER_TYPE,                GLX_RGBA_BIT,
 
352
                GLX_RED_SIZE,           1,
 
353
                GLX_GREEN_SIZE,                 1,
 
354
                GLX_BLUE_SIZE,          1,
 
355
                GLX_ALPHA_SIZE,                 1,
 
356
                GLX_DEPTH_SIZE,                 1,
 
357
                None};
 
358
        
 
359
        XVisualInfo *pVisInfo = NULL;
 
360
        int i, iNumOfFBConfigs = 0;
 
361
        pFBConfigs = glXChooseFBConfig (XDisplay,
 
362
                DefaultScreen (XDisplay),
 
363
                visAttribs,
 
364
                &iNumOfFBConfigs);
 
365
        if (iNumOfFBConfigs == 0)
 
366
        {
 
367
                cd_warning ("No suitable visual could be found for pbuffer\n this might affect the drawing of some applets which are inside a dock");
 
368
                *pContext = 0;
 
369
                return 0;
 
370
        }
 
371
        cd_debug (" -> %d FBConfig(s) pour le pbuffer", iNumOfFBConfigs);
 
372
        
 
373
        int pbufAttribs [] = {
 
374
                GLX_PBUFFER_WIDTH, iWidth,
 
375
                GLX_PBUFFER_HEIGHT, iHeight,
 
376
                GLX_LARGEST_PBUFFER, True,
 
377
                None};
 
378
        GLXPbuffer pbuffer = glXCreatePbuffer (XDisplay, pFBConfigs[0], pbufAttribs);
 
379
        
 
380
        pVisInfo = glXGetVisualFromFBConfig (XDisplay, pFBConfigs[0]);
 
381
        
 
382
        GdkGLContext *pGlContext = gtk_widget_get_gl_context (g_pMainDock->container.pWidget);
 
383
        GLXContext mainContext = GDK_GL_CONTEXT_GLXCONTEXT (pGlContext);
 
384
        *pContext = glXCreateContext (XDisplay, pVisInfo, mainContext, ! g_openglConfig.bIndirectRendering);
 
385
        
 
386
        XFree (pVisInfo);
 
387
        XFree (pFBConfigs);
 
388
        
 
389
        return pbuffer;
 
390
}
 
391
 
 
392
void cairo_dock_create_icon_pbuffer (void)
 
393
{
 
394
        if (! g_openglConfig.pGlConfig || ! g_openglConfig.bPBufferAvailable)
 
395
                return ;
 
396
        int iWidth = 0, iHeight = 0;
 
397
        int i;
 
398
        for (i = 0; i < CAIRO_DOCK_NB_TYPES; i += 2)
 
399
        {
 
400
                iWidth = MAX (iWidth, myIcons.tIconAuthorizedWidth[i]);
 
401
                iHeight = MAX (iHeight, myIcons.tIconAuthorizedHeight[i]);
 
402
        }
 
403
        if (iWidth == 0)
 
404
                iWidth = 48;
 
405
        if (iHeight == 0)
 
406
                iHeight = 48;
 
407
        iWidth *= (1 + myIcons.fAmplitude);
 
408
        iHeight *= (1 + myIcons.fAmplitude);
 
409
        
 
410
        cd_debug ("%s (%dx%d)", __func__, iWidth, iHeight);
 
411
        if (g_openglConfig.iIconPbufferWidth != iWidth || g_openglConfig.iIconPbufferHeight != iHeight)
 
412
        {
 
413
                Display *XDisplay = gdk_x11_get_default_xdisplay ();
 
414
                if (g_openglConfig.iconPbuffer != 0)
 
415
                {
 
416
                        glXDestroyPbuffer (XDisplay, g_openglConfig.iconPbuffer);
 
417
                        glXDestroyContext (XDisplay, g_openglConfig.iconContext);
 
418
                        g_openglConfig.iconContext = 0;
 
419
                }
 
420
                g_openglConfig.iconPbuffer = _cairo_dock_create_pbuffer (iWidth, iHeight, &g_openglConfig.iconContext);
 
421
                g_openglConfig.iIconPbufferWidth = iWidth;
 
422
                g_openglConfig.iIconPbufferHeight = iHeight;
 
423
                
 
424
                cd_debug ("activating pbuffer, usually buggy drivers will crash here ...");
 
425
                if (g_openglConfig.iconPbuffer != 0 && g_openglConfig.iconContext != 0 && glXMakeCurrent (XDisplay, g_openglConfig.iconPbuffer, g_openglConfig.iconContext))
 
426
                {
 
427
                        glMatrixMode(GL_PROJECTION);
 
428
                        glLoadIdentity();
 
429
                        glOrtho(0, iWidth, 0, iHeight, 0.0, 500.0);
 
430
                        glMatrixMode (GL_MODELVIEW);
 
431
                        
 
432
                        glLoadIdentity();
 
433
                        gluLookAt (0., 0., 3.,
 
434
                                0., 0., 0.,
 
435
                                0.0f, 1.0f, 0.0f);
 
436
                        
 
437
                        glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
 
438
                        glClearDepth (1.0f);
 
439
                }
 
440
                cd_debug (" ok, they are fine enough.\n");
 
441
        }
 
442
}
 
443
 
 
444
void cairo_dock_destroy_icon_pbuffer (void)
 
445
{
 
446
        Display *XDisplay = gdk_x11_get_default_xdisplay ();
 
447
        if (g_openglConfig.iconPbuffer != 0)
 
448
        {
 
449
                glXDestroyPbuffer (XDisplay, g_openglConfig.iconPbuffer);
 
450
                g_openglConfig.iconPbuffer = 0;
 
451
        }
 
452
        if (g_openglConfig.iconContext != 0)
 
453
        {
 
454
                glXDestroyContext (XDisplay, g_openglConfig.iconContext);
 
455
                g_openglConfig.iconContext = 0;
 
456
        }
 
457
        g_openglConfig.iIconPbufferWidth = 0;
 
458
        g_openglConfig.iIconPbufferHeight = 0;
 
459
}*/
 
460
 
 
461
gboolean cairo_dock_begin_draw_icon (Icon *pIcon, CairoContainer *pContainer, gint iRenderingMode)
 
462
{
 
463
        int iWidth, iHeight;
 
464
        if (CAIRO_DOCK_IS_DESKLET (pContainer))
 
465
        {
 
466
                GdkGLContext *pGlContext = gtk_widget_get_gl_context (pContainer->pWidget);
 
467
                GdkGLDrawable *pGlDrawable = gtk_widget_get_gl_drawable (pContainer->pWidget);
 
468
                if (! gdk_gl_drawable_gl_begin (pGlDrawable, pGlContext))
 
469
                        return FALSE;
 
470
                
 
471
                ///cairo_dock_set_ortho_view (pContainer);
 
472
                iWidth = pContainer->iWidth;
 
473
                iHeight = pContainer->iHeight;
 
474
                glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
475
        }
 
476
        else if (g_openglConfig.iFboId != 0)
 
477
        {
 
478
                // on attache la texture au FBO.
 
479
                cairo_dock_get_icon_extent (pIcon, pContainer, &iWidth, &iHeight);
 
480
                if (pContainer == NULL)
 
481
                        pContainer = g_pPrimaryContainer;
 
482
                GdkGLContext *pGlContext = gtk_widget_get_gl_context (pContainer->pWidget);
 
483
                GdkGLDrawable *pGlDrawable = gtk_widget_get_gl_drawable (pContainer->pWidget);
 
484
                if (! gdk_gl_drawable_gl_begin (pGlDrawable, pGlContext))
 
485
                        return FALSE;
 
486
                glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, g_openglConfig.iFboId);  // on redirige sur notre FBO.
 
487
                g_openglConfig.bRedirected = (iRenderingMode == 2);
 
488
                glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
 
489
                        GL_COLOR_ATTACHMENT0_EXT,
 
490
                        GL_TEXTURE_2D,
 
491
                        g_openglConfig.bRedirected ? g_openglConfig.iRedirectedTexture : pIcon->iIconTexture,
 
492
                        0);  // attach the texture to FBO color attachment point.
 
493
                
 
494
                GLenum status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
 
495
                if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
 
496
                {
 
497
                        cd_warning ("FBO not ready for %s (tex:%d)", pIcon->cName, pIcon->iIconTexture);
 
498
                        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);  // switch back to window-system-provided framebuffer
 
499
                        glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
 
500
                                GL_COLOR_ATTACHMENT0_EXT,
 
501
                                GL_TEXTURE_2D,
 
502
                                0,
 
503
                                0);
 
504
                        return FALSE;
 
505
                }
 
506
                
 
507
                // on se positionne au milieu.
 
508
                /**cairo_dock_set_ortho_view (pContainer);
 
509
                glLoadIdentity ();
 
510
                glTranslatef (iWidth/2, iHeight/2, - iHeight/2);*/
 
511
                
 
512
                if (iRenderingMode != 1)
 
513
                        glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
514
        }
 
515
        /**else if (g_openglConfig.iconContext != 0)
 
516
        {
 
517
                Display *XDisplay = gdk_x11_get_default_xdisplay ();
 
518
                if (! glXMakeCurrent (XDisplay, g_openglConfig.iconPbuffer, g_openglConfig.iconContext))
 
519
                        return FALSE;
 
520
                glLoadIdentity ();
 
521
                glTranslatef (g_openglConfig.iIconPbufferWidth/2, g_openglConfig.iIconPbufferHeight/2, - g_openglConfig.iIconPbufferHeight/2);
 
522
        }*/
 
523
        else
 
524
                return FALSE;
 
525
        
 
526
        if (pContainer->bPerspectiveView)
 
527
        {
 
528
                cairo_dock_set_ortho_view (pContainer);
 
529
                g_openglConfig.bSetPerspective = TRUE;
 
530
        }
 
531
        else
 
532
        {
 
533
                cairo_dock_set_ortho_view (pContainer);  // au demarrage, le contexte n'a pas encore de vue.
 
534
                glLoadIdentity ();
 
535
                glTranslatef (iWidth/2, iHeight/2, - iHeight/2);
 
536
        }
 
537
        
 
538
        glColor4f(1., 1., 1., 1.);
 
539
        
 
540
        glScalef (1., -1., 1.);
 
541
        
 
542
        return TRUE;
 
543
}
 
544
 
 
545
void cairo_dock_end_draw_icon (Icon *pIcon, CairoContainer *pContainer)
 
546
{
 
547
        g_return_if_fail (pIcon->iIconTexture != 0);
 
548
        
 
549
        if (CAIRO_DOCK_IS_DESKLET (pContainer))
 
550
        {
 
551
                // copie dans notre texture
 
552
                glEnable (GL_TEXTURE_2D);
 
553
                glBindTexture (GL_TEXTURE_2D, pIcon->iIconTexture);
 
554
                glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
555
                glEnable(GL_BLEND);
 
556
                glBlendFunc (GL_ZERO, GL_ONE);
 
557
                glColor4f(1., 1., 1., 1.);
 
558
                
 
559
                int iWidth, iHeight;  // taille de la texture
 
560
                cairo_dock_get_icon_extent (pIcon, pContainer, &iWidth, &iHeight);
 
561
                int x = (pContainer->iWidth - iWidth)/2;
 
562
                int y = (pContainer->iHeight - iHeight)/2;
 
563
                glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, x, y, iWidth, iHeight, 0);  // target, num mipmap, format, x,y, w,h, border.
 
564
                
 
565
                glDisable (GL_TEXTURE_2D);
 
566
                glDisable (GL_BLEND);
 
567
        }
 
568
        else if (g_openglConfig.iFboId != 0)
 
569
        {
 
570
                if (g_openglConfig.bRedirected)  // copie dans notre texture
 
571
                {
 
572
                        glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
 
573
                                GL_COLOR_ATTACHMENT0_EXT,
 
574
                                GL_TEXTURE_2D,
 
575
                                pIcon->iIconTexture,
 
576
                                0);  // maintenant on dessine dans la texture de l'icone.
 
577
                        _cairo_dock_enable_texture ();
 
578
                        _cairo_dock_set_blend_source ();
 
579
                        
 
580
                        int iWidth, iHeight;  // taille de la texture
 
581
                        cairo_dock_get_icon_extent (pIcon, pContainer, &iWidth, &iHeight);
 
582
                        
 
583
                        glLoadIdentity ();
 
584
                        glTranslatef (iWidth/2, iHeight/2, - iHeight/2);
 
585
                        _cairo_dock_apply_texture_at_size_with_alpha (g_openglConfig.iRedirectedTexture, iWidth, iHeight, 1.);
 
586
                        
 
587
                        _cairo_dock_disable_texture ();
 
588
                        g_openglConfig.bRedirected = FALSE;
 
589
                }
 
590
                glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);  // switch back to window-system-provided framebuffer
 
591
                glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
 
592
                        GL_COLOR_ATTACHMENT0_EXT,
 
593
                        GL_TEXTURE_2D,
 
594
                        0,
 
595
                        0);  // on detache la texture (precaution).
 
596
                //glGenerateMipmapEXT(GL_TEXTURE_2D);  // si on utilise les mipmaps, il faut les generer explicitement avec les FBO.
 
597
        }
 
598
        /**else
 
599
        {
 
600
                x = (g_openglConfig.iIconPbufferWidth - iWidth)/2;
 
601
                y = (g_openglConfig.iIconPbufferHeight - iHeight)/2;
 
602
        }*/
 
603
                
 
604
        ///if (CAIRO_DOCK_IS_DESKLET (pContainer))
 
605
        if (pContainer && g_openglConfig.bSetPerspective)
 
606
        {
 
607
                cairo_dock_set_perspective_view (pContainer);
 
608
                g_openglConfig.bSetPerspective = FALSE;
 
609
        }
 
610
        
 
611
        if (pContainer)
 
612
        {
 
613
                GdkGLDrawable *pGlDrawable = gtk_widget_get_gl_drawable (pContainer->pWidget);
 
614
                gdk_gl_drawable_gl_end (pGlDrawable);
 
615
        }
 
616
}
 
617
 
 
618
 
 
619
 
 
620
static inline void _cairo_dock_set_perspective_view (int iWidth, int iHeight)
 
621
{
 
622
        glMatrixMode(GL_PROJECTION);
 
623
        glLoadIdentity();
 
624
        gluPerspective(60.0, 1.0*(GLfloat)iWidth/(GLfloat)iHeight, 1., 4*iHeight);
 
625
        glViewport(0, 0, iWidth, iHeight);
 
626
        glMatrixMode (GL_MODELVIEW);
 
627
        
 
628
        glLoadIdentity ();
 
629
        gluLookAt (0, 0, 3., 0, 0, 0., 0.0f, 1.0f, 0.0f);
 
630
        //gluLookAt (0/2, 0/2, 3., 0/2, 0/2, 0., 0.0f, 1.0f, 0.0f);
 
631
        glTranslatef (0., 0., -iHeight*(sqrt(3)/2) - 1);
 
632
        //glTranslatef (iWidth/2, iHeight/2, -iHeight*(sqrt(3)/2) - 1);
 
633
}
 
634
void cairo_dock_set_perspective_view (CairoContainer *pContainer)
 
635
{
 
636
        int w, h;
 
637
        if (pContainer->bIsHorizontal)
 
638
        {
 
639
                w = pContainer->iWidth;
 
640
                h = pContainer->iHeight;
 
641
        }
 
642
        else
 
643
        {
 
644
                w = pContainer->iHeight;
 
645
                h = pContainer->iWidth;
 
646
        }
 
647
        _cairo_dock_set_perspective_view (w, h);
 
648
        pContainer->bPerspectiveView = TRUE;
 
649
}
 
650
 
 
651
void cairo_dock_set_perspective_view_for_icon (Icon *pIcon, CairoContainer *pContainer)
 
652
{
 
653
        int w, h;
 
654
        cairo_dock_get_icon_extent (pIcon, pContainer, &w, &h);
 
655
        _cairo_dock_set_perspective_view (w, h);
 
656
}
 
657
 
 
658
static inline void _cairo_dock_set_ortho_view (int iWidth, int iHeight)
 
659
{
 
660
        glMatrixMode(GL_PROJECTION);
 
661
        glLoadIdentity();
 
662
        glOrtho(0, iWidth, 0, iHeight, 0.0, 500.0);
 
663
        glViewport(0, 0, iWidth, iHeight);
 
664
        glMatrixMode (GL_MODELVIEW);
 
665
        
 
666
        glLoadIdentity ();
 
667
        gluLookAt (0/2, 0/2, 3.,
 
668
                0/2, 0/2, 0.,
 
669
                0.0f, 1.0f, 0.0f);
 
670
        glTranslatef (iWidth/2, iHeight/2, - iHeight/2);
 
671
}
 
672
void cairo_dock_set_ortho_view (CairoContainer *pContainer)
 
673
{
 
674
        int w, h;
 
675
        if (pContainer->bIsHorizontal)
 
676
        {
 
677
                w = pContainer->iWidth;
 
678
                h = pContainer->iHeight;
 
679
        }
 
680
        else
 
681
        {
 
682
                w = pContainer->iHeight;
 
683
                h = pContainer->iWidth;
 
684
        }
 
685
        _cairo_dock_set_ortho_view (w, h);
 
686
        pContainer->bPerspectiveView = FALSE;
 
687
}
 
688
 
 
689
void cairo_dock_set_ortho_view_for_icon (Icon *pIcon, CairoContainer *pContainer)
 
690
{
 
691
        int w, h;
 
692
        cairo_dock_get_icon_extent (pIcon, pContainer, &w, &h);
 
693
        _cairo_dock_set_ortho_view (w, h);
 
694
}
 
695
 
 
696
 
 
697
void cairo_dock_apply_desktop_background_opengl (CairoContainer *pContainer)
 
698
{
 
699
        if (! mySystem.bUseFakeTransparency || ! g_pFakeTransparencyDesktopBg || g_pFakeTransparencyDesktopBg->iTexture == 0)
 
700
                return ;
 
701
        
 
702
        glPushMatrix ();
 
703
        gboolean bSetPerspective = pContainer->bPerspectiveView;
 
704
        if (bSetPerspective)
 
705
                cairo_dock_set_ortho_view (pContainer);
 
706
        glLoadIdentity ();
 
707
        _cairo_dock_enable_texture ();
 
708
        _cairo_dock_set_blend_source ();
 
709
        _cairo_dock_set_alpha (1.);
 
710
        glBindTexture (GL_TEXTURE_2D, g_pFakeTransparencyDesktopBg->iTexture);
 
711
        
 
712
        double x, y, w, h, W, H;
 
713
        W = g_desktopGeometry.iXScreenWidth[CAIRO_DOCK_HORIZONTAL];
 
714
        H = g_desktopGeometry.iXScreenHeight[CAIRO_DOCK_HORIZONTAL];
 
715
        if (pContainer->bIsHorizontal)
 
716
        {
 
717
                w = pContainer->iWidth;
 
718
                h = pContainer->iHeight;
 
719
                x = pContainer->iWindowPositionX;
 
720
                y = pContainer->iWindowPositionY;
 
721
        }
 
722
        else
 
723
        {
 
724
                h = pContainer->iWidth;
 
725
                w = pContainer->iHeight;
 
726
                y = pContainer->iWindowPositionX;
 
727
                x = pContainer->iWindowPositionY;
 
728
        }
 
729
        
 
730
        glBegin(GL_QUADS);
 
731
        glTexCoord2f ((x + 0) / W, (y + 0) / H);
 
732
        glVertex3f (0., h, 0.);  // Top Left.
 
733
        
 
734
        glTexCoord2f ((x + w) / W, (y + 0) / H);
 
735
        glVertex3f (w, h, 0.);  // Top Right
 
736
        
 
737
        glTexCoord2f ((x + w) / W, (y + h) / H);
 
738
        glVertex3f (w, 0., 0.);  // Bottom Right
 
739
        
 
740
        glTexCoord2f ((x + 0.) / W, (y + h) / H);
 
741
        glVertex3f (0., 0., 0.);  // Bottom Left
 
742
        glEnd();
 
743
        
 
744
        _cairo_dock_disable_texture ();
 
745
        if (bSetPerspective)
 
746
                cairo_dock_set_perspective_view (pContainer);
 
747
        glPopMatrix ();
 
748
}
 
749
 
 
750
 
 
751
 
 
752
 
 
753
static void _cairo_dock_post_initialize_opengl_backend (GtkWidget* pWidget, gpointer data)  // initialisation necessitant un contexte opengl.
 
754
{
 
755
        static gboolean bChecked=FALSE;
 
756
        if (bChecked)
 
757
                return;
 
758
        GdkGLContext* pGlContext = gtk_widget_get_gl_context (pWidget);
 
759
        GdkGLDrawable* pGlDrawable = gtk_widget_get_gl_drawable (pWidget);
 
760
        if (!gdk_gl_drawable_gl_begin (pGlDrawable, pGlContext))
 
761
                return ;
 
762
        
 
763
        bChecked = TRUE;
 
764
        g_openglConfig.bNonPowerOfTwoAvailable = _check_gl_extension ("GL_ARB_texture_non_power_of_two");
 
765
        g_openglConfig.bFboAvailable = _check_gl_extension ("GL_EXT_framebuffer_object");
 
766
        if (!g_openglConfig.bFboAvailable)
 
767
                cd_warning ("No FBO support, some applets will be invisible if placed inside the dock.");
 
768
        
 
769
        g_openglConfig.bNonPowerOfTwoAvailable = _check_gl_extension ("GL_ARB_texture_non_power_of_two");
 
770
        g_openglConfig.bAccumBufferAvailable = _check_gl_extension ("GL_SUN_slice_accum");
 
771
        
 
772
        GLfloat fMaximumAnistropy = 0.;
 
773
        if (_check_gl_extension ("GL_EXT_texture_filter_anisotropic"))
 
774
        {
 
775
                glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fMaximumAnistropy);
 
776
                glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fMaximumAnistropy);
 
777
        }
 
778
        
 
779
        cd_debug ("OpenGL config summary :\n - bNonPowerOfTwoAvailable : %d\n - bFboAvailable : %d\n - direct rendering : %d\n - bTextureFromPixmapAvailable : %d\n - bAccumBufferAvailable : %d\n - Anisotroy filtering level max : %.1f\n - OpenGL version: %s\n - OpenGL vendor: %s\n - OpenGL renderer: %s\n\n",
 
780
                g_openglConfig.bNonPowerOfTwoAvailable,
 
781
                g_openglConfig.bFboAvailable,
 
782
                !g_openglConfig.bIndirectRendering,
 
783
                g_openglConfig.bTextureFromPixmapAvailable,
 
784
                g_openglConfig.bAccumBufferAvailable,
 
785
                fMaximumAnistropy,
 
786
                glGetString (GL_VERSION),
 
787
                glGetString (GL_VENDOR),
 
788
                glGetString (GL_RENDERER));
 
789
        
 
790
        gdk_gl_drawable_gl_end (pGlDrawable);
 
791
}
 
792
 
 
793
 
 
794
static void _reset_opengl_context (GtkWidget* pWidget, gpointer data)
 
795
{
 
796
        if (! g_bUseOpenGL)
 
797
                return ;
 
798
        
 
799
        GdkGLContext* pGlContext = gtk_widget_get_gl_context (pWidget);
 
800
        GdkGLDrawable* pGlDrawable = gtk_widget_get_gl_drawable (pWidget);
 
801
        if (!gdk_gl_drawable_gl_begin (pGlDrawable, pGlContext))
 
802
                return ;
 
803
        
 
804
        glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
 
805
        glClearDepth (1.0f);
 
806
        glClearStencil (0);
 
807
        glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
 
808
        
 
809
        /// a tester ...
 
810
        if (g_bEasterEggs)
 
811
                glEnable (GL_MULTISAMPLE_ARB);
 
812
        
 
813
        glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);  // GL_MODULATE / GL_DECAL /  GL_BLEND
 
814
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 
815
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
816
        glTexParameteri (GL_TEXTURE_2D,
 
817
                GL_TEXTURE_MIN_FILTER,
 
818
                GL_LINEAR_MIPMAP_LINEAR);
 
819
        glTexParameteri (GL_TEXTURE_2D,
 
820
                GL_TEXTURE_MAG_FILTER,
 
821
                GL_LINEAR);
 
822
        
 
823
        gdk_gl_drawable_gl_end (pGlDrawable);
 
824
}
 
825
void cairo_dock_set_gl_capabilities (GtkWidget *pWindow)
 
826
{
 
827
        gboolean bFirstContainer = (! g_pPrimaryContainer || ! g_pPrimaryContainer->pWidget);
 
828
        GdkGLContext *pMainGlContext = (bFirstContainer ? NULL : gtk_widget_get_gl_context (g_pPrimaryContainer->pWidget));  // NULL si on est en train de creer la fenetre du main dock, ce qui nous convient.
 
829
        gtk_widget_set_gl_capability (pWindow,
 
830
                g_openglConfig.pGlConfig,
 
831
                pMainGlContext,  // on partage les ressources entre les contextes.
 
832
                ! g_openglConfig.bIndirectRendering,  // TRUE <=> direct connection to the graphics system.
 
833
                GDK_GL_RGBA_TYPE);
 
834
        if (bFirstContainer)  // c'est donc le 1er container cree, on finit l'initialisation du backend opengl.
 
835
                g_signal_connect (G_OBJECT (pWindow),
 
836
                        "realize",
 
837
                        G_CALLBACK (_cairo_dock_post_initialize_opengl_backend),
 
838
                        NULL);
 
839
        g_signal_connect_after (G_OBJECT (pWindow),
 
840
                "realize",
 
841
                G_CALLBACK (_reset_opengl_context),
 
842
                NULL);
 
843
}