simple-egl: Remove leftover wl_visual variable
[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_compositor *compositor;
39         struct wl_shell *shell;
40         struct {
41                 EGLDisplay dpy;
42                 EGLContext ctx;
43                 EGLConfig conf;
44         } egl;
45         uint32_t mask;
46 };
47
48 struct window {
49         struct display *display;
50         struct {
51                 int width, height;
52         } geometry;
53         struct {
54                 GLuint fbo;
55                 GLuint color_rbo;
56
57                 GLuint program;
58                 GLuint rotation_uniform;
59
60                 GLuint pos;
61                 GLuint col;
62         } gl;
63
64         struct wl_egl_window *native;
65         struct wl_surface *surface;
66         EGLSurface egl_surface;
67 };
68
69 static const char *vert_shader_text =
70         "uniform mat4 rotation;\n"
71         "attribute vec4 pos;\n"
72         "attribute vec4 color;\n"
73         "varying vec4 v_color;\n"
74         "void main() {\n"
75         "  gl_Position = rotation * pos;\n"
76         "  v_color = color;\n"
77         "}\n";
78
79 static const char *frag_shader_text =
80         "precision mediump float;\n"
81         "varying vec4 v_color;\n"
82         "void main() {\n"
83         "  gl_FragColor = v_color;\n"
84         "}\n";
85
86 static void
87 init_egl(struct display *display)
88 {
89         static const EGLint context_attribs[] = {
90                 EGL_CONTEXT_CLIENT_VERSION, 2,
91                 EGL_NONE
92         };
93
94         static const EGLint config_attribs[] = {
95                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT,
96                 EGL_RED_SIZE, 1,
97                 EGL_GREEN_SIZE, 1,
98                 EGL_BLUE_SIZE, 1,
99                 EGL_ALPHA_SIZE, 1,
100                 EGL_DEPTH_SIZE, 1,
101                 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
102                 EGL_NONE
103         };
104
105         EGLint major, minor, n;
106         EGLBoolean ret;
107
108         display->egl.dpy = eglGetDisplay(display->display);
109         assert(display->egl.dpy);
110
111         ret = eglInitialize(display->egl.dpy, &major, &minor);
112         assert(ret == EGL_TRUE);
113         ret = eglBindAPI(EGL_OPENGL_ES_API);
114         assert(ret == EGL_TRUE);
115
116         assert(eglChooseConfig(display->egl.dpy, config_attribs,
117                                &display->egl.conf, 1, &n) && n == 1);
118
119         display->egl.ctx = eglCreateContext(display->egl.dpy,
120                                             display->egl.conf,
121                                             EGL_NO_CONTEXT, context_attribs);
122         assert(display->egl.ctx);
123
124 }
125
126 static GLuint
127 create_shader(struct window *window, const char *source, GLenum shader_type)
128 {
129         GLuint shader;
130         GLint status;
131
132         shader = glCreateShader(shader_type);
133         assert(shader != 0);
134
135         glShaderSource(shader, 1, (const char **) &source, NULL);
136         glCompileShader(shader);
137
138         glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
139         if (!status) {
140                 char log[1000];
141                 GLsizei len;
142                 glGetShaderInfoLog(shader, 1000, &len, log);
143                 fprintf(stderr, "Error: compiling %s: %*s\n",
144                         shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
145                         len, log);
146                 exit(1);
147         }
148
149         return shader;
150 }
151
152 static void
153 init_gl(struct window *window)
154 {
155         GLuint frag, vert;
156         GLint status;
157
158         glViewport(0, 0, window->geometry.width, window->geometry.height);
159
160         frag = create_shader(window, frag_shader_text, GL_FRAGMENT_SHADER);
161         vert = create_shader(window, vert_shader_text, GL_VERTEX_SHADER);
162
163         window->gl.program = glCreateProgram();
164         glAttachShader(window->gl.program, frag);
165         glAttachShader(window->gl.program, vert);
166         glLinkProgram(window->gl.program);
167
168         glGetProgramiv(window->gl.program, GL_LINK_STATUS, &status);
169         if (!status) {
170                 char log[1000];
171                 GLsizei len;
172                 glGetProgramInfoLog(window->gl.program, 1000, &len, log);
173                 fprintf(stderr, "Error: linking:\n%*s\n", len, log);
174                 exit(1);
175         }
176
177         glUseProgram(window->gl.program);
178         
179         window->gl.pos = 0;
180         window->gl.pos = 1;
181
182         glBindAttribLocation(window->gl.program, window->gl.pos, "pos");
183         glBindAttribLocation(window->gl.program, window->gl.col, "color");
184         glLinkProgram(window->gl.program);
185
186         window->gl.rotation_uniform =
187                 glGetUniformLocation(window->gl.program, "rotation");
188 }
189
190 static void
191 create_surface(struct window *window)
192 {
193         struct display *display = window->display;
194         EGLBoolean ret;
195         static const EGLint surface_attribs[] = {
196                 EGL_ALPHA_FORMAT, EGL_ALPHA_FORMAT_PRE,
197                 EGL_NONE
198         };
199         
200         window->surface = wl_compositor_create_surface(display->compositor);
201         window->native =
202                 wl_egl_window_create(window->surface,
203                                      window->geometry.width,
204                                      window->geometry.height);
205         window->egl_surface =
206                 eglCreateWindowSurface(display->egl.dpy,
207                                        display->egl.conf,
208                                        window->native,
209                                        surface_attribs);
210
211         wl_shell_set_toplevel(display->shell, window->surface);
212
213         ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,
214                              window->egl_surface, window->display->egl.ctx);
215         assert(ret == EGL_TRUE);
216 }
217
218 static const struct wl_callback_listener frame_listener;
219
220 static void
221 redraw(void *data, struct wl_callback *callback, uint32_t time)
222 {
223         struct window *window = data;
224         static const GLfloat verts[3][2] = {
225                 { -0.5, -0.5 },
226                 {  0.5, -0.5 },
227                 {  0,    0.5 }
228         };
229         static const GLfloat colors[3][3] = {
230                 { 1, 0, 0 },
231                 { 0, 1, 0 },
232                 { 0, 0, 1 }
233         };
234         GLfloat angle;
235         GLfloat rotation[4][4] = {
236                 { 1, 0, 0, 0 },
237                 { 0, 1, 0, 0 },
238                 { 0, 0, 1, 0 },
239                 { 0, 0, 0, 1 }
240         };
241         static const int32_t speed_div = 5;
242         static uint32_t start_time = 0;
243
244         if (start_time == 0)
245                 start_time = time;
246
247         angle = ((time-start_time) / speed_div) % 360 * M_PI / 180.0;
248         rotation[0][0] =  cos(angle);
249         rotation[0][2] =  sin(angle);
250         rotation[2][0] = -sin(angle);
251         rotation[2][2] =  cos(angle);
252
253         glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
254                            (GLfloat *) rotation);
255
256         glClearColor(0.0, 0.0, 0.0, 0.5);
257         glClear(GL_COLOR_BUFFER_BIT);
258
259         glVertexAttribPointer(window->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
260         glVertexAttribPointer(window->gl.col, 3, GL_FLOAT, GL_FALSE, 0, colors);
261         glEnableVertexAttribArray(window->gl.pos);
262         glEnableVertexAttribArray(window->gl.col);
263
264         glDrawArrays(GL_TRIANGLES, 0, 3);
265
266         glDisableVertexAttribArray(window->gl.pos);
267         glDisableVertexAttribArray(window->gl.col);
268
269         glFlush();
270
271         eglSwapBuffers(window->display->egl.dpy, window->egl_surface);
272         if (callback)
273                 wl_callback_destroy(callback);
274
275         callback = wl_surface_frame(window->surface);
276         wl_callback_add_listener(callback, &frame_listener, window);
277 }
278
279 static const struct wl_callback_listener frame_listener = {
280         redraw
281 };
282
283 static void
284 display_handle_global(struct wl_display *display, uint32_t id,
285                       const char *interface, uint32_t version, void *data)
286 {
287         struct display *d = data;
288
289         if (strcmp(interface, "wl_compositor") == 0) {
290                 d->compositor =
291                         wl_display_bind(display, id, &wl_compositor_interface);
292         } else if (strcmp(interface, "wl_shell") == 0) {
293                 d->shell = wl_display_bind(display, id, &wl_shell_interface);
294         }
295 }
296
297 static int
298 event_mask_update(uint32_t mask, void *data)
299 {
300         struct display *d = data;
301
302         d->mask = mask;
303
304         return 0;
305 }
306
307 int
308 main(int argc, char **argv)
309 {
310         struct display display = { 0 };
311         struct window  window  = { 0 };
312
313         memset(&display, 0, sizeof display);
314         memset(&window,  0, sizeof window);
315
316         window.display = &display;
317         window.geometry.width  = 250;
318         window.geometry.height = 250;
319
320         display.display = wl_display_connect(NULL);
321         assert(display.display);
322
323         wl_display_add_global_listener(display.display,
324                                        display_handle_global, &display);
325
326         wl_display_get_fd(display.display, event_mask_update, &display);
327         wl_display_iterate(display.display, WL_DISPLAY_READABLE);
328
329         init_egl(&display);
330         create_surface(&window);
331         init_gl(&window);
332
333         redraw(&window, NULL, 0);
334
335         while (true)
336                 wl_display_iterate(display.display, display.mask);
337
338         return 0;
339 }