Removed invalid EGL config attribute
[glmemperf] / native_x11.c
1 /**
2  * OpenGL ES 2.0 memory performance estimator
3  * Copyright (C) 2009 Nokia
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * \author Sami Kyöstilä <sami.kyostila@nokia.com>
20  *
21  *  Native windowing implementation for X11
22  */
23 #include <EGL/egl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <X11/Xatom.h>
30 #include "native.h"
31
32 EGLBoolean nativeCreateDisplay(EGLNativeDisplayType *pNativeDisplay)
33 {
34     *pNativeDisplay = XOpenDisplay(NULL);
35
36     if (!*pNativeDisplay)
37     {
38         fprintf(stderr, "XOpenDisplay failed\n");
39         return EGL_FALSE;
40     }
41     
42     return EGL_TRUE;
43 }
44
45 void nativeDestroyDisplay(EGLNativeDisplayType nativeDisplay)
46 {
47     XCloseDisplay(nativeDisplay);
48 }
49
50 static int runningOnFremantle(void)
51 {
52     /* Somewhat hacky way of detecting fremantle */
53     FILE* f = popen("pgrep hildon-desktop", "r");
54     int found = 0;
55
56     while (!feof(f))
57     {
58         int pid;
59         if (fscanf(f, "%d", &pid) == 1)
60         {
61             found = 1;
62         }
63     }
64     pclose(f);
65     return found;
66 }
67
68 EGLBoolean nativeCreateWindow(EGLNativeDisplayType nativeDisplay, EGLDisplay dpy, EGLConfig config, 
69                               const char *title, int width, int height, EGLNativeWindowType *nativeWindow)
70 {
71     Window rootWindow = DefaultRootWindow(nativeDisplay);
72     EGLint visualId;
73     Window window;
74     XVisualInfo* visual;
75     XTextProperty windowTitle;
76     XSetWindowAttributes winAttrs;
77     XWindowAttributes rootAttrs;
78     XVisualInfo visualInfo;
79     int visualCount = 0;
80
81     if (eglGetConfigAttrib(dpy, config, EGL_NATIVE_VISUAL_ID, &visualId) != EGL_TRUE)
82     {
83         fprintf(stderr, "eglGetConfigAttrib failed: %x\n", eglGetError());
84         return EGL_FALSE;
85     }
86
87     visualInfo.visualid = visualId;
88     visualInfo.screen = DefaultScreen(nativeDisplay);
89     visual = XGetVisualInfo(nativeDisplay, VisualIDMask | VisualScreenMask, &visualInfo, &visualCount);
90
91     if (!visualCount)
92     {
93         fprintf(stderr, "XGetVisualInfo failed\n");
94         return EGL_FALSE;
95     }
96
97     XGetWindowAttributes(nativeDisplay, rootWindow, &rootAttrs);
98
99     winAttrs.background_pixmap = None;
100     winAttrs.border_pixel = 0;
101     winAttrs.colormap = XCreateColormap(nativeDisplay, rootWindow, visual->visual, AllocNone);
102
103     window = XCreateWindow(nativeDisplay, rootWindow, 0, 0,
104                            width, height, 0, visual->depth,
105                            InputOutput, visual->visual,
106                            CWBackPixmap | CWBorderPixel | CWColormap,
107                            &winAttrs);
108
109     if (!window)
110     {
111         fprintf(stderr, "XCreateSimpleWindow failed\n");
112         return EGL_FALSE;
113     }
114
115     /* Enable non-composited mode if possible */
116     if (XVisualIDFromVisual(rootAttrs.visual) == visualId)
117     {
118         Atom nonCompWindow = XInternAtom(nativeDisplay, "_HILDON_NON_COMPOSITED_WINDOW", False);
119         Atom windowType = XInternAtom(nativeDisplay, "_NET_WM_WINDOW_TYPE", False);
120         Atom windowTypeOverride = XInternAtom(nativeDisplay, "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", False);
121         int one = 1;
122
123         XChangeProperty(nativeDisplay, window, nonCompWindow, XA_INTEGER, 32, PropModeReplace, (unsigned char*)&one, 1);
124
125         if (!runningOnFremantle())
126         {
127             XChangeProperty(nativeDisplay, window, windowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&windowTypeOverride, 1);
128         }
129     }
130     else
131     {
132         printf("Warning: using a composited window\n");
133     }
134
135     windowTitle.value    = (unsigned char*)title;
136     windowTitle.encoding = XA_STRING;
137     windowTitle.format   = 8;
138     windowTitle.nitems   = strlen(title);
139     XSetWMName(nativeDisplay, window, &windowTitle);
140     
141     XMapWindow(nativeDisplay, window);
142     XFlush(nativeDisplay);
143
144     /* Set window to fullscreen mode if it matches the screen size */
145     if (rootAttrs.width == width && rootAttrs.height == height)
146     {
147         XEvent xev;
148         Atom wmState = XInternAtom(nativeDisplay, "_NET_WM_STATE", False);
149         Atom wmStateFullscreen = XInternAtom(nativeDisplay, "_NET_WM_STATE_FULLSCREEN", False);
150
151         memset(&xev, 0, sizeof(XEvent));
152         xev.type = ClientMessage;
153         xev.xclient.window = window;
154         xev.xclient.message_type = wmState;
155         xev.xclient.format = 32;
156         xev.xclient.data.l[0] = 1;
157         xev.xclient.data.l[1] = wmStateFullscreen;
158         xev.xclient.data.l[2] = 0;
159         XSendEvent(nativeDisplay, rootWindow, False, SubstructureNotifyMask, &xev);
160     }
161
162     *nativeWindow = window;
163     
164     return EGL_TRUE;
165 }
166
167 void nativeDestroyWindow(EGLNativeDisplayType nativeDisplay, EGLNativeWindowType nativeWindow)
168 {
169     XDestroyWindow(nativeDisplay, nativeWindow);
170 }
171
172 EGLBoolean nativeCreatePixmap(EGLNativeDisplayType nativeDisplay, EGLDisplay dpy, EGLConfig config, 
173                               int width, int height, EGLNativePixmapType *nativePixmap)
174 {
175     Window rootWindow = DefaultRootWindow(nativeDisplay);
176     Pixmap pixmap;
177     int depth;
178
179     if (eglGetConfigAttrib(dpy, config, EGL_BUFFER_SIZE, &depth) != EGL_TRUE)
180     {
181         fprintf(stderr, "eglGetConfigAttrib failed: %x\n", eglGetError());
182         return EGL_FALSE;
183     }
184     
185     pixmap = XCreatePixmap(nativeDisplay, rootWindow, width, height, depth);
186
187     if (!pixmap)
188     {
189         fprintf(stderr, "XCreatePixmap failed\n");
190         return EGL_FALSE;
191     }
192
193     XFlush(nativeDisplay);
194
195     *nativePixmap = pixmap;
196
197     return EGL_TRUE;
198 }
199
200 void nativeDestroyPixmap(EGLNativeDisplayType nativeDisplay, EGLNativePixmapType nativePixmap)
201 {
202     XFreePixmap(nativeDisplay, nativePixmap);
203 }