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