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