blob: 96cf1c8a965754854b8ca534c296133cea58f363 [file] [log] [blame]
Kristian Høgsberg1cc5ac32013-04-11 21:47:41 -04001/*
2 * Copyright © 2013 Intel Corporation
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
Andrew Wedgbury9cd661e2014-04-07 12:40:35 +010023#include "config.h"
24
Kristian Høgsberg1cc5ac32013-04-11 21:47:41 -040025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <wayland-egl.h>
30#include <wayland-cursor.h>
31
32#include <GLES2/gl2.h>
33#include <EGL/egl.h>
34
35struct window;
36struct seat;
37
38struct nested_client {
39 struct wl_display *display;
40 struct wl_registry *registry;
41 struct wl_compositor *compositor;
42
43 EGLDisplay egl_display;
44 EGLContext egl_context;
45 EGLConfig egl_config;
46 EGLSurface egl_surface;
47 struct program *color_program;
48
49 GLuint vert, frag, program;
50 GLuint rotation;
51 GLuint pos;
52 GLuint col;
53
54 struct wl_surface *surface;
55 struct wl_egl_window *native;
56 int width, height;
57};
58
59#define POS 0
60#define COL 1
61
62static GLuint
63create_shader(const char *source, GLenum shader_type)
64{
65 GLuint shader;
66 GLint status;
67
68 shader = glCreateShader(shader_type);
69 if (shader == 0)
70 return 0;
71
72 glShaderSource(shader, 1, (const char **) &source, NULL);
73 glCompileShader(shader);
74
75 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
76 if (!status) {
77 char log[1000];
78 GLsizei len;
79 glGetShaderInfoLog(shader, 1000, &len, log);
80 fprintf(stderr, "Error: compiling %s: %*s\n",
81 shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
82 len, log);
83 return 0;
84 }
85
86 return shader;
87}
88
89static void
90create_program(struct nested_client *client,
91 const char *vert, const char *frag)
92{
93 GLint status;
94
95 client->vert = create_shader(vert, GL_VERTEX_SHADER);
96 client->frag = create_shader(frag, GL_FRAGMENT_SHADER);
97
98 client->program = glCreateProgram();
99 glAttachShader(client->program, client->frag);
100 glAttachShader(client->program, client->vert);
101 glBindAttribLocation(client->program, POS, "pos");
102 glBindAttribLocation(client->program, COL, "color");
103 glLinkProgram(client->program);
104
105 glGetProgramiv(client->program, GL_LINK_STATUS, &status);
106 if (!status) {
107 char log[1000];
108 GLsizei len;
109 glGetProgramInfoLog(client->program, 1000, &len, log);
110 fprintf(stderr, "Error: linking:\n%*s\n", len, log);
111 exit(1);
112 }
113
114 client->rotation =
115 glGetUniformLocation(client->program, "rotation");
116}
117
118static const char vertex_shader_text[] =
119 "uniform mat4 rotation;\n"
120 "attribute vec4 pos;\n"
121 "attribute vec4 color;\n"
122 "varying vec4 v_color;\n"
123 "void main() {\n"
124 " gl_Position = rotation * pos;\n"
125 " v_color = color;\n"
126 "}\n";
127
128static const char color_fragment_shader_text[] =
129 "precision mediump float;\n"
130 "varying vec4 v_color;\n"
131 "void main() {\n"
132 " gl_FragColor = v_color;\n"
133 "}\n";
134
135static void
136render_triangle(struct nested_client *client, uint32_t time)
137{
138 static const GLfloat verts[3][2] = {
139 { -0.5, -0.5 },
140 { 0.5, -0.5 },
141 { 0, 0.5 }
142 };
143 static const GLfloat colors[3][3] = {
144 { 1, 0, 0 },
145 { 0, 1, 0 },
146 { 0, 0, 1 }
147 };
148 GLfloat angle;
149 GLfloat rotation[4][4] = {
150 { 1, 0, 0, 0 },
151 { 0, 1, 0, 0 },
152 { 0, 0, 1, 0 },
153 { 0, 0, 0, 1 }
154 };
155 static const int32_t speed_div = 5;
156 static uint32_t start_time = 0;
157
158 if (client->program == 0)
159 create_program(client, vertex_shader_text,
160 color_fragment_shader_text);
161
162 if (start_time == 0)
163 start_time = time;
164
165 angle = ((time - start_time) / speed_div) % 360 * M_PI / 180.0;
166 rotation[0][0] = cos(angle);
167 rotation[0][2] = sin(angle);
168 rotation[2][0] = -sin(angle);
169 rotation[2][2] = cos(angle);
170
171 glClearColor(0.4, 0.4, 0.4, 1.0);
172 glClear(GL_COLOR_BUFFER_BIT);
173
174 glUseProgram(client->program);
175
176 glViewport(0, 0, client->width, client->height);
177
178 glUniformMatrix4fv(client->rotation, 1, GL_FALSE,
179 (GLfloat *) rotation);
180
181 glVertexAttribPointer(POS, 2, GL_FLOAT, GL_FALSE, 0, verts);
182 glVertexAttribPointer(COL, 3, GL_FLOAT, GL_FALSE, 0, colors);
183 glEnableVertexAttribArray(POS);
184 glEnableVertexAttribArray(COL);
185
186 glDrawArrays(GL_TRIANGLES, 0, 3);
187
188 glDisableVertexAttribArray(POS);
189 glDisableVertexAttribArray(COL);
190
191 glFlush();
192}
193
194static void
195frame_callback(void *data, struct wl_callback *callback, uint32_t time);
196
197static const struct wl_callback_listener frame_listener = {
198 frame_callback
199};
200
201static void
202frame_callback(void *data, struct wl_callback *callback, uint32_t time)
203{
204 struct nested_client *client = data;
205
206 if (callback)
207 wl_callback_destroy(callback);
208
209 callback = wl_surface_frame(client->surface);
210 wl_callback_add_listener(callback, &frame_listener, client);
211
212 render_triangle(client, time);
213
214 eglSwapBuffers(client->egl_display, client->egl_surface);
215}
216
217static void
218registry_handle_global(void *data, struct wl_registry *registry,
219 uint32_t name, const char *interface, uint32_t version)
220{
221 struct nested_client *client = data;
222
223 if (strcmp(interface, "wl_compositor") == 0) {
224 client->compositor =
225 wl_registry_bind(registry, name,
226 &wl_compositor_interface, 1);
227 }
228}
229
230static void
231registry_handle_global_remove(void *data, struct wl_registry *registry,
232 uint32_t name)
233{
234}
235
236static const struct wl_registry_listener registry_listener = {
237 registry_handle_global,
238 registry_handle_global_remove
239};
240
241static struct nested_client *
242nested_client_create(void)
243{
244 static const EGLint context_attribs[] = {
245 EGL_CONTEXT_CLIENT_VERSION, 2,
246 EGL_NONE
247 };
248
249 static const EGLint config_attribs[] = {
250 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
251 EGL_RED_SIZE, 1,
252 EGL_GREEN_SIZE, 1,
253 EGL_BLUE_SIZE, 1,
254 EGL_ALPHA_SIZE, 1,
255 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
256 EGL_NONE
257 };
258
259 EGLint major, minor, n;
260 EGLBoolean ret;
261
262 struct nested_client *client;
263
264 client = malloc(sizeof *client);
265 if (client == NULL)
266 return NULL;
267
268 client->width = 250;
269 client->height = 250;
270
271 client->display = wl_display_connect(NULL);
272
273 client->registry = wl_display_get_registry(client->display);
274 wl_registry_add_listener(client->registry,
275 &registry_listener, client);
276
277 /* get globals */
278 wl_display_roundtrip(client->display);
279
Jonny Lamb51a7ae52015-03-20 15:26:51 +0100280 client->egl_display =
281 weston_platform_get_egl_display(EGL_PLATFORM_WAYLAND_KHR,
282 client->display, NULL);
Kristian Høgsberg1cc5ac32013-04-11 21:47:41 -0400283 if (client->egl_display == NULL)
284 return NULL;
285
286 ret = eglInitialize(client->egl_display, &major, &minor);
287 if (!ret)
288 return NULL;
289 ret = eglBindAPI(EGL_OPENGL_ES_API);
290 if (!ret)
291 return NULL;
292
293 ret = eglChooseConfig(client->egl_display, config_attribs,
294 &client->egl_config, 1, &n);
295 if (!ret || n != 1)
296 return NULL;
297
298 client->egl_context = eglCreateContext(client->egl_display,
299 client->egl_config,
300 EGL_NO_CONTEXT,
301 context_attribs);
302 if (!client->egl_context)
303 return NULL;
304
305 client->surface = wl_compositor_create_surface(client->compositor);
306
307 client->native = wl_egl_window_create(client->surface,
308 client->width, client->height);
309
310 client->egl_surface =
311 eglCreateWindowSurface(client->egl_display,
312 client->egl_config,
313 client->native, NULL);
314
315 eglMakeCurrent(client->egl_display, client->egl_surface,
316 client->egl_surface, client->egl_context);
317
318 wl_egl_window_resize(client->native,
319 client->width, client->height, 0, 0);
320
321 frame_callback(client, NULL, 0);
322
323 return client;
324}
325
326static void
327nested_client_destroy(struct nested_client *client)
328{
329 eglMakeCurrent(client->egl_display,
330 EGL_NO_SURFACE, EGL_NO_SURFACE,
331 EGL_NO_CONTEXT);
332
333 wl_egl_window_destroy(client->native);
334
335 wl_surface_destroy(client->surface);
336
337 if (client->compositor)
338 wl_compositor_destroy(client->compositor);
339
340 wl_registry_destroy(client->registry);
341 wl_display_flush(client->display);
342 wl_display_disconnect(client->display);
343}
344
345int
346main(int argc, char **argv)
347{
348 struct nested_client *client;
349 int ret = 0;
350
351 if (getenv("WAYLAND_SOCKET") == NULL) {
352 fprintf(stderr,
353 "must be run by nested, don't run standalone\n");
Kristian Høgsbergf1144dd2013-10-09 13:25:58 -0700354 return EXIT_FAILURE;
Kristian Høgsberg1cc5ac32013-04-11 21:47:41 -0400355 }
356
357 client = nested_client_create();
Kristian Høgsbergf1144dd2013-10-09 13:25:58 -0700358 if (client == NULL)
359 return EXIT_FAILURE;
Kristian Høgsberg1cc5ac32013-04-11 21:47:41 -0400360
361 while (ret != -1)
362 ret = wl_display_dispatch(client->display);
363
364 nested_client_destroy(client);
365
366 return 0;
367}