Remove egl display type setenv hack
[profile/ivi/weston.git] / clients / simple-egl.c
1 /*
2  * Copyright © 2011 Benjamin Franzke
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdbool.h>
27 #include <math.h>
28 #include <assert.h>
29
30 #include <wayland-client.h>
31 #include <wayland-egl.h>
32
33 #include <GLES2/gl2.h>
34 #include <EGL/egl.h>
35
36 struct display {
37         struct wl_display *display;
38         struct wl_visual *premultiplied_argb_visual;
39         struct wl_compositor *compositor;
40         struct wl_shell *shell;
41         struct {
42                 EGLDisplay dpy;
43                 EGLContext ctx;
44                 EGLConfig conf;
45         } egl;
46         uint32_t mask;
47 };
48
49 struct window {
50         struct display *display;
51         struct {
52                 int width, height;
53         } geometry;
54         struct {
55                 GLuint fbo;
56                 GLuint color_rbo;
57
58                 GLuint program;
59                 GLuint rotation_uniform;
60
61                 GLuint pos;
62                 GLuint col;
63         } gl;
64
65         struct wl_egl_window *native;
66         struct wl_surface *surface;
67         EGLSurface egl_surface;
68 };
69
70 static const char *vert_shader_text =
71         "uniform mat4 rotation;\n"
72         "attribute vec4 pos;\n"
73         "attribute vec4 color;\n"
74         "varying vec4 v_color;\n"
75         "void main() {\n"
76         "  gl_Position = rotation * pos;\n"
77         "  v_color = color;\n"
78         "}\n";
79
80 static const char *frag_shader_text =
81         "precision mediump float;\n"
82         "varying vec4 v_color;\n"
83         "void main() {\n"
84         "  gl_FragColor = v_color;\n"
85         "}\n";
86
87 static void
88 init_egl(struct display *display)
89 {
90         static const EGLint context_attribs[] = {
91                 EGL_CONTEXT_CLIENT_VERSION, 2,
92                 EGL_NONE
93         };
94
95         static const EGLint config_attribs[] = {
96                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT,
97                 EGL_RED_SIZE, 1,
98                 EGL_GREEN_SIZE, 1,
99                 EGL_BLUE_SIZE, 1,
100                 EGL_ALPHA_SIZE, 1,
101                 EGL_DEPTH_SIZE, 1,
102                 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
103                 EGL_NONE
104         };
105
106         EGLint major, minor, n;
107         EGLBoolean ret;
108
109         display->egl.dpy = eglGetDisplay(display->display);
110         assert(display->egl.dpy);
111
112         ret = eglInitialize(display->egl.dpy, &major, &minor);
113         assert(ret == EGL_TRUE);
114         ret = eglBindAPI(EGL_OPENGL_ES_API);
115         assert(ret == EGL_TRUE);
116
117         assert(eglChooseConfig(display->egl.dpy, config_attribs,
118                                &display->egl.conf, 1, &n) && n == 1);
119
120         display->egl.ctx = eglCreateContext(display->egl.dpy,
121                                             display->egl.conf,
122                                             EGL_NO_CONTEXT, context_attribs);
123         assert(display->egl.ctx);
124
125 }
126
127 static GLuint
128 create_shader(struct window *window, const char *source, GLenum shader_type)
129 {
130         GLuint shader;
131         GLint status;
132
133         shader = glCreateShader(shader_type);
134         assert(shader != 0);
135
136         glShaderSource(shader, 1, (const char **) &source, NULL);
137         glCompileShader(shader);
138
139         glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
140         if (!status) {
141                 char log[1000];
142                 GLsizei len;
143                 glGetShaderInfoLog(shader, 1000, &len, log);
144                 fprintf(stderr, "Error: compiling %s: %*s\n",
145                         shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
146                         len, log);
147                 exit(1);
148         }
149
150         return shader;
151 }
152
153 static void
154 init_gl(struct window *window)
155 {
156         GLuint frag, vert;
157         GLint status;
158
159         glViewport(0, 0, window->geometry.width, window->geometry.height);
160
161         frag = create_shader(window, frag_shader_text, GL_FRAGMENT_SHADER);
162         vert = create_shader(window, vert_shader_text, GL_VERTEX_SHADER);
163
164         window->gl.program = glCreateProgram();
165         glAttachShader(window->gl.program, frag);
166         glAttachShader(window->gl.program, vert);
167         glLinkProgram(window->gl.program);
168
169         glGetProgramiv(window->gl.program, GL_LINK_STATUS, &status);
170         if (!status) {
171                 char log[1000];
172                 GLsizei len;
173                 glGetProgramInfoLog(window->gl.program, 1000, &len, log);
174                 fprintf(stderr, "Error: linking:\n%*s\n", len, log);
175                 exit(1);
176         }
177
178         glUseProgram(window->gl.program);
179         
180         window->gl.pos = 0;
181         window->gl.pos = 1;
182
183         glBindAttribLocation(window->gl.program, window->gl.pos, "pos");
184         glBindAttribLocation(window->gl.program, window->gl.col, "color");
185         glLinkProgram(window->gl.program);
186
187         window->gl.rotation_uniform =
188                 glGetUniformLocation(window->gl.program, "rotation");
189 }
190
191 static void
192 create_surface(struct window *window)
193 {
194         struct display *display = window->display;
195         struct wl_visual *visual;
196         EGLBoolean ret;
197         static const EGLint surface_attribs[] = {
198                 EGL_ALPHA_FORMAT, EGL_ALPHA_FORMAT_PRE,
199                 EGL_NONE
200         };
201         
202         window->surface = wl_compositor_create_surface(display->compositor);
203         visual = display->premultiplied_argb_visual;
204         window->native =
205                 wl_egl_window_create(window->surface,
206                                      window->geometry.width,
207                                      window->geometry.height);
208         window->egl_surface =
209                 eglCreateWindowSurface(display->egl.dpy,
210                                        display->egl.conf,
211                                        window->native,
212                                        surface_attribs);
213
214         wl_shell_set_toplevel(display->shell, window->surface);
215
216         ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,
217                              window->egl_surface, window->display->egl.ctx);
218         assert(ret == EGL_TRUE);
219 }
220
221 static const struct wl_callback_listener frame_listener;
222
223 static void
224 redraw(void *data, struct wl_callback *callback, uint32_t time)
225 {
226         struct window *window = data;
227         static const GLfloat verts[3][2] = {
228                 { -0.5, -0.5 },
229                 {  0.5, -0.5 },
230                 {  0,    0.5 }
231         };
232         static const GLfloat colors[3][3] = {
233                 { 1, 0, 0 },
234                 { 0, 1, 0 },
235                 { 0, 0, 1 }
236         };
237         GLfloat angle;
238         GLfloat rotation[4][4] = {
239                 { 1, 0, 0, 0 },
240                 { 0, 1, 0, 0 },
241                 { 0, 0, 1, 0 },
242                 { 0, 0, 0, 1 }
243         };
244         static const int32_t speed_div = 5;
245         static uint32_t start_time = 0;
246
247         if (start_time == 0)
248                 start_time = time;
249
250         angle = ((time-start_time) / speed_div) % 360 * M_PI / 180.0;
251         rotation[0][0] =  cos(angle);
252         rotation[0][2] =  sin(angle);
253         rotation[2][0] = -sin(angle);
254         rotation[2][2] =  cos(angle);
255
256         glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
257                            (GLfloat *) rotation);
258
259         glClearColor(0.0, 0.0, 0.0, 0.5);
260         glClear(GL_COLOR_BUFFER_BIT);
261
262         glVertexAttribPointer(window->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
263         glVertexAttribPointer(window->gl.col, 3, GL_FLOAT, GL_FALSE, 0, colors);
264         glEnableVertexAttribArray(window->gl.pos);
265         glEnableVertexAttribArray(window->gl.col);
266
267         glDrawArrays(GL_TRIANGLES, 0, 3);
268
269         glDisableVertexAttribArray(window->gl.pos);
270         glDisableVertexAttribArray(window->gl.col);
271
272         glFlush();
273
274         eglSwapBuffers(window->display->egl.dpy, window->egl_surface);
275         if (callback)
276                 wl_callback_destroy(callback);
277
278         callback = wl_surface_frame(window->surface);
279         wl_callback_add_listener(callback, &frame_listener, window);
280 }
281
282 static const struct wl_callback_listener frame_listener = {
283         redraw
284 };
285
286 static void
287 display_handle_global(struct wl_display *display, uint32_t id,
288                       const char *interface, uint32_t version, void *data)
289 {
290         struct display *d = data;
291
292         if (strcmp(interface, "wl_compositor") == 0) {
293                 d->compositor =
294                         wl_display_bind(display, id, &wl_compositor_interface);
295         } else if (strcmp(interface, "wl_shell") == 0) {
296                 d->shell = wl_display_bind(display, id, &wl_shell_interface);
297         }
298 }
299
300 static int
301 event_mask_update(uint32_t mask, void *data)
302 {
303         struct display *d = data;
304
305         d->mask = mask;
306
307         return 0;
308 }
309
310 int
311 main(int argc, char **argv)
312 {
313         struct display display = { 0 };
314         struct window  window  = { 0 };
315
316         memset(&display, 0, sizeof display);
317         memset(&window,  0, sizeof window);
318
319         window.display = &display;
320         window.geometry.width  = 250;
321         window.geometry.height = 250;
322
323         display.display = wl_display_connect(NULL);
324         assert(display.display);
325
326         wl_display_add_global_listener(display.display,
327                                        display_handle_global, &display);
328
329         wl_display_get_fd(display.display, event_mask_update, &display);
330         wl_display_iterate(display.display, WL_DISPLAY_READABLE);
331
332         init_egl(&display);
333         create_surface(&window);
334         init_gl(&window);
335
336         redraw(&window, NULL, 0);
337
338         while (true)
339                 wl_display_iterate(display.display, display.mask);
340
341         return 0;
342 }