blob: f74015589e10fd26b6c23c7119b57cf8453e1848 [file] [log] [blame]
Kristian Høgsbergd7c17262012-09-05 21:54:15 -04001/*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040023#define _GNU_SOURCE
24
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040025#include <stdlib.h>
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040026#include <string.h>
27#include <ctype.h>
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +030028#include <float.h>
29#include <assert.h>
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +020030#include <linux/input.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040031
Kristian Høgsbergd7c17262012-09-05 21:54:15 -040032#include "compositor.h"
33
John Kåre Alsaker40684142012-11-13 19:10:25 +010034struct gles2_shader {
35 GLuint program;
36 GLuint vertex_shader, fragment_shader;
37 GLint proj_uniform;
38 GLint tex_uniforms[3];
39 GLint alpha_uniform;
40 GLint color_uniform;
41};
42
John Kåre Alsaker94659272012-11-13 19:10:18 +010043struct gles2_output_state {
44 EGLSurface egl_surface;
45};
46
John Kåre Alsaker878f4492012-11-13 19:10:23 +010047struct gles2_surface_state {
48 GLfloat color[4];
John Kåre Alsaker40684142012-11-13 19:10:25 +010049 struct gles2_shader *shader;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +010050
51 GLuint textures[3];
52 int num_textures;
53
54 EGLImageKHR images[3];
55 GLenum target;
56 int num_images;
John Kåre Alsaker878f4492012-11-13 19:10:23 +010057};
58
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010059struct gles2_renderer {
60 struct weston_renderer base;
61 int fragment_shader_debug;
62
63 EGLDisplay egl_display;
64 EGLContext egl_context;
65 EGLConfig egl_config;
John Kåre Alsaker44154502012-11-13 19:10:20 +010066
67 struct {
68 int32_t top, bottom, left, right;
69 GLuint texture;
70 int32_t width, height;
71 } border;
John Kåre Alsaker40684142012-11-13 19:10:25 +010072
73 struct gles2_shader texture_shader_rgba;
74 struct gles2_shader texture_shader_rgbx;
75 struct gles2_shader texture_shader_egl_external;
76 struct gles2_shader texture_shader_y_uv;
77 struct gles2_shader texture_shader_y_u_v;
78 struct gles2_shader texture_shader_y_xuxv;
79 struct gles2_shader invert_color_shader;
80 struct gles2_shader solid_shader;
81 struct gles2_shader *current_shader;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010082};
John Kåre Alsaker94659272012-11-13 19:10:18 +010083
84static inline struct gles2_output_state *
85get_output_state(struct weston_output *output)
86{
87 return (struct gles2_output_state *)output->renderer_state;
88}
89
John Kåre Alsaker878f4492012-11-13 19:10:23 +010090static inline struct gles2_surface_state *
91get_surface_state(struct weston_surface *surface)
92{
93 return (struct gles2_surface_state *)surface->renderer_state;
94}
95
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010096static inline struct gles2_renderer *
97get_renderer(struct weston_compositor *ec)
98{
99 return (struct gles2_renderer *)ec->renderer;
100}
101
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400102static const char *
103egl_error_string(EGLint code)
104{
105#define MYERRCODE(x) case x: return #x;
106 switch (code) {
107 MYERRCODE(EGL_SUCCESS)
108 MYERRCODE(EGL_NOT_INITIALIZED)
109 MYERRCODE(EGL_BAD_ACCESS)
110 MYERRCODE(EGL_BAD_ALLOC)
111 MYERRCODE(EGL_BAD_ATTRIBUTE)
112 MYERRCODE(EGL_BAD_CONTEXT)
113 MYERRCODE(EGL_BAD_CONFIG)
114 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
115 MYERRCODE(EGL_BAD_DISPLAY)
116 MYERRCODE(EGL_BAD_SURFACE)
117 MYERRCODE(EGL_BAD_MATCH)
118 MYERRCODE(EGL_BAD_PARAMETER)
119 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
120 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
121 MYERRCODE(EGL_CONTEXT_LOST)
122 default:
123 return "unknown";
124 }
125#undef MYERRCODE
126}
127
128static void
129print_egl_error_state(void)
130{
131 EGLint code;
132
133 code = eglGetError();
134 weston_log("EGL error state: %s (0x%04lx)\n",
135 egl_error_string(code), (long)code);
136}
137
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300138struct polygon8 {
139 GLfloat x[8];
140 GLfloat y[8];
141 int n;
142};
143
144struct clip_context {
145 struct {
146 GLfloat x;
147 GLfloat y;
148 } prev;
149
150 struct {
151 GLfloat x1, y1;
152 GLfloat x2, y2;
153 } clip;
154
155 struct {
156 GLfloat *x;
157 GLfloat *y;
158 } vertices;
159};
160
161static GLfloat
162float_difference(GLfloat a, GLfloat b)
163{
164 /* http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/ */
165 static const GLfloat max_diff = 4.0f * FLT_MIN;
166 static const GLfloat max_rel_diff = 4.0e-5;
167 GLfloat diff = a - b;
168 GLfloat adiff = fabsf(diff);
169
170 if (adiff <= max_diff)
171 return 0.0f;
172
173 a = fabsf(a);
174 b = fabsf(b);
175 if (adiff <= (a > b ? a : b) * max_rel_diff)
176 return 0.0f;
177
178 return diff;
179}
180
181/* A line segment (p1x, p1y)-(p2x, p2y) intersects the line x = x_arg.
182 * Compute the y coordinate of the intersection.
183 */
184static GLfloat
185clip_intersect_y(GLfloat p1x, GLfloat p1y, GLfloat p2x, GLfloat p2y,
186 GLfloat x_arg)
187{
188 GLfloat a;
189 GLfloat diff = float_difference(p1x, p2x);
190
191 /* Practically vertical line segment, yet the end points have already
192 * been determined to be on different sides of the line. Therefore
193 * the line segment is part of the line and intersects everywhere.
194 * Return the end point, so we use the whole line segment.
195 */
196 if (diff == 0.0f)
197 return p2y;
198
199 a = (x_arg - p2x) / diff;
200 return p2y + (p1y - p2y) * a;
201}
202
203/* A line segment (p1x, p1y)-(p2x, p2y) intersects the line y = y_arg.
204 * Compute the x coordinate of the intersection.
205 */
206static GLfloat
207clip_intersect_x(GLfloat p1x, GLfloat p1y, GLfloat p2x, GLfloat p2y,
208 GLfloat y_arg)
209{
210 GLfloat a;
211 GLfloat diff = float_difference(p1y, p2y);
212
213 /* Practically horizontal line segment, yet the end points have already
214 * been determined to be on different sides of the line. Therefore
215 * the line segment is part of the line and intersects everywhere.
216 * Return the end point, so we use the whole line segment.
217 */
218 if (diff == 0.0f)
219 return p2x;
220
221 a = (y_arg - p2y) / diff;
222 return p2x + (p1x - p2x) * a;
223}
224
225enum path_transition {
226 PATH_TRANSITION_OUT_TO_OUT = 0,
227 PATH_TRANSITION_OUT_TO_IN = 1,
228 PATH_TRANSITION_IN_TO_OUT = 2,
229 PATH_TRANSITION_IN_TO_IN = 3,
230};
231
232static void
233clip_append_vertex(struct clip_context *ctx, GLfloat x, GLfloat y)
234{
235 *ctx->vertices.x++ = x;
236 *ctx->vertices.y++ = y;
237}
238
239static enum path_transition
240path_transition_left_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
241{
242 return ((ctx->prev.x >= ctx->clip.x1) << 1) | (x >= ctx->clip.x1);
243}
244
245static enum path_transition
246path_transition_right_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
247{
248 return ((ctx->prev.x < ctx->clip.x2) << 1) | (x < ctx->clip.x2);
249}
250
251static enum path_transition
252path_transition_top_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
253{
254 return ((ctx->prev.y >= ctx->clip.y1) << 1) | (y >= ctx->clip.y1);
255}
256
257static enum path_transition
258path_transition_bottom_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
259{
260 return ((ctx->prev.y < ctx->clip.y2) << 1) | (y < ctx->clip.y2);
261}
262
263static void
264clip_polygon_leftright(struct clip_context *ctx,
265 enum path_transition transition,
266 GLfloat x, GLfloat y, GLfloat clip_x)
267{
268 GLfloat yi;
269
270 switch (transition) {
271 case PATH_TRANSITION_IN_TO_IN:
272 clip_append_vertex(ctx, x, y);
273 break;
274 case PATH_TRANSITION_IN_TO_OUT:
275 yi = clip_intersect_y(ctx->prev.x, ctx->prev.y, x, y, clip_x);
276 clip_append_vertex(ctx, clip_x, yi);
277 break;
278 case PATH_TRANSITION_OUT_TO_IN:
279 yi = clip_intersect_y(ctx->prev.x, ctx->prev.y, x, y, clip_x);
280 clip_append_vertex(ctx, clip_x, yi);
281 clip_append_vertex(ctx, x, y);
282 break;
283 case PATH_TRANSITION_OUT_TO_OUT:
284 /* nothing */
285 break;
286 default:
287 assert(0 && "bad enum path_transition");
288 }
289
290 ctx->prev.x = x;
291 ctx->prev.y = y;
292}
293
294static void
295clip_polygon_topbottom(struct clip_context *ctx,
296 enum path_transition transition,
297 GLfloat x, GLfloat y, GLfloat clip_y)
298{
299 GLfloat xi;
300
301 switch (transition) {
302 case PATH_TRANSITION_IN_TO_IN:
303 clip_append_vertex(ctx, x, y);
304 break;
305 case PATH_TRANSITION_IN_TO_OUT:
306 xi = clip_intersect_x(ctx->prev.x, ctx->prev.y, x, y, clip_y);
307 clip_append_vertex(ctx, xi, clip_y);
308 break;
309 case PATH_TRANSITION_OUT_TO_IN:
310 xi = clip_intersect_x(ctx->prev.x, ctx->prev.y, x, y, clip_y);
311 clip_append_vertex(ctx, xi, clip_y);
312 clip_append_vertex(ctx, x, y);
313 break;
314 case PATH_TRANSITION_OUT_TO_OUT:
315 /* nothing */
316 break;
317 default:
318 assert(0 && "bad enum path_transition");
319 }
320
321 ctx->prev.x = x;
322 ctx->prev.y = y;
323}
324
325static void
326clip_context_prepare(struct clip_context *ctx, const struct polygon8 *src,
327 GLfloat *dst_x, GLfloat *dst_y)
328{
329 ctx->prev.x = src->x[src->n - 1];
330 ctx->prev.y = src->y[src->n - 1];
331 ctx->vertices.x = dst_x;
332 ctx->vertices.y = dst_y;
333}
334
335static int
336clip_polygon_left(struct clip_context *ctx, const struct polygon8 *src,
337 GLfloat *dst_x, GLfloat *dst_y)
338{
339 enum path_transition trans;
340 int i;
341
342 clip_context_prepare(ctx, src, dst_x, dst_y);
343 for (i = 0; i < src->n; i++) {
344 trans = path_transition_left_edge(ctx, src->x[i], src->y[i]);
345 clip_polygon_leftright(ctx, trans, src->x[i], src->y[i],
346 ctx->clip.x1);
347 }
348 return ctx->vertices.x - dst_x;
349}
350
351static int
352clip_polygon_right(struct clip_context *ctx, const struct polygon8 *src,
353 GLfloat *dst_x, GLfloat *dst_y)
354{
355 enum path_transition trans;
356 int i;
357
358 clip_context_prepare(ctx, src, dst_x, dst_y);
359 for (i = 0; i < src->n; i++) {
360 trans = path_transition_right_edge(ctx, src->x[i], src->y[i]);
361 clip_polygon_leftright(ctx, trans, src->x[i], src->y[i],
362 ctx->clip.x2);
363 }
364 return ctx->vertices.x - dst_x;
365}
366
367static int
368clip_polygon_top(struct clip_context *ctx, const struct polygon8 *src,
369 GLfloat *dst_x, GLfloat *dst_y)
370{
371 enum path_transition trans;
372 int i;
373
374 clip_context_prepare(ctx, src, dst_x, dst_y);
375 for (i = 0; i < src->n; i++) {
376 trans = path_transition_top_edge(ctx, src->x[i], src->y[i]);
377 clip_polygon_topbottom(ctx, trans, src->x[i], src->y[i],
378 ctx->clip.y1);
379 }
380 return ctx->vertices.x - dst_x;
381}
382
383static int
384clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src,
385 GLfloat *dst_x, GLfloat *dst_y)
386{
387 enum path_transition trans;
388 int i;
389
390 clip_context_prepare(ctx, src, dst_x, dst_y);
391 for (i = 0; i < src->n; i++) {
392 trans = path_transition_bottom_edge(ctx, src->x[i], src->y[i]);
393 clip_polygon_topbottom(ctx, trans, src->x[i], src->y[i],
394 ctx->clip.y2);
395 }
396 return ctx->vertices.x - dst_x;
397}
398
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400399#define max(a, b) (((a) > (b)) ? (a) : (b))
400#define min(a, b) (((a) > (b)) ? (b) : (a))
401#define clip(x, a, b) min(max(x, a), b)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400402
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300403/*
404 * Compute the boundary vertices of the intersection of the global coordinate
405 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
406 * 'surf_rect' when transformed from surface coordinates into global coordinates.
407 * The vertices are written to 'ex' and 'ey', and the return value is the
408 * number of vertices. Vertices are produced in clockwise winding order.
409 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
410 * polygon area.
411 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400412static int
413calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
414 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
415{
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300416 struct polygon8 polygon;
417 struct clip_context ctx;
418 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400419 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300420 struct polygon8 surf = {
421 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
422 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
423 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400424 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400425
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300426 ctx.clip.x1 = rect->x1;
427 ctx.clip.y1 = rect->y1;
428 ctx.clip.x2 = rect->x2;
429 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400430
431 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300432 for (i = 0; i < surf.n; i++)
433 weston_surface_to_global_float(es, surf.x[i], surf.y[i],
434 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400435
436 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300437 min_x = max_x = surf.x[0];
438 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400439
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300440 for (i = 1; i < surf.n; i++) {
441 min_x = min(min_x, surf.x[i]);
442 max_x = max(max_x, surf.x[i]);
443 min_y = min(min_y, surf.y[i]);
444 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400445 }
446
447 /* First, simple bounding box check to discard early transformed
448 * surface rects that do not intersect with the clip region:
449 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300450 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
451 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400452 return 0;
453
454 /* Simple case, bounding box edges are parallel to surface edges,
455 * there will be only four edges. We just need to clip the surface
456 * vertices to the clip rect bounds:
457 */
458 if (!es->transform.enabled) {
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300459 for (i = 0; i < surf.n; i++) {
460 ex[i] = clip(surf.x[i], ctx.clip.x1, ctx.clip.x2);
461 ey[i] = clip(surf.y[i], ctx.clip.y1, ctx.clip.y2);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400462 }
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300463 return surf.n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400464 }
465
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300466 /* Transformed case: use a general polygon clipping algorithm to
467 * clip the surface rectangle with each side of 'rect'.
468 * The algorithm is Sutherland-Hodgman, as explained in
469 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
470 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400471 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300472 polygon.n = clip_polygon_left(&ctx, &surf, polygon.x, polygon.y);
473 surf.n = clip_polygon_right(&ctx, &polygon, surf.x, surf.y);
474 polygon.n = clip_polygon_top(&ctx, &surf, polygon.x, polygon.y);
475 surf.n = clip_polygon_bottom(&ctx, &polygon, surf.x, surf.y);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400476
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300477 /* Get rid of duplicate vertices */
478 ex[0] = surf.x[0];
479 ey[0] = surf.y[0];
480 n = 1;
481 for (i = 1; i < surf.n; i++) {
482 if (float_difference(ex[n - 1], surf.x[i]) == 0.0f &&
483 float_difference(ey[n - 1], surf.y[i]) == 0.0f)
484 continue;
485 ex[n] = surf.x[i];
486 ey[n] = surf.y[i];
487 n++;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400488 }
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300489 if (float_difference(ex[n - 1], surf.x[0]) == 0.0f &&
490 float_difference(ey[n - 1], surf.y[0]) == 0.0f)
491 n--;
492
493 if (n < 3)
494 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400495
496 return n;
497}
498
499static int
500texture_region(struct weston_surface *es, pixman_region32_t *region,
501 pixman_region32_t *surf_region)
502{
503 struct weston_compositor *ec = es->compositor;
504 GLfloat *v, inv_width, inv_height;
505 unsigned int *vtxcnt, nvtx = 0;
506 pixman_box32_t *rects, *surf_rects;
507 int i, j, k, nrects, nsurf;
508
509 rects = pixman_region32_rectangles(region, &nrects);
510 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
511
512 /* worst case we can have 8 vertices per rect (ie. clipped into
513 * an octagon):
514 */
515 v = wl_array_add(&ec->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
516 vtxcnt = wl_array_add(&ec->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
517
518 inv_width = 1.0 / es->pitch;
519 inv_height = 1.0 / es->geometry.height;
520
521 for (i = 0; i < nrects; i++) {
522 pixman_box32_t *rect = &rects[i];
523 for (j = 0; j < nsurf; j++) {
524 pixman_box32_t *surf_rect = &surf_rects[j];
525 GLfloat sx, sy;
526 GLfloat ex[8], ey[8]; /* edge points in screen space */
527 int n;
528
529 /* The transformed surface, after clipping to the clip region,
530 * can have as many as eight sides, emitted as a triangle-fan.
531 * The first vertex in the triangle fan can be chosen arbitrarily,
532 * since the area is guaranteed to be convex.
533 *
534 * If a corner of the transformed surface falls outside of the
535 * clip region, instead of emitting one vertex for the corner
536 * of the surface, up to two are emitted for two corresponding
537 * intersection point(s) between the surface and the clip region.
538 *
539 * To do this, we first calculate the (up to eight) points that
540 * form the intersection of the clip rect and the transformed
541 * surface.
542 */
543 n = calculate_edges(es, rect, surf_rect, ex, ey);
544 if (n < 3)
545 continue;
546
547 /* emit edge points: */
548 for (k = 0; k < n; k++) {
549 weston_surface_from_global_float(es, ex[k], ey[k], &sx, &sy);
550 /* position: */
551 *(v++) = ex[k];
552 *(v++) = ey[k];
553 /* texcoord: */
554 *(v++) = sx * inv_width;
555 *(v++) = sy * inv_height;
556 }
557
558 vtxcnt[nvtx++] = n;
559 }
560 }
561
562 return nvtx;
563}
564
565static void
566triangle_fan_debug(struct weston_surface *surface, int first, int count)
567{
568 struct weston_compositor *compositor = surface->compositor;
John Kåre Alsaker40684142012-11-13 19:10:25 +0100569 struct gles2_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400570 int i;
571 GLushort *buffer;
572 GLushort *index;
573 int nelems;
574 static int color_idx = 0;
575 static const GLfloat color[][4] = {
576 { 1.0, 0.0, 0.0, 1.0 },
577 { 0.0, 1.0, 0.0, 1.0 },
578 { 0.0, 0.0, 1.0, 1.0 },
579 { 1.0, 1.0, 1.0, 1.0 },
580 };
581
582 nelems = (count - 1 + count - 2) * 2;
583
584 buffer = malloc(sizeof(GLushort) * nelems);
585 index = buffer;
586
587 for (i = 1; i < count; i++) {
588 *index++ = first;
589 *index++ = first + i;
590 }
591
592 for (i = 2; i < count; i++) {
593 *index++ = first + i - 1;
594 *index++ = first + i;
595 }
596
John Kåre Alsaker40684142012-11-13 19:10:25 +0100597 glUseProgram(gr->solid_shader.program);
598 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400599 color[color_idx++ % ARRAY_LENGTH(color)]);
600 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100601 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400602 free(buffer);
603}
604
605static void
606repaint_region(struct weston_surface *es, pixman_region32_t *region,
607 pixman_region32_t *surf_region)
608{
609 struct weston_compositor *ec = es->compositor;
610 GLfloat *v;
611 unsigned int *vtxcnt;
612 int i, first, nfans;
613
614 /* The final region to be painted is the intersection of
615 * 'region' and 'surf_region'. However, 'region' is in the global
616 * coordinates, and 'surf_region' is in the surface-local
617 * coordinates. texture_region() will iterate over all pairs of
618 * rectangles from both regions, compute the intersection
619 * polygon for each pair, and store it as a triangle fan if
620 * it has a non-zero area (at least 3 vertices, actually).
621 */
622 nfans = texture_region(es, region, surf_region);
623
624 v = ec->vertices.data;
625 vtxcnt = ec->vtxcnt.data;
626
627 /* position: */
628 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
629 glEnableVertexAttribArray(0);
630
631 /* texcoord: */
632 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
633 glEnableVertexAttribArray(1);
634
635 for (i = 0, first = 0; i < nfans; i++) {
636 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
637 if (ec->fan_debug)
638 triangle_fan_debug(es, first, vtxcnt[i]);
639 first += vtxcnt[i];
640 }
641
642 glDisableVertexAttribArray(1);
643 glDisableVertexAttribArray(0);
644
645 ec->vertices.size = 0;
646 ec->vtxcnt.size = 0;
647}
648
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100649static int
650use_output(struct weston_output *output)
651{
652 static int errored;
653 struct gles2_output_state *go = get_output_state(output);
654 struct gles2_renderer *gr = get_renderer(output->compositor);
655 EGLBoolean ret;
656
657 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
658 go->egl_surface, gr->egl_context);
659
660 if (ret == EGL_FALSE) {
661 if (errored)
662 return -1;
663 errored = 1;
664 weston_log("Failed to make EGL context current.\n");
665 print_egl_error_state();
666 return -1;
667 }
668
669 return 0;
670}
671
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400672static void
John Kåre Alsaker40684142012-11-13 19:10:25 +0100673use_shader(struct gles2_renderer *gr,
674 struct gles2_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400675{
John Kåre Alsaker40684142012-11-13 19:10:25 +0100676 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400677 return;
678
679 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100680 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400681}
682
683static void
John Kåre Alsaker40684142012-11-13 19:10:25 +0100684shader_uniforms(struct gles2_shader *shader,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400685 struct weston_surface *surface,
686 struct weston_output *output)
687{
688 int i;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100689 struct gles2_surface_state *gs = get_surface_state(surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400690
691 glUniformMatrix4fv(shader->proj_uniform,
692 1, GL_FALSE, output->matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100693 glUniform4fv(shader->color_uniform, 1, gs->color);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400694 glUniform1f(shader->alpha_uniform, surface->alpha);
695
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100696 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400697 glUniform1i(shader->tex_uniforms[i], i);
698}
699
700static void
701draw_surface(struct weston_surface *es, struct weston_output *output,
702 pixman_region32_t *damage) /* in global coordinates */
703{
704 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker40684142012-11-13 19:10:25 +0100705 struct gles2_renderer *gr = get_renderer(ec);
706 struct gles2_surface_state *gs = get_surface_state(es);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400707 /* repaint bounding region in global coordinates: */
708 pixman_region32_t repaint;
709 /* non-opaque region in surface coordinates: */
710 pixman_region32_t surface_blend;
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300711 pixman_region32_t *buffer_damage;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400712 GLint filter;
713 int i;
714
715 pixman_region32_init(&repaint);
716 pixman_region32_intersect(&repaint,
717 &es->transform.boundingbox, damage);
718 pixman_region32_subtract(&repaint, &repaint, &es->clip);
719
720 if (!pixman_region32_not_empty(&repaint))
721 goto out;
722
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300723 buffer_damage = &output->buffer_damage[output->current_buffer];
724 pixman_region32_subtract(buffer_damage, buffer_damage, &repaint);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400725
726 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
727
728 if (ec->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100729 use_shader(gr, &gr->solid_shader);
730 shader_uniforms(&gr->solid_shader, es, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400731 }
732
John Kåre Alsaker40684142012-11-13 19:10:25 +0100733 use_shader(gr, gs->shader);
734 shader_uniforms(gs->shader, es, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400735
736 if (es->transform.enabled || output->zoom.active)
737 filter = GL_LINEAR;
738 else
739 filter = GL_NEAREST;
740
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100741 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400742 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100743 glBindTexture(gs->target, gs->textures[i]);
744 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
745 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400746 }
747
748 /* blended region is whole surface minus opaque region: */
749 pixman_region32_init_rect(&surface_blend, 0, 0,
750 es->geometry.width, es->geometry.height);
751 pixman_region32_subtract(&surface_blend, &surface_blend, &es->opaque);
752
753 if (pixman_region32_not_empty(&es->opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100754 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400755 /* Special case for RGBA textures with possibly
756 * bad data in alpha channel: use the shader
757 * that forces texture alpha = 1.0.
758 * Xwayland surfaces need this.
759 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100760 use_shader(gr, &gr->texture_shader_rgbx);
761 shader_uniforms(&gr->texture_shader_rgbx, es, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400762 }
763
764 if (es->alpha < 1.0)
765 glEnable(GL_BLEND);
766 else
767 glDisable(GL_BLEND);
768
769 repaint_region(es, &repaint, &es->opaque);
770 }
771
772 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100773 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400774 glEnable(GL_BLEND);
775 repaint_region(es, &repaint, &surface_blend);
776 }
777
778 pixman_region32_fini(&surface_blend);
779
780out:
781 pixman_region32_fini(&repaint);
782}
783
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400784static void
785repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
786{
787 struct weston_compositor *compositor = output->compositor;
788 struct weston_surface *surface;
789
790 wl_list_for_each_reverse(surface, &compositor->surface_list, link)
791 if (surface->plane == &compositor->primary_plane)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400792 draw_surface(surface, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400793}
794
John Kåre Alsaker44154502012-11-13 19:10:20 +0100795
796static int
797texture_border(struct weston_output *output)
798{
799 struct weston_compositor *ec = output->compositor;
800 struct gles2_renderer *gr = get_renderer(ec);
801 GLfloat *d;
802 unsigned int *p;
803 int i, j, k, n;
804 GLfloat x[4], y[4], u[4], v[4];
805
806 x[0] = -gr->border.left;
807 x[1] = 0;
808 x[2] = output->current->width;
809 x[3] = output->current->width + gr->border.right;
810
811 y[0] = -gr->border.top;
812 y[1] = 0;
813 y[2] = output->current->height;
814 y[3] = output->current->height + gr->border.bottom;
815
816 u[0] = 0.0;
817 u[1] = (GLfloat) gr->border.left / gr->border.width;
818 u[2] = (GLfloat) (gr->border.width - gr->border.right) / gr->border.width;
819 u[3] = 1.0;
820
821 v[0] = 0.0;
822 v[1] = (GLfloat) gr->border.top / gr->border.height;
823 v[2] = (GLfloat) (gr->border.height - gr->border.bottom) / gr->border.height;
824 v[3] = 1.0;
825
826 n = 8;
827 d = wl_array_add(&ec->vertices, n * 16 * sizeof *d);
828 p = wl_array_add(&ec->indices, n * 6 * sizeof *p);
829
830 k = 0;
831 for (i = 0; i < 3; i++)
832 for (j = 0; j < 3; j++) {
833
834 if (i == 1 && j == 1)
835 continue;
836
837 d[ 0] = x[i];
838 d[ 1] = y[j];
839 d[ 2] = u[i];
840 d[ 3] = v[j];
841
842 d[ 4] = x[i];
843 d[ 5] = y[j + 1];
844 d[ 6] = u[i];
845 d[ 7] = v[j + 1];
846
847 d[ 8] = x[i + 1];
848 d[ 9] = y[j];
849 d[10] = u[i + 1];
850 d[11] = v[j];
851
852 d[12] = x[i + 1];
853 d[13] = y[j + 1];
854 d[14] = u[i + 1];
855 d[15] = v[j + 1];
856
857 p[0] = k + 0;
858 p[1] = k + 1;
859 p[2] = k + 2;
860 p[3] = k + 2;
861 p[4] = k + 1;
862 p[5] = k + 3;
863
864 d += 16;
865 p += 6;
866 k += 4;
867 }
868
869 return k / 4;
870}
871
872static void
873draw_border(struct weston_output *output)
874{
875 struct weston_compositor *ec = output->compositor;
876 struct gles2_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100877 struct gles2_shader *shader = &gr->texture_shader_rgba;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100878 GLfloat *v;
879 int n;
880
881 glDisable(GL_BLEND);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100882 use_shader(gr, shader);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100883
884 glUniformMatrix4fv(shader->proj_uniform,
885 1, GL_FALSE, output->matrix.d);
886
887 glUniform1i(shader->tex_uniforms[0], 0);
888 glUniform1f(shader->alpha_uniform, 1);
889
890 n = texture_border(output);
891
892 glActiveTexture(GL_TEXTURE0);
893 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
894
895 v = ec->vertices.data;
896 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
897 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
898 glEnableVertexAttribArray(0);
899 glEnableVertexAttribArray(1);
900
901 glDrawElements(GL_TRIANGLES, n * 6,
902 GL_UNSIGNED_INT, ec->indices.data);
903
904 glDisableVertexAttribArray(1);
905 glDisableVertexAttribArray(0);
906
907 ec->vertices.size = 0;
908 ec->indices.size = 0;
909}
910
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400911static void
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400912gles2_renderer_repaint_output(struct weston_output *output,
913 pixman_region32_t *output_damage)
914{
John Kåre Alsaker94659272012-11-13 19:10:18 +0100915 struct gles2_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400916 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100917 struct gles2_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400918 EGLBoolean ret;
919 static int errored;
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300920 int32_t width, height, i;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400921
922 width = output->current->width +
923 output->border.left + output->border.right;
924 height = output->current->height +
925 output->border.top + output->border.bottom;
926
927 glViewport(0, 0, width, height);
928
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100929 if (use_output(output) < 0)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400930 return;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400931
932 /* if debugging, redraw everything outside the damage to clean up
933 * debug lines from the previous draw on this buffer:
934 */
935 if (compositor->fan_debug) {
936 pixman_region32_t undamaged;
937 pixman_region32_init(&undamaged);
938 pixman_region32_subtract(&undamaged, &output->region,
939 output_damage);
940 compositor->fan_debug = 0;
941 repaint_surfaces(output, &undamaged);
942 compositor->fan_debug = 1;
943 pixman_region32_fini(&undamaged);
944 }
945
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300946 for (i = 0; i < 2; i++)
947 pixman_region32_union(&output->buffer_damage[i],
948 &output->buffer_damage[i],
949 output_damage);
950
951 pixman_region32_union(output_damage, output_damage,
952 &output->buffer_damage[output->current_buffer]);
953
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400954 repaint_surfaces(output, output_damage);
955
John Kåre Alsaker44154502012-11-13 19:10:20 +0100956 if (gr->border.texture)
957 draw_border(output);
958
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400959 wl_signal_emit(&output->frame_signal, output);
960
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100961 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400962 if (ret == EGL_FALSE && !errored) {
963 errored = 1;
964 weston_log("Failed in eglSwapBuffers.\n");
965 print_egl_error_state();
966 }
967
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300968 output->current_buffer ^= 1;
969
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400970}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -0400971
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100972static int
973gles2_renderer_read_pixels(struct weston_output *output,
974 pixman_format_code_t format, void *pixels,
975 uint32_t x, uint32_t y,
976 uint32_t width, uint32_t height)
977{
978 GLenum gl_format;
979
980 switch (format) {
981 case PIXMAN_a8r8g8b8:
982 gl_format = GL_BGRA_EXT;
983 break;
984 case PIXMAN_a8b8g8r8:
985 gl_format = GL_RGBA;
986 break;
987 default:
988 return -1;
989 }
990
991 if (use_output(output) < 0)
992 return -1;
993
994 glPixelStorei(GL_PACK_ALIGNMENT, 1);
995 glReadPixels(x, y, width, height, gl_format,
996 GL_UNSIGNED_BYTE, pixels);
997
998 return 0;
999}
1000
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001001static void
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001002gles2_renderer_flush_damage(struct weston_surface *surface)
1003{
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001004 struct gles2_surface_state *gs = get_surface_state(surface);
1005
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001006#ifdef GL_UNPACK_ROW_LENGTH
1007 pixman_box32_t *rectangles;
1008 void *data;
1009 int i, n;
1010#endif
1011
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001012 pixman_region32_union(&surface->texture_damage,
1013 &surface->texture_damage, &surface->damage);
1014
1015 /* Avoid upload, if the texture won't be used this time.
1016 * We still accumulate the damage in texture_damage.
1017 */
1018 if (surface->plane != &surface->compositor->primary_plane)
1019 return;
1020
1021 if (!pixman_region32_not_empty(&surface->texture_damage))
1022 return;
1023
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001024 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001025
1026 if (!surface->compositor->has_unpack_subimage) {
1027 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1028 surface->pitch, surface->buffer->height, 0,
1029 GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1030 wl_shm_buffer_get_data(surface->buffer));
1031
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001032 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001033 }
1034
1035#ifdef GL_UNPACK_ROW_LENGTH
1036 /* Mesa does not define GL_EXT_unpack_subimage */
1037 glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch);
1038 data = wl_shm_buffer_get_data(surface->buffer);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001039 rectangles = pixman_region32_rectangles(&surface->texture_damage, &n);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001040 for (i = 0; i < n; i++) {
1041 glPixelStorei(GL_UNPACK_SKIP_PIXELS, rectangles[i].x1);
1042 glPixelStorei(GL_UNPACK_SKIP_ROWS, rectangles[i].y1);
1043 glTexSubImage2D(GL_TEXTURE_2D, 0,
1044 rectangles[i].x1, rectangles[i].y1,
1045 rectangles[i].x2 - rectangles[i].x1,
1046 rectangles[i].y2 - rectangles[i].y1,
1047 GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
1048 }
1049#endif
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001050
1051done:
1052 pixman_region32_fini(&surface->texture_damage);
1053 pixman_region32_init(&surface->texture_damage);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001054}
1055
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001056static void
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001057ensure_textures(struct gles2_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001058{
1059 int i;
1060
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001061 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001062 return;
1063
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001064 for (i = gs->num_textures; i < num_textures; i++) {
1065 glGenTextures(1, &gs->textures[i]);
1066 glBindTexture(gs->target, gs->textures[i]);
1067 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001068 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001069 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001070 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1071 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001072 gs->num_textures = num_textures;
1073 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001074}
1075
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001076static void
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001077gles2_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
1078{
1079 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001080 struct gles2_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01001081 struct gles2_surface_state *gs = get_surface_state(es);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001082 EGLint attribs[3], format;
1083 int i, num_planes;
1084
1085 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001086 for (i = 0; i < gs->num_images; i++) {
1087 ec->destroy_image(gr->egl_display, gs->images[i]);
1088 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001089 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001090 gs->num_images = 0;
1091 glDeleteTextures(gs->num_textures, gs->textures);
1092 gs->num_textures = 0;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001093 return;
1094 }
1095
1096 if (wl_buffer_is_shm(buffer)) {
1097 es->pitch = wl_shm_buffer_get_stride(buffer) / 4;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001098 gs->target = GL_TEXTURE_2D;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001099
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001100 ensure_textures(gs, 1);
1101 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001102 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1103 es->pitch, buffer->height, 0,
1104 GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1105 if (wl_shm_buffer_get_format(buffer) == WL_SHM_FORMAT_XRGB8888)
John Kåre Alsaker40684142012-11-13 19:10:25 +01001106 gs->shader = &gr->texture_shader_rgbx;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001107 else
John Kåre Alsaker40684142012-11-13 19:10:25 +01001108 gs->shader = &gr->texture_shader_rgba;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001109 } else if (ec->query_buffer(gr->egl_display, buffer,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001110 EGL_TEXTURE_FORMAT, &format)) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001111 for (i = 0; i < gs->num_images; i++)
1112 ec->destroy_image(gr->egl_display, gs->images[i]);
1113 gs->num_images = 0;
1114 gs->target = GL_TEXTURE_2D;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001115 switch (format) {
1116 case EGL_TEXTURE_RGB:
1117 case EGL_TEXTURE_RGBA:
1118 default:
1119 num_planes = 1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001120 gs->shader = &gr->texture_shader_rgba;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001121 break;
1122 case EGL_TEXTURE_EXTERNAL_WL:
1123 num_planes = 1;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001124 gs->target = GL_TEXTURE_EXTERNAL_OES;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001125 gs->shader = &gr->texture_shader_egl_external;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001126 break;
1127 case EGL_TEXTURE_Y_UV_WL:
1128 num_planes = 2;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001129 gs->shader = &gr->texture_shader_y_uv;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001130 break;
1131 case EGL_TEXTURE_Y_U_V_WL:
1132 num_planes = 3;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001133 gs->shader = &gr->texture_shader_y_u_v;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001134 break;
1135 case EGL_TEXTURE_Y_XUXV_WL:
1136 num_planes = 2;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001137 gs->shader = &gr->texture_shader_y_xuxv;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001138 break;
1139 }
1140
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001141 ensure_textures(gs, num_planes);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001142 for (i = 0; i < num_planes; i++) {
1143 attribs[0] = EGL_WAYLAND_PLANE_WL;
1144 attribs[1] = i;
1145 attribs[2] = EGL_NONE;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001146 gs->images[i] = ec->create_image(gr->egl_display,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001147 NULL,
1148 EGL_WAYLAND_BUFFER_WL,
1149 buffer, attribs);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001150 if (!gs->images[i]) {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001151 weston_log("failed to create img for plane %d\n", i);
1152 continue;
1153 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001154 gs->num_images++;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001155
1156 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001157 glBindTexture(gs->target, gs->textures[i]);
1158 ec->image_target_texture_2d(gs->target,
1159 gs->images[i]);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001160 }
1161
1162 es->pitch = buffer->width;
1163 } else {
1164 weston_log("unhandled buffer type!\n");
1165 }
1166}
1167
Kristian Høgsberg42263852012-09-06 21:59:29 -04001168static void
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001169gles2_renderer_surface_set_color(struct weston_surface *surface,
1170 float red, float green, float blue, float alpha)
1171{
1172 struct gles2_surface_state *gs = get_surface_state(surface);
John Kåre Alsaker40684142012-11-13 19:10:25 +01001173 struct gles2_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001174
1175 gs->color[0] = red;
1176 gs->color[1] = green;
1177 gs->color[2] = blue;
1178 gs->color[3] = alpha;
1179
John Kåre Alsaker40684142012-11-13 19:10:25 +01001180 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001181}
1182
1183static int
1184gles2_renderer_create_surface(struct weston_surface *surface)
1185{
1186 struct gles2_surface_state *gs;
1187
1188 gs = calloc(1, sizeof *gs);
1189
1190 if (!gs)
1191 return -1;
1192
1193 surface->renderer_state = gs;
1194
1195 return 0;
1196}
1197
1198static void
Kristian Høgsberg42263852012-09-06 21:59:29 -04001199gles2_renderer_destroy_surface(struct weston_surface *surface)
1200{
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001201 struct gles2_surface_state *gs = get_surface_state(surface);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001202 struct weston_compositor *ec = surface->compositor;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001203 struct gles2_renderer *gr = get_renderer(ec);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001204 int i;
1205
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001206 glDeleteTextures(gs->num_textures, gs->textures);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001207
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001208 for (i = 0; i < gs->num_images; i++)
1209 ec->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001210
1211 free(gs);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001212}
1213
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001214static const char vertex_shader[] =
1215 "uniform mat4 proj;\n"
1216 "attribute vec2 position;\n"
1217 "attribute vec2 texcoord;\n"
1218 "varying vec2 v_texcoord;\n"
1219 "void main()\n"
1220 "{\n"
1221 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1222 " v_texcoord = texcoord;\n"
1223 "}\n";
1224
1225/* Declare common fragment shader uniforms */
1226#define FRAGMENT_CONVERT_YUV \
1227 " y *= alpha;\n" \
1228 " u *= alpha;\n" \
1229 " v *= alpha;\n" \
1230 " gl_FragColor.r = y + 1.59602678 * v;\n" \
1231 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
1232 " gl_FragColor.b = y + 2.01723214 * u;\n" \
1233 " gl_FragColor.a = alpha;\n"
1234
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001235static const char fragment_debug[] =
1236 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
1237
1238static const char fragment_brace[] =
1239 "}\n";
1240
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001241static const char texture_fragment_shader_rgba[] =
1242 "precision mediump float;\n"
1243 "varying vec2 v_texcoord;\n"
1244 "uniform sampler2D tex;\n"
1245 "uniform float alpha;\n"
1246 "void main()\n"
1247 "{\n"
1248 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001249 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001250
1251static const char texture_fragment_shader_rgbx[] =
1252 "precision mediump float;\n"
1253 "varying vec2 v_texcoord;\n"
1254 "uniform sampler2D tex;\n"
1255 "uniform float alpha;\n"
1256 "void main()\n"
1257 "{\n"
1258 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
1259 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001260 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001261
1262static const char texture_fragment_shader_egl_external[] =
1263 "#extension GL_OES_EGL_image_external : require\n"
1264 "precision mediump float;\n"
1265 "varying vec2 v_texcoord;\n"
1266 "uniform samplerExternalOES tex;\n"
1267 "uniform float alpha;\n"
1268 "void main()\n"
1269 "{\n"
1270 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001271 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001272
1273static const char texture_fragment_shader_y_uv[] =
1274 "precision mediump float;\n"
1275 "uniform sampler2D tex;\n"
1276 "uniform sampler2D tex1;\n"
1277 "varying vec2 v_texcoord;\n"
1278 "uniform float alpha;\n"
1279 "void main() {\n"
1280 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1281 " float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
1282 " float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
1283 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001284 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001285
1286static const char texture_fragment_shader_y_u_v[] =
1287 "precision mediump float;\n"
1288 "uniform sampler2D tex;\n"
1289 "uniform sampler2D tex1;\n"
1290 "uniform sampler2D tex2;\n"
1291 "varying vec2 v_texcoord;\n"
1292 "uniform float alpha;\n"
1293 "void main() {\n"
1294 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1295 " float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
1296 " float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
1297 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001298 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001299
1300static const char texture_fragment_shader_y_xuxv[] =
1301 "precision mediump float;\n"
1302 "uniform sampler2D tex;\n"
1303 "uniform sampler2D tex1;\n"
1304 "varying vec2 v_texcoord;\n"
1305 "uniform float alpha;\n"
1306 "void main() {\n"
1307 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1308 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
1309 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
1310 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001311 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001312
1313static const char solid_fragment_shader[] =
1314 "precision mediump float;\n"
1315 "uniform vec4 color;\n"
1316 "uniform float alpha;\n"
1317 "void main()\n"
1318 "{\n"
1319 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001320 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001321
1322static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001323compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001324{
1325 GLuint s;
1326 char msg[512];
1327 GLint status;
1328
1329 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001330 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001331 glCompileShader(s);
1332 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1333 if (!status) {
1334 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1335 weston_log("shader info: %s\n", msg);
1336 return GL_NONE;
1337 }
1338
1339 return s;
1340}
1341
1342static int
John Kåre Alsaker40684142012-11-13 19:10:25 +01001343shader_init(struct gles2_shader *shader, struct weston_compositor *ec,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001344 const char *vertex_source, const char *fragment_source)
1345{
1346 char msg[512];
1347 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001348 int count;
1349 const char *sources[3];
1350 struct gles2_renderer *renderer =
1351 (struct gles2_renderer *) ec->renderer;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001352
1353 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001354 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
1355
1356 if (renderer->fragment_shader_debug) {
1357 sources[0] = fragment_source;
1358 sources[1] = fragment_debug;
1359 sources[2] = fragment_brace;
1360 count = 3;
1361 } else {
1362 sources[0] = fragment_source;
1363 sources[1] = fragment_brace;
1364 count = 2;
1365 }
1366
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001367 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001368 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001369
1370 shader->program = glCreateProgram();
1371 glAttachShader(shader->program, shader->vertex_shader);
1372 glAttachShader(shader->program, shader->fragment_shader);
1373 glBindAttribLocation(shader->program, 0, "position");
1374 glBindAttribLocation(shader->program, 1, "texcoord");
1375
1376 glLinkProgram(shader->program);
1377 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1378 if (!status) {
1379 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1380 weston_log("link info: %s\n", msg);
1381 return -1;
1382 }
1383
1384 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1385 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
1386 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
1387 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
1388 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
1389 shader->color_uniform = glGetUniformLocation(shader->program, "color");
1390
1391 return 0;
1392}
1393
1394static void
John Kåre Alsaker40684142012-11-13 19:10:25 +01001395shader_release(struct gles2_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001396{
1397 glDeleteShader(shader->vertex_shader);
1398 glDeleteShader(shader->fragment_shader);
1399 glDeleteProgram(shader->program);
1400
1401 shader->vertex_shader = 0;
1402 shader->fragment_shader = 0;
1403 shader->program = 0;
1404}
1405
1406static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001407log_extensions(const char *name, const char *extensions)
1408{
1409 const char *p, *end;
1410 int l;
1411 int len;
1412
1413 l = weston_log("%s:", name);
1414 p = extensions;
1415 while (*p) {
1416 end = strchrnul(p, ' ');
1417 len = end - p;
1418 if (l + len > 78)
1419 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
1420 len, p);
1421 else
1422 l += weston_log_continue(" %.*s", len, p);
1423 for (p = end; isspace(*p); p++)
1424 ;
1425 }
1426 weston_log_continue("\n");
1427}
1428
1429static void
1430log_egl_gl_info(EGLDisplay egldpy)
1431{
1432 const char *str;
1433
1434 str = eglQueryString(egldpy, EGL_VERSION);
1435 weston_log("EGL version: %s\n", str ? str : "(null)");
1436
1437 str = eglQueryString(egldpy, EGL_VENDOR);
1438 weston_log("EGL vendor: %s\n", str ? str : "(null)");
1439
1440 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
1441 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
1442
1443 str = eglQueryString(egldpy, EGL_EXTENSIONS);
1444 log_extensions("EGL extensions", str ? str : "(null)");
1445
1446 str = (char *)glGetString(GL_VERSION);
1447 weston_log("GL version: %s\n", str ? str : "(null)");
1448
1449 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1450 weston_log("GLSL version: %s\n", str ? str : "(null)");
1451
1452 str = (char *)glGetString(GL_VENDOR);
1453 weston_log("GL vendor: %s\n", str ? str : "(null)");
1454
1455 str = (char *)glGetString(GL_RENDERER);
1456 weston_log("GL renderer: %s\n", str ? str : "(null)");
1457
1458 str = (char *)glGetString(GL_EXTENSIONS);
1459 log_extensions("GL extensions", str ? str : "(null)");
1460}
1461
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001462static void
1463log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
1464{
1465 EGLint r, g, b, a;
1466
1467 weston_log("Chosen EGL config details:\n");
1468
1469 weston_log_continue(STAMP_SPACE "RGBA bits");
1470 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
1471 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
1472 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
1473 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
1474 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
1475 else
1476 weston_log_continue(" unknown\n");
1477
1478 weston_log_continue(STAMP_SPACE "swap interval range");
1479 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
1480 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
1481 weston_log_continue(": %d - %d\n", a, b);
1482 else
1483 weston_log_continue(" unknown\n");
1484}
1485
John Kåre Alsaker44154502012-11-13 19:10:20 +01001486static void
1487output_apply_border(struct weston_output *output, struct gles2_renderer *gr)
1488{
1489 output->border.top = gr->border.top;
1490 output->border.bottom = gr->border.bottom;
1491 output->border.left = gr->border.left;
1492 output->border.right = gr->border.right;
1493}
1494
1495WL_EXPORT void
1496gles2_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
1497 int32_t *edges)
1498{
1499 struct gles2_renderer *gr = get_renderer(ec);
1500 struct weston_output *output;
1501
1502 gr->border.left = edges[0];
1503 gr->border.right = edges[1];
1504 gr->border.top = edges[2];
1505 gr->border.bottom = edges[3];
1506
1507 gr->border.width = width;
1508 gr->border.height = height;
1509
1510 glGenTextures(1, &gr->border.texture);
1511 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
1512 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1513 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1514 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1515 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1516
1517 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1518 width,
1519 height,
1520 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1521 data);
1522
1523 wl_list_for_each(output, &ec->output_list, link)
1524 output_apply_border(output, gr);
1525}
1526
John Kåre Alsaker94659272012-11-13 19:10:18 +01001527static int
1528gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
1529
1530WL_EXPORT int
1531gles2_renderer_output_create(struct weston_output *output,
1532 EGLNativeWindowType window)
1533{
1534 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001535 struct gles2_renderer *gr = get_renderer(ec);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001536 struct gles2_output_state *go = calloc(1, sizeof *go);
1537
1538 if (!go)
1539 return -1;
1540
1541 go->egl_surface =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001542 eglCreateWindowSurface(gr->egl_display,
1543 gr->egl_config,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001544 window, NULL);
1545
1546 if (go->egl_surface == EGL_NO_SURFACE) {
1547 weston_log("failed to create egl surface\n");
1548 free(go);
1549 return -1;
1550 }
1551
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001552 if (gr->egl_context == NULL)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001553 if (gles2_renderer_setup(ec, go->egl_surface) < 0) {
1554 free(go);
1555 return -1;
1556 }
1557
1558 output->renderer_state = go;
1559
John Kåre Alsaker44154502012-11-13 19:10:20 +01001560 output_apply_border(output, gr);
1561
John Kåre Alsaker94659272012-11-13 19:10:18 +01001562 return 0;
1563}
1564
1565WL_EXPORT void
1566gles2_renderer_output_destroy(struct weston_output *output)
1567{
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001568 struct gles2_renderer *gr = get_renderer(output->compositor);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001569 struct gles2_output_state *go = get_output_state(output);
1570
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001571 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001572
1573 free(go);
1574}
1575
1576WL_EXPORT EGLSurface
1577gles2_renderer_output_surface(struct weston_output *output)
1578{
1579 return get_output_state(output)->egl_surface;
1580}
1581
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001582WL_EXPORT void
1583gles2_renderer_destroy(struct weston_compositor *ec)
1584{
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001585 struct gles2_renderer *gr = get_renderer(ec);
1586
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001587 if (ec->has_bind_display)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001588 ec->unbind_display(gr->egl_display, ec->wl_display);
1589
1590 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
1591 eglMakeCurrent(gr->egl_display,
1592 EGL_NO_SURFACE, EGL_NO_SURFACE,
1593 EGL_NO_CONTEXT);
1594
1595 eglTerminate(gr->egl_display);
1596 eglReleaseThread();
1597}
1598
1599static int
1600egl_choose_config(struct gles2_renderer *gr, const EGLint *attribs,
1601 const EGLint *visual_id)
1602{
1603 EGLint count = 0;
1604 EGLint matched = 0;
1605 EGLConfig *configs;
1606 int i;
1607
1608 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
1609 return -1;
1610
1611 configs = calloc(count, sizeof *configs);
1612 if (!configs)
1613 return -1;
1614
1615 if (!eglChooseConfig(gr->egl_display, attribs, configs,
1616 count, &matched))
1617 goto out;
1618
1619 for (i = 0; i < matched; ++i) {
1620 EGLint id;
1621
1622 if (visual_id) {
1623 if (!eglGetConfigAttrib(gr->egl_display,
1624 configs[i], EGL_NATIVE_VISUAL_ID,
1625 &id))
1626 continue;
1627
1628 if (id != *visual_id)
1629 continue;
1630 }
1631
1632 gr->egl_config = configs[i];
1633
1634 free(configs);
1635 return 0;
1636 }
1637
1638out:
1639 free(configs);
1640 return -1;
1641}
1642
1643WL_EXPORT const EGLint gles2_renderer_opaque_attribs[] = {
1644 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1645 EGL_RED_SIZE, 1,
1646 EGL_GREEN_SIZE, 1,
1647 EGL_BLUE_SIZE, 1,
1648 EGL_ALPHA_SIZE, 0,
1649 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1650 EGL_NONE
1651};
1652
1653WL_EXPORT const EGLint gles2_renderer_alpha_attribs[] = {
1654 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1655 EGL_RED_SIZE, 1,
1656 EGL_GREEN_SIZE, 1,
1657 EGL_BLUE_SIZE, 1,
1658 EGL_ALPHA_SIZE, 1,
1659 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1660 EGL_NONE
1661};
1662
1663WL_EXPORT int
1664gles2_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
1665 const EGLint *attribs, const EGLint *visual_id)
1666{
1667 struct gles2_renderer *gr;
1668 EGLint major, minor;
1669
1670 gr = calloc(1, sizeof *gr);
1671
1672 if (gr == NULL)
1673 return -1;
1674
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001675 gr->base.read_pixels = gles2_renderer_read_pixels;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001676 gr->base.repaint_output = gles2_renderer_repaint_output;
1677 gr->base.flush_damage = gles2_renderer_flush_damage;
1678 gr->base.attach = gles2_renderer_attach;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001679 gr->base.create_surface = gles2_renderer_create_surface;
1680 gr->base.surface_set_color = gles2_renderer_surface_set_color;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001681 gr->base.destroy_surface = gles2_renderer_destroy_surface;
1682
1683 gr->egl_display = eglGetDisplay(display);
1684 if (gr->egl_display == EGL_NO_DISPLAY) {
1685 weston_log("failed to create display\n");
1686 goto err_egl;
1687 }
1688
1689 if (!eglInitialize(gr->egl_display, &major, &minor)) {
1690 weston_log("failed to initialize display\n");
1691 goto err_egl;
1692 }
1693
1694 if (egl_choose_config(gr, attribs, visual_id) < 0) {
1695 weston_log("failed to choose EGL config\n");
1696 goto err_egl;
1697 }
1698
1699 ec->renderer = &gr->base;
1700
1701 return 0;
1702
1703err_egl:
1704 print_egl_error_state();
1705 free(gr);
1706 return -1;
1707}
1708
1709WL_EXPORT EGLDisplay
1710gles2_renderer_display(struct weston_compositor *ec)
1711{
1712 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001713}
1714
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001715static int
1716compile_shaders(struct weston_compositor *ec)
1717{
John Kåre Alsaker40684142012-11-13 19:10:25 +01001718 struct gles2_renderer *gr = get_renderer(ec);
1719
1720 if (shader_init(&gr->texture_shader_rgba, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001721 vertex_shader, texture_fragment_shader_rgba) < 0)
1722 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001723 if (shader_init(&gr->texture_shader_rgbx, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001724 vertex_shader, texture_fragment_shader_rgbx) < 0)
1725 return -1;
1726 if (ec->has_egl_image_external &&
John Kåre Alsaker40684142012-11-13 19:10:25 +01001727 shader_init(&gr->texture_shader_egl_external, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001728 vertex_shader, texture_fragment_shader_egl_external) < 0)
1729 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001730 if (shader_init(&gr->texture_shader_y_uv, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001731 vertex_shader, texture_fragment_shader_y_uv) < 0)
1732 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001733 if (shader_init(&gr->texture_shader_y_u_v, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001734 vertex_shader, texture_fragment_shader_y_u_v) < 0)
1735 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001736 if (shader_init(&gr->texture_shader_y_xuxv, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001737 vertex_shader, texture_fragment_shader_y_xuxv) < 0)
1738 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001739 if (shader_init(&gr->solid_shader, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001740 vertex_shader, solid_fragment_shader) < 0)
1741 return -1;
1742
1743 return 0;
1744}
1745
1746static void
1747fragment_debug_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
1748 void *data)
1749{
1750 struct weston_compositor *ec = data;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001751 struct gles2_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001752 struct weston_output *output;
1753
John Kåre Alsaker40684142012-11-13 19:10:25 +01001754 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001755
John Kåre Alsaker40684142012-11-13 19:10:25 +01001756 shader_release(&gr->texture_shader_rgba);
1757 shader_release(&gr->texture_shader_rgbx);
1758 shader_release(&gr->texture_shader_egl_external);
1759 shader_release(&gr->texture_shader_y_uv);
1760 shader_release(&gr->texture_shader_y_u_v);
1761 shader_release(&gr->texture_shader_y_xuxv);
1762 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001763
1764 compile_shaders(ec);
1765
1766 wl_list_for_each(output, &ec->output_list, link)
1767 weston_output_damage(output);
1768}
1769
John Kåre Alsaker94659272012-11-13 19:10:18 +01001770static int
1771gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001772{
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001773 struct gles2_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001774 const char *extensions;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001775 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001776
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001777 static const EGLint context_attribs[] = {
1778 EGL_CONTEXT_CLIENT_VERSION, 2,
1779 EGL_NONE
1780 };
1781
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001782 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1783 weston_log("failed to bind EGL_OPENGL_ES_API\n");
1784 print_egl_error_state();
1785 return -1;
1786 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001787
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001788 log_egl_config_info(gr->egl_display, gr->egl_config);
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001789
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001790 gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001791 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001792 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001793 weston_log("failed to create context\n");
1794 print_egl_error_state();
1795 return -1;
1796 }
1797
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001798 ret = eglMakeCurrent(gr->egl_display, egl_surface,
1799 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001800 if (ret == EGL_FALSE) {
1801 weston_log("Failed to make EGL context current.\n");
1802 print_egl_error_state();
1803 return -1;
1804 }
1805
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001806 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001807
1808 ec->image_target_texture_2d =
1809 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
1810 ec->image_target_renderbuffer_storage = (void *)
1811 eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
1812 ec->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1813 ec->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1814 ec->bind_display =
1815 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
1816 ec->unbind_display =
1817 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
1818 ec->query_buffer =
1819 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
1820
1821 extensions = (const char *) glGetString(GL_EXTENSIONS);
1822 if (!extensions) {
1823 weston_log("Retrieving GL extension string failed.\n");
1824 return -1;
1825 }
1826
1827 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
1828 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
1829 return -1;
1830 }
1831
1832 if (strstr(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001833 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001834 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001835 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001836
1837 if (strstr(extensions, "GL_EXT_unpack_subimage"))
1838 ec->has_unpack_subimage = 1;
1839
1840 if (strstr(extensions, "GL_OES_EGL_image_external"))
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001841 ec->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001842
1843 extensions =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001844 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001845 if (!extensions) {
1846 weston_log("Retrieving EGL extension string failed.\n");
1847 return -1;
1848 }
1849
1850 if (strstr(extensions, "EGL_WL_bind_wayland_display"))
1851 ec->has_bind_display = 1;
Pekka Paalanen035a0322012-10-24 09:43:06 +03001852 if (ec->has_bind_display) {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001853 ret = ec->bind_display(gr->egl_display, ec->wl_display);
Pekka Paalanen035a0322012-10-24 09:43:06 +03001854 if (!ret)
1855 ec->has_bind_display = 0;
1856 }
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001857
1858 glActiveTexture(GL_TEXTURE0);
1859
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001860 if (compile_shaders(ec))
1861 return -1;
1862
1863 weston_compositor_add_debug_binding(ec, KEY_S,
1864 fragment_debug_binding, ec);
1865
Pekka Paalanen035a0322012-10-24 09:43:06 +03001866 weston_log("GL ES 2 renderer features:\n");
1867 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
1868 ec->read_format == GL_BGRA_EXT ? "BGRA" : "RGBA");
1869 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
1870 ec->has_unpack_subimage ? "yes" : "no");
1871 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
1872 ec->has_bind_display ? "yes" : "no");
1873
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001874
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001875 return 0;
1876}