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