2 * Copyright © 2013 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
31 #include <wayland-egl.h>
32 #include <wayland-cursor.h>
34 #include <GLES2/gl2.h>
37 #include "../shared/platform.h"
42 struct nested_client {
43 struct wl_display *display;
44 struct wl_registry *registry;
45 struct wl_compositor *compositor;
47 EGLDisplay egl_display;
48 EGLContext egl_context;
50 EGLSurface egl_surface;
51 struct program *color_program;
53 GLuint vert, frag, program;
58 struct wl_surface *surface;
59 struct wl_egl_window *native;
67 create_shader(const char *source, GLenum shader_type)
72 shader = glCreateShader(shader_type);
76 glShaderSource(shader, 1, (const char **) &source, NULL);
77 glCompileShader(shader);
79 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
83 glGetShaderInfoLog(shader, 1000, &len, log);
84 fprintf(stderr, "Error: compiling %s: %*s\n",
85 shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
94 create_program(struct nested_client *client,
95 const char *vert, const char *frag)
99 client->vert = create_shader(vert, GL_VERTEX_SHADER);
100 client->frag = create_shader(frag, GL_FRAGMENT_SHADER);
102 client->program = glCreateProgram();
103 glAttachShader(client->program, client->frag);
104 glAttachShader(client->program, client->vert);
105 glBindAttribLocation(client->program, POS, "pos");
106 glBindAttribLocation(client->program, COL, "color");
107 glLinkProgram(client->program);
109 glGetProgramiv(client->program, GL_LINK_STATUS, &status);
113 glGetProgramInfoLog(client->program, 1000, &len, log);
114 fprintf(stderr, "Error: linking:\n%*s\n", len, log);
119 glGetUniformLocation(client->program, "rotation");
122 static const char vertex_shader_text[] =
123 "uniform mat4 rotation;\n"
124 "attribute vec4 pos;\n"
125 "attribute vec4 color;\n"
126 "varying vec4 v_color;\n"
128 " gl_Position = rotation * pos;\n"
129 " v_color = color;\n"
132 static const char color_fragment_shader_text[] =
133 "precision mediump float;\n"
134 "varying vec4 v_color;\n"
136 " gl_FragColor = v_color;\n"
140 render_triangle(struct nested_client *client, uint32_t time)
142 static const GLfloat verts[3][2] = {
147 static const GLfloat colors[3][3] = {
153 GLfloat rotation[4][4] = {
159 static const int32_t speed_div = 5;
160 static uint32_t start_time = 0;
162 if (client->program == 0)
163 create_program(client, vertex_shader_text,
164 color_fragment_shader_text);
169 angle = ((time - start_time) / speed_div) % 360 * M_PI / 180.0;
170 rotation[0][0] = cos(angle);
171 rotation[0][2] = sin(angle);
172 rotation[2][0] = -sin(angle);
173 rotation[2][2] = cos(angle);
175 glClearColor(0.4, 0.4, 0.4, 1.0);
176 glClear(GL_COLOR_BUFFER_BIT);
178 glUseProgram(client->program);
180 glViewport(0, 0, client->width, client->height);
182 glUniformMatrix4fv(client->rotation, 1, GL_FALSE,
183 (GLfloat *) rotation);
185 glVertexAttribPointer(POS, 2, GL_FLOAT, GL_FALSE, 0, verts);
186 glVertexAttribPointer(COL, 3, GL_FLOAT, GL_FALSE, 0, colors);
187 glEnableVertexAttribArray(POS);
188 glEnableVertexAttribArray(COL);
190 glDrawArrays(GL_TRIANGLES, 0, 3);
192 glDisableVertexAttribArray(POS);
193 glDisableVertexAttribArray(COL);
199 frame_callback(void *data, struct wl_callback *callback, uint32_t time);
201 static const struct wl_callback_listener frame_listener = {
206 frame_callback(void *data, struct wl_callback *callback, uint32_t time)
208 struct nested_client *client = data;
211 wl_callback_destroy(callback);
213 callback = wl_surface_frame(client->surface);
214 wl_callback_add_listener(callback, &frame_listener, client);
216 render_triangle(client, time);
218 eglSwapBuffers(client->egl_display, client->egl_surface);
222 registry_handle_global(void *data, struct wl_registry *registry,
223 uint32_t name, const char *interface, uint32_t version)
225 struct nested_client *client = data;
227 if (strcmp(interface, "wl_compositor") == 0) {
229 wl_registry_bind(registry, name,
230 &wl_compositor_interface, 1);
235 registry_handle_global_remove(void *data, struct wl_registry *registry,
240 static const struct wl_registry_listener registry_listener = {
241 registry_handle_global,
242 registry_handle_global_remove
245 static struct nested_client *
246 nested_client_create(void)
248 static const EGLint context_attribs[] = {
249 EGL_CONTEXT_CLIENT_VERSION, 2,
253 static const EGLint config_attribs[] = {
254 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
259 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
263 EGLint major, minor, n;
266 struct nested_client *client;
268 client = malloc(sizeof *client);
273 client->height = 250;
275 client->display = wl_display_connect(NULL);
277 client->registry = wl_display_get_registry(client->display);
278 wl_registry_add_listener(client->registry,
279 ®istry_listener, client);
282 wl_display_roundtrip(client->display);
284 client->egl_display =
285 weston_platform_get_egl_display(EGL_PLATFORM_WAYLAND_KHR,
286 client->display, NULL);
287 if (client->egl_display == NULL)
290 ret = eglInitialize(client->egl_display, &major, &minor);
293 ret = eglBindAPI(EGL_OPENGL_ES_API);
297 ret = eglChooseConfig(client->egl_display, config_attribs,
298 &client->egl_config, 1, &n);
302 client->egl_context = eglCreateContext(client->egl_display,
306 if (!client->egl_context)
309 client->surface = wl_compositor_create_surface(client->compositor);
311 client->native = wl_egl_window_create(client->surface,
312 client->width, client->height);
314 client->egl_surface = weston_platform_create_egl_surface(client->egl_display,
316 client->native, NULL);
318 eglMakeCurrent(client->egl_display, client->egl_surface,
319 client->egl_surface, client->egl_context);
321 wl_egl_window_resize(client->native,
322 client->width, client->height, 0, 0);
324 frame_callback(client, NULL, 0);
330 nested_client_destroy(struct nested_client *client)
332 eglMakeCurrent(client->egl_display,
333 EGL_NO_SURFACE, EGL_NO_SURFACE,
336 weston_platform_destroy_egl_surface(client->egl_display,
337 client->egl_surface);
338 wl_egl_window_destroy(client->native);
340 wl_surface_destroy(client->surface);
342 if (client->compositor)
343 wl_compositor_destroy(client->compositor);
345 wl_registry_destroy(client->registry);
346 eglTerminate(client->egl_display);
348 wl_display_flush(client->display);
349 wl_display_disconnect(client->display);
353 main(int argc, char **argv)
355 struct nested_client *client;
358 if (getenv("WAYLAND_SOCKET") == NULL) {
360 "must be run by nested, don't run standalone\n");
364 client = nested_client_create();
369 ret = wl_display_dispatch(client->display);
371 nested_client_destroy(client);