blob: 4f08a0cacaf6d31f70c86b778a5ceaaea48220f5 [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
John Kåre Alsaker320711d2012-11-13 19:10:27 +010073 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
74 PFNEGLCREATEIMAGEKHRPROC create_image;
75 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
76
77 int has_unpack_subimage;
78
79 PFNEGLBINDWAYLANDDISPLAYWL bind_display;
80 PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
81 PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
82 int has_bind_display;
83
84 int has_egl_image_external;
85
John Kåre Alsaker40684142012-11-13 19:10:25 +010086 struct gles2_shader texture_shader_rgba;
87 struct gles2_shader texture_shader_rgbx;
88 struct gles2_shader texture_shader_egl_external;
89 struct gles2_shader texture_shader_y_uv;
90 struct gles2_shader texture_shader_y_u_v;
91 struct gles2_shader texture_shader_y_xuxv;
92 struct gles2_shader invert_color_shader;
93 struct gles2_shader solid_shader;
94 struct gles2_shader *current_shader;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +010095};
John Kåre Alsaker94659272012-11-13 19:10:18 +010096
97static inline struct gles2_output_state *
98get_output_state(struct weston_output *output)
99{
100 return (struct gles2_output_state *)output->renderer_state;
101}
102
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100103static inline struct gles2_surface_state *
104get_surface_state(struct weston_surface *surface)
105{
106 return (struct gles2_surface_state *)surface->renderer_state;
107}
108
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100109static inline struct gles2_renderer *
110get_renderer(struct weston_compositor *ec)
111{
112 return (struct gles2_renderer *)ec->renderer;
113}
114
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400115static const char *
116egl_error_string(EGLint code)
117{
118#define MYERRCODE(x) case x: return #x;
119 switch (code) {
120 MYERRCODE(EGL_SUCCESS)
121 MYERRCODE(EGL_NOT_INITIALIZED)
122 MYERRCODE(EGL_BAD_ACCESS)
123 MYERRCODE(EGL_BAD_ALLOC)
124 MYERRCODE(EGL_BAD_ATTRIBUTE)
125 MYERRCODE(EGL_BAD_CONTEXT)
126 MYERRCODE(EGL_BAD_CONFIG)
127 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
128 MYERRCODE(EGL_BAD_DISPLAY)
129 MYERRCODE(EGL_BAD_SURFACE)
130 MYERRCODE(EGL_BAD_MATCH)
131 MYERRCODE(EGL_BAD_PARAMETER)
132 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
133 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
134 MYERRCODE(EGL_CONTEXT_LOST)
135 default:
136 return "unknown";
137 }
138#undef MYERRCODE
139}
140
141static void
142print_egl_error_state(void)
143{
144 EGLint code;
145
146 code = eglGetError();
147 weston_log("EGL error state: %s (0x%04lx)\n",
148 egl_error_string(code), (long)code);
149}
150
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300151struct polygon8 {
152 GLfloat x[8];
153 GLfloat y[8];
154 int n;
155};
156
157struct clip_context {
158 struct {
159 GLfloat x;
160 GLfloat y;
161 } prev;
162
163 struct {
164 GLfloat x1, y1;
165 GLfloat x2, y2;
166 } clip;
167
168 struct {
169 GLfloat *x;
170 GLfloat *y;
171 } vertices;
172};
173
174static GLfloat
175float_difference(GLfloat a, GLfloat b)
176{
177 /* http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/ */
178 static const GLfloat max_diff = 4.0f * FLT_MIN;
179 static const GLfloat max_rel_diff = 4.0e-5;
180 GLfloat diff = a - b;
181 GLfloat adiff = fabsf(diff);
182
183 if (adiff <= max_diff)
184 return 0.0f;
185
186 a = fabsf(a);
187 b = fabsf(b);
188 if (adiff <= (a > b ? a : b) * max_rel_diff)
189 return 0.0f;
190
191 return diff;
192}
193
194/* A line segment (p1x, p1y)-(p2x, p2y) intersects the line x = x_arg.
195 * Compute the y coordinate of the intersection.
196 */
197static GLfloat
198clip_intersect_y(GLfloat p1x, GLfloat p1y, GLfloat p2x, GLfloat p2y,
199 GLfloat x_arg)
200{
201 GLfloat a;
202 GLfloat diff = float_difference(p1x, p2x);
203
204 /* Practically vertical line segment, yet the end points have already
205 * been determined to be on different sides of the line. Therefore
206 * the line segment is part of the line and intersects everywhere.
207 * Return the end point, so we use the whole line segment.
208 */
209 if (diff == 0.0f)
210 return p2y;
211
212 a = (x_arg - p2x) / diff;
213 return p2y + (p1y - p2y) * a;
214}
215
216/* A line segment (p1x, p1y)-(p2x, p2y) intersects the line y = y_arg.
217 * Compute the x coordinate of the intersection.
218 */
219static GLfloat
220clip_intersect_x(GLfloat p1x, GLfloat p1y, GLfloat p2x, GLfloat p2y,
221 GLfloat y_arg)
222{
223 GLfloat a;
224 GLfloat diff = float_difference(p1y, p2y);
225
226 /* Practically horizontal line segment, yet the end points have already
227 * been determined to be on different sides of the line. Therefore
228 * the line segment is part of the line and intersects everywhere.
229 * Return the end point, so we use the whole line segment.
230 */
231 if (diff == 0.0f)
232 return p2x;
233
234 a = (y_arg - p2y) / diff;
235 return p2x + (p1x - p2x) * a;
236}
237
238enum path_transition {
239 PATH_TRANSITION_OUT_TO_OUT = 0,
240 PATH_TRANSITION_OUT_TO_IN = 1,
241 PATH_TRANSITION_IN_TO_OUT = 2,
242 PATH_TRANSITION_IN_TO_IN = 3,
243};
244
245static void
246clip_append_vertex(struct clip_context *ctx, GLfloat x, GLfloat y)
247{
248 *ctx->vertices.x++ = x;
249 *ctx->vertices.y++ = y;
250}
251
252static enum path_transition
253path_transition_left_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
254{
255 return ((ctx->prev.x >= ctx->clip.x1) << 1) | (x >= ctx->clip.x1);
256}
257
258static enum path_transition
259path_transition_right_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
260{
261 return ((ctx->prev.x < ctx->clip.x2) << 1) | (x < ctx->clip.x2);
262}
263
264static enum path_transition
265path_transition_top_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
266{
267 return ((ctx->prev.y >= ctx->clip.y1) << 1) | (y >= ctx->clip.y1);
268}
269
270static enum path_transition
271path_transition_bottom_edge(struct clip_context *ctx, GLfloat x, GLfloat y)
272{
273 return ((ctx->prev.y < ctx->clip.y2) << 1) | (y < ctx->clip.y2);
274}
275
276static void
277clip_polygon_leftright(struct clip_context *ctx,
278 enum path_transition transition,
279 GLfloat x, GLfloat y, GLfloat clip_x)
280{
281 GLfloat yi;
282
283 switch (transition) {
284 case PATH_TRANSITION_IN_TO_IN:
285 clip_append_vertex(ctx, x, y);
286 break;
287 case PATH_TRANSITION_IN_TO_OUT:
288 yi = clip_intersect_y(ctx->prev.x, ctx->prev.y, x, y, clip_x);
289 clip_append_vertex(ctx, clip_x, yi);
290 break;
291 case PATH_TRANSITION_OUT_TO_IN:
292 yi = clip_intersect_y(ctx->prev.x, ctx->prev.y, x, y, clip_x);
293 clip_append_vertex(ctx, clip_x, yi);
294 clip_append_vertex(ctx, x, y);
295 break;
296 case PATH_TRANSITION_OUT_TO_OUT:
297 /* nothing */
298 break;
299 default:
300 assert(0 && "bad enum path_transition");
301 }
302
303 ctx->prev.x = x;
304 ctx->prev.y = y;
305}
306
307static void
308clip_polygon_topbottom(struct clip_context *ctx,
309 enum path_transition transition,
310 GLfloat x, GLfloat y, GLfloat clip_y)
311{
312 GLfloat xi;
313
314 switch (transition) {
315 case PATH_TRANSITION_IN_TO_IN:
316 clip_append_vertex(ctx, x, y);
317 break;
318 case PATH_TRANSITION_IN_TO_OUT:
319 xi = clip_intersect_x(ctx->prev.x, ctx->prev.y, x, y, clip_y);
320 clip_append_vertex(ctx, xi, clip_y);
321 break;
322 case PATH_TRANSITION_OUT_TO_IN:
323 xi = clip_intersect_x(ctx->prev.x, ctx->prev.y, x, y, clip_y);
324 clip_append_vertex(ctx, xi, clip_y);
325 clip_append_vertex(ctx, x, y);
326 break;
327 case PATH_TRANSITION_OUT_TO_OUT:
328 /* nothing */
329 break;
330 default:
331 assert(0 && "bad enum path_transition");
332 }
333
334 ctx->prev.x = x;
335 ctx->prev.y = y;
336}
337
338static void
339clip_context_prepare(struct clip_context *ctx, const struct polygon8 *src,
340 GLfloat *dst_x, GLfloat *dst_y)
341{
342 ctx->prev.x = src->x[src->n - 1];
343 ctx->prev.y = src->y[src->n - 1];
344 ctx->vertices.x = dst_x;
345 ctx->vertices.y = dst_y;
346}
347
348static int
349clip_polygon_left(struct clip_context *ctx, const struct polygon8 *src,
350 GLfloat *dst_x, GLfloat *dst_y)
351{
352 enum path_transition trans;
353 int i;
354
355 clip_context_prepare(ctx, src, dst_x, dst_y);
356 for (i = 0; i < src->n; i++) {
357 trans = path_transition_left_edge(ctx, src->x[i], src->y[i]);
358 clip_polygon_leftright(ctx, trans, src->x[i], src->y[i],
359 ctx->clip.x1);
360 }
361 return ctx->vertices.x - dst_x;
362}
363
364static int
365clip_polygon_right(struct clip_context *ctx, const struct polygon8 *src,
366 GLfloat *dst_x, GLfloat *dst_y)
367{
368 enum path_transition trans;
369 int i;
370
371 clip_context_prepare(ctx, src, dst_x, dst_y);
372 for (i = 0; i < src->n; i++) {
373 trans = path_transition_right_edge(ctx, src->x[i], src->y[i]);
374 clip_polygon_leftright(ctx, trans, src->x[i], src->y[i],
375 ctx->clip.x2);
376 }
377 return ctx->vertices.x - dst_x;
378}
379
380static int
381clip_polygon_top(struct clip_context *ctx, const struct polygon8 *src,
382 GLfloat *dst_x, GLfloat *dst_y)
383{
384 enum path_transition trans;
385 int i;
386
387 clip_context_prepare(ctx, src, dst_x, dst_y);
388 for (i = 0; i < src->n; i++) {
389 trans = path_transition_top_edge(ctx, src->x[i], src->y[i]);
390 clip_polygon_topbottom(ctx, trans, src->x[i], src->y[i],
391 ctx->clip.y1);
392 }
393 return ctx->vertices.x - dst_x;
394}
395
396static int
397clip_polygon_bottom(struct clip_context *ctx, const struct polygon8 *src,
398 GLfloat *dst_x, GLfloat *dst_y)
399{
400 enum path_transition trans;
401 int i;
402
403 clip_context_prepare(ctx, src, dst_x, dst_y);
404 for (i = 0; i < src->n; i++) {
405 trans = path_transition_bottom_edge(ctx, src->x[i], src->y[i]);
406 clip_polygon_topbottom(ctx, trans, src->x[i], src->y[i],
407 ctx->clip.y2);
408 }
409 return ctx->vertices.x - dst_x;
410}
411
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400412#define max(a, b) (((a) > (b)) ? (a) : (b))
413#define min(a, b) (((a) > (b)) ? (b) : (a))
414#define clip(x, a, b) min(max(x, a), b)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400415
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300416/*
417 * Compute the boundary vertices of the intersection of the global coordinate
418 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
419 * 'surf_rect' when transformed from surface coordinates into global coordinates.
420 * The vertices are written to 'ex' and 'ey', and the return value is the
421 * number of vertices. Vertices are produced in clockwise winding order.
422 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
423 * polygon area.
424 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400425static int
426calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
427 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
428{
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300429 struct polygon8 polygon;
430 struct clip_context ctx;
431 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400432 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300433 struct polygon8 surf = {
434 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
435 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
436 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400437 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400438
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300439 ctx.clip.x1 = rect->x1;
440 ctx.clip.y1 = rect->y1;
441 ctx.clip.x2 = rect->x2;
442 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400443
444 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300445 for (i = 0; i < surf.n; i++)
446 weston_surface_to_global_float(es, surf.x[i], surf.y[i],
447 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400448
449 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300450 min_x = max_x = surf.x[0];
451 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400452
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300453 for (i = 1; i < surf.n; i++) {
454 min_x = min(min_x, surf.x[i]);
455 max_x = max(max_x, surf.x[i]);
456 min_y = min(min_y, surf.y[i]);
457 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400458 }
459
460 /* First, simple bounding box check to discard early transformed
461 * surface rects that do not intersect with the clip region:
462 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300463 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
464 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400465 return 0;
466
467 /* Simple case, bounding box edges are parallel to surface edges,
468 * there will be only four edges. We just need to clip the surface
469 * vertices to the clip rect bounds:
470 */
471 if (!es->transform.enabled) {
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300472 for (i = 0; i < surf.n; i++) {
473 ex[i] = clip(surf.x[i], ctx.clip.x1, ctx.clip.x2);
474 ey[i] = clip(surf.y[i], ctx.clip.y1, ctx.clip.y2);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400475 }
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300476 return surf.n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400477 }
478
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300479 /* Transformed case: use a general polygon clipping algorithm to
480 * clip the surface rectangle with each side of 'rect'.
481 * The algorithm is Sutherland-Hodgman, as explained in
482 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
483 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400484 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300485 polygon.n = clip_polygon_left(&ctx, &surf, polygon.x, polygon.y);
486 surf.n = clip_polygon_right(&ctx, &polygon, surf.x, surf.y);
487 polygon.n = clip_polygon_top(&ctx, &surf, polygon.x, polygon.y);
488 surf.n = clip_polygon_bottom(&ctx, &polygon, surf.x, surf.y);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400489
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300490 /* Get rid of duplicate vertices */
491 ex[0] = surf.x[0];
492 ey[0] = surf.y[0];
493 n = 1;
494 for (i = 1; i < surf.n; i++) {
495 if (float_difference(ex[n - 1], surf.x[i]) == 0.0f &&
496 float_difference(ey[n - 1], surf.y[i]) == 0.0f)
497 continue;
498 ex[n] = surf.x[i];
499 ey[n] = surf.y[i];
500 n++;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400501 }
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300502 if (float_difference(ex[n - 1], surf.x[0]) == 0.0f &&
503 float_difference(ey[n - 1], surf.y[0]) == 0.0f)
504 n--;
505
506 if (n < 3)
507 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400508
509 return n;
510}
511
512static int
513texture_region(struct weston_surface *es, pixman_region32_t *region,
514 pixman_region32_t *surf_region)
515{
516 struct weston_compositor *ec = es->compositor;
517 GLfloat *v, inv_width, inv_height;
518 unsigned int *vtxcnt, nvtx = 0;
519 pixman_box32_t *rects, *surf_rects;
520 int i, j, k, nrects, nsurf;
521
522 rects = pixman_region32_rectangles(region, &nrects);
523 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
524
525 /* worst case we can have 8 vertices per rect (ie. clipped into
526 * an octagon):
527 */
528 v = wl_array_add(&ec->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
529 vtxcnt = wl_array_add(&ec->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
530
531 inv_width = 1.0 / es->pitch;
532 inv_height = 1.0 / es->geometry.height;
533
534 for (i = 0; i < nrects; i++) {
535 pixman_box32_t *rect = &rects[i];
536 for (j = 0; j < nsurf; j++) {
537 pixman_box32_t *surf_rect = &surf_rects[j];
538 GLfloat sx, sy;
539 GLfloat ex[8], ey[8]; /* edge points in screen space */
540 int n;
541
542 /* The transformed surface, after clipping to the clip region,
543 * can have as many as eight sides, emitted as a triangle-fan.
544 * The first vertex in the triangle fan can be chosen arbitrarily,
545 * since the area is guaranteed to be convex.
546 *
547 * If a corner of the transformed surface falls outside of the
548 * clip region, instead of emitting one vertex for the corner
549 * of the surface, up to two are emitted for two corresponding
550 * intersection point(s) between the surface and the clip region.
551 *
552 * To do this, we first calculate the (up to eight) points that
553 * form the intersection of the clip rect and the transformed
554 * surface.
555 */
556 n = calculate_edges(es, rect, surf_rect, ex, ey);
557 if (n < 3)
558 continue;
559
560 /* emit edge points: */
561 for (k = 0; k < n; k++) {
562 weston_surface_from_global_float(es, ex[k], ey[k], &sx, &sy);
563 /* position: */
564 *(v++) = ex[k];
565 *(v++) = ey[k];
566 /* texcoord: */
567 *(v++) = sx * inv_width;
568 *(v++) = sy * inv_height;
569 }
570
571 vtxcnt[nvtx++] = n;
572 }
573 }
574
575 return nvtx;
576}
577
578static void
579triangle_fan_debug(struct weston_surface *surface, int first, int count)
580{
581 struct weston_compositor *compositor = surface->compositor;
John Kåre Alsaker40684142012-11-13 19:10:25 +0100582 struct gles2_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400583 int i;
584 GLushort *buffer;
585 GLushort *index;
586 int nelems;
587 static int color_idx = 0;
588 static const GLfloat color[][4] = {
589 { 1.0, 0.0, 0.0, 1.0 },
590 { 0.0, 1.0, 0.0, 1.0 },
591 { 0.0, 0.0, 1.0, 1.0 },
592 { 1.0, 1.0, 1.0, 1.0 },
593 };
594
595 nelems = (count - 1 + count - 2) * 2;
596
597 buffer = malloc(sizeof(GLushort) * nelems);
598 index = buffer;
599
600 for (i = 1; i < count; i++) {
601 *index++ = first;
602 *index++ = first + i;
603 }
604
605 for (i = 2; i < count; i++) {
606 *index++ = first + i - 1;
607 *index++ = first + i;
608 }
609
John Kåre Alsaker40684142012-11-13 19:10:25 +0100610 glUseProgram(gr->solid_shader.program);
611 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400612 color[color_idx++ % ARRAY_LENGTH(color)]);
613 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100614 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400615 free(buffer);
616}
617
618static void
619repaint_region(struct weston_surface *es, pixman_region32_t *region,
620 pixman_region32_t *surf_region)
621{
622 struct weston_compositor *ec = es->compositor;
623 GLfloat *v;
624 unsigned int *vtxcnt;
625 int i, first, nfans;
626
627 /* The final region to be painted is the intersection of
628 * 'region' and 'surf_region'. However, 'region' is in the global
629 * coordinates, and 'surf_region' is in the surface-local
630 * coordinates. texture_region() will iterate over all pairs of
631 * rectangles from both regions, compute the intersection
632 * polygon for each pair, and store it as a triangle fan if
633 * it has a non-zero area (at least 3 vertices, actually).
634 */
635 nfans = texture_region(es, region, surf_region);
636
637 v = ec->vertices.data;
638 vtxcnt = ec->vtxcnt.data;
639
640 /* position: */
641 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
642 glEnableVertexAttribArray(0);
643
644 /* texcoord: */
645 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
646 glEnableVertexAttribArray(1);
647
648 for (i = 0, first = 0; i < nfans; i++) {
649 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
650 if (ec->fan_debug)
651 triangle_fan_debug(es, first, vtxcnt[i]);
652 first += vtxcnt[i];
653 }
654
655 glDisableVertexAttribArray(1);
656 glDisableVertexAttribArray(0);
657
658 ec->vertices.size = 0;
659 ec->vtxcnt.size = 0;
660}
661
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100662static int
663use_output(struct weston_output *output)
664{
665 static int errored;
666 struct gles2_output_state *go = get_output_state(output);
667 struct gles2_renderer *gr = get_renderer(output->compositor);
668 EGLBoolean ret;
669
670 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
671 go->egl_surface, gr->egl_context);
672
673 if (ret == EGL_FALSE) {
674 if (errored)
675 return -1;
676 errored = 1;
677 weston_log("Failed to make EGL context current.\n");
678 print_egl_error_state();
679 return -1;
680 }
681
682 return 0;
683}
684
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400685static void
John Kåre Alsaker40684142012-11-13 19:10:25 +0100686use_shader(struct gles2_renderer *gr,
687 struct gles2_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400688{
John Kåre Alsaker40684142012-11-13 19:10:25 +0100689 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400690 return;
691
692 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100693 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400694}
695
696static void
John Kåre Alsaker40684142012-11-13 19:10:25 +0100697shader_uniforms(struct gles2_shader *shader,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400698 struct weston_surface *surface,
699 struct weston_output *output)
700{
701 int i;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100702 struct gles2_surface_state *gs = get_surface_state(surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400703
704 glUniformMatrix4fv(shader->proj_uniform,
705 1, GL_FALSE, output->matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100706 glUniform4fv(shader->color_uniform, 1, gs->color);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400707 glUniform1f(shader->alpha_uniform, surface->alpha);
708
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100709 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400710 glUniform1i(shader->tex_uniforms[i], i);
711}
712
713static void
714draw_surface(struct weston_surface *es, struct weston_output *output,
715 pixman_region32_t *damage) /* in global coordinates */
716{
717 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker40684142012-11-13 19:10:25 +0100718 struct gles2_renderer *gr = get_renderer(ec);
719 struct gles2_surface_state *gs = get_surface_state(es);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400720 /* repaint bounding region in global coordinates: */
721 pixman_region32_t repaint;
722 /* non-opaque region in surface coordinates: */
723 pixman_region32_t surface_blend;
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300724 pixman_region32_t *buffer_damage;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400725 GLint filter;
726 int i;
727
728 pixman_region32_init(&repaint);
729 pixman_region32_intersect(&repaint,
730 &es->transform.boundingbox, damage);
731 pixman_region32_subtract(&repaint, &repaint, &es->clip);
732
733 if (!pixman_region32_not_empty(&repaint))
734 goto out;
735
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300736 buffer_damage = &output->buffer_damage[output->current_buffer];
737 pixman_region32_subtract(buffer_damage, buffer_damage, &repaint);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400738
739 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
740
741 if (ec->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100742 use_shader(gr, &gr->solid_shader);
743 shader_uniforms(&gr->solid_shader, es, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400744 }
745
John Kåre Alsaker40684142012-11-13 19:10:25 +0100746 use_shader(gr, gs->shader);
747 shader_uniforms(gs->shader, es, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400748
749 if (es->transform.enabled || output->zoom.active)
750 filter = GL_LINEAR;
751 else
752 filter = GL_NEAREST;
753
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100754 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400755 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100756 glBindTexture(gs->target, gs->textures[i]);
757 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
758 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400759 }
760
761 /* blended region is whole surface minus opaque region: */
762 pixman_region32_init_rect(&surface_blend, 0, 0,
763 es->geometry.width, es->geometry.height);
764 pixman_region32_subtract(&surface_blend, &surface_blend, &es->opaque);
765
766 if (pixman_region32_not_empty(&es->opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100767 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400768 /* Special case for RGBA textures with possibly
769 * bad data in alpha channel: use the shader
770 * that forces texture alpha = 1.0.
771 * Xwayland surfaces need this.
772 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100773 use_shader(gr, &gr->texture_shader_rgbx);
774 shader_uniforms(&gr->texture_shader_rgbx, es, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400775 }
776
777 if (es->alpha < 1.0)
778 glEnable(GL_BLEND);
779 else
780 glDisable(GL_BLEND);
781
782 repaint_region(es, &repaint, &es->opaque);
783 }
784
785 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100786 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400787 glEnable(GL_BLEND);
788 repaint_region(es, &repaint, &surface_blend);
789 }
790
791 pixman_region32_fini(&surface_blend);
792
793out:
794 pixman_region32_fini(&repaint);
795}
796
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400797static void
798repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
799{
800 struct weston_compositor *compositor = output->compositor;
801 struct weston_surface *surface;
802
803 wl_list_for_each_reverse(surface, &compositor->surface_list, link)
804 if (surface->plane == &compositor->primary_plane)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400805 draw_surface(surface, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400806}
807
John Kåre Alsaker44154502012-11-13 19:10:20 +0100808
809static int
810texture_border(struct weston_output *output)
811{
812 struct weston_compositor *ec = output->compositor;
813 struct gles2_renderer *gr = get_renderer(ec);
814 GLfloat *d;
815 unsigned int *p;
816 int i, j, k, n;
817 GLfloat x[4], y[4], u[4], v[4];
818
819 x[0] = -gr->border.left;
820 x[1] = 0;
821 x[2] = output->current->width;
822 x[3] = output->current->width + gr->border.right;
823
824 y[0] = -gr->border.top;
825 y[1] = 0;
826 y[2] = output->current->height;
827 y[3] = output->current->height + gr->border.bottom;
828
829 u[0] = 0.0;
830 u[1] = (GLfloat) gr->border.left / gr->border.width;
831 u[2] = (GLfloat) (gr->border.width - gr->border.right) / gr->border.width;
832 u[3] = 1.0;
833
834 v[0] = 0.0;
835 v[1] = (GLfloat) gr->border.top / gr->border.height;
836 v[2] = (GLfloat) (gr->border.height - gr->border.bottom) / gr->border.height;
837 v[3] = 1.0;
838
839 n = 8;
840 d = wl_array_add(&ec->vertices, n * 16 * sizeof *d);
841 p = wl_array_add(&ec->indices, n * 6 * sizeof *p);
842
843 k = 0;
844 for (i = 0; i < 3; i++)
845 for (j = 0; j < 3; j++) {
846
847 if (i == 1 && j == 1)
848 continue;
849
850 d[ 0] = x[i];
851 d[ 1] = y[j];
852 d[ 2] = u[i];
853 d[ 3] = v[j];
854
855 d[ 4] = x[i];
856 d[ 5] = y[j + 1];
857 d[ 6] = u[i];
858 d[ 7] = v[j + 1];
859
860 d[ 8] = x[i + 1];
861 d[ 9] = y[j];
862 d[10] = u[i + 1];
863 d[11] = v[j];
864
865 d[12] = x[i + 1];
866 d[13] = y[j + 1];
867 d[14] = u[i + 1];
868 d[15] = v[j + 1];
869
870 p[0] = k + 0;
871 p[1] = k + 1;
872 p[2] = k + 2;
873 p[3] = k + 2;
874 p[4] = k + 1;
875 p[5] = k + 3;
876
877 d += 16;
878 p += 6;
879 k += 4;
880 }
881
882 return k / 4;
883}
884
885static void
886draw_border(struct weston_output *output)
887{
888 struct weston_compositor *ec = output->compositor;
889 struct gles2_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100890 struct gles2_shader *shader = &gr->texture_shader_rgba;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100891 GLfloat *v;
892 int n;
893
894 glDisable(GL_BLEND);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100895 use_shader(gr, shader);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100896
897 glUniformMatrix4fv(shader->proj_uniform,
898 1, GL_FALSE, output->matrix.d);
899
900 glUniform1i(shader->tex_uniforms[0], 0);
901 glUniform1f(shader->alpha_uniform, 1);
902
903 n = texture_border(output);
904
905 glActiveTexture(GL_TEXTURE0);
906 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
907
908 v = ec->vertices.data;
909 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
910 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
911 glEnableVertexAttribArray(0);
912 glEnableVertexAttribArray(1);
913
914 glDrawElements(GL_TRIANGLES, n * 6,
915 GL_UNSIGNED_INT, ec->indices.data);
916
917 glDisableVertexAttribArray(1);
918 glDisableVertexAttribArray(0);
919
920 ec->vertices.size = 0;
921 ec->indices.size = 0;
922}
923
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400924static void
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400925gles2_renderer_repaint_output(struct weston_output *output,
926 pixman_region32_t *output_damage)
927{
John Kåre Alsaker94659272012-11-13 19:10:18 +0100928 struct gles2_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400929 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100930 struct gles2_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400931 EGLBoolean ret;
932 static int errored;
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300933 int32_t width, height, i;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400934
935 width = output->current->width +
936 output->border.left + output->border.right;
937 height = output->current->height +
938 output->border.top + output->border.bottom;
939
940 glViewport(0, 0, width, height);
941
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100942 if (use_output(output) < 0)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400943 return;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400944
945 /* if debugging, redraw everything outside the damage to clean up
946 * debug lines from the previous draw on this buffer:
947 */
948 if (compositor->fan_debug) {
949 pixman_region32_t undamaged;
950 pixman_region32_init(&undamaged);
951 pixman_region32_subtract(&undamaged, &output->region,
952 output_damage);
953 compositor->fan_debug = 0;
954 repaint_surfaces(output, &undamaged);
955 compositor->fan_debug = 1;
956 pixman_region32_fini(&undamaged);
957 }
958
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300959 for (i = 0; i < 2; i++)
960 pixman_region32_union(&output->buffer_damage[i],
961 &output->buffer_damage[i],
962 output_damage);
963
964 pixman_region32_union(output_damage, output_damage,
965 &output->buffer_damage[output->current_buffer]);
966
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400967 repaint_surfaces(output, output_damage);
968
John Kåre Alsaker44154502012-11-13 19:10:20 +0100969 if (gr->border.texture)
970 draw_border(output);
971
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400972 wl_signal_emit(&output->frame_signal, output);
973
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100974 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400975 if (ret == EGL_FALSE && !errored) {
976 errored = 1;
977 weston_log("Failed in eglSwapBuffers.\n");
978 print_egl_error_state();
979 }
980
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300981 output->current_buffer ^= 1;
982
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400983}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -0400984
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100985static int
986gles2_renderer_read_pixels(struct weston_output *output,
987 pixman_format_code_t format, void *pixels,
988 uint32_t x, uint32_t y,
989 uint32_t width, uint32_t height)
990{
991 GLenum gl_format;
992
993 switch (format) {
994 case PIXMAN_a8r8g8b8:
995 gl_format = GL_BGRA_EXT;
996 break;
997 case PIXMAN_a8b8g8r8:
998 gl_format = GL_RGBA;
999 break;
1000 default:
1001 return -1;
1002 }
1003
1004 if (use_output(output) < 0)
1005 return -1;
1006
1007 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1008 glReadPixels(x, y, width, height, gl_format,
1009 GL_UNSIGNED_BYTE, pixels);
1010
1011 return 0;
1012}
1013
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001014static void
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001015gles2_renderer_flush_damage(struct weston_surface *surface)
1016{
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001017 struct gles2_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001018 struct gles2_surface_state *gs = get_surface_state(surface);
1019
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001020#ifdef GL_UNPACK_ROW_LENGTH
1021 pixman_box32_t *rectangles;
1022 void *data;
1023 int i, n;
1024#endif
1025
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001026 pixman_region32_union(&surface->texture_damage,
1027 &surface->texture_damage, &surface->damage);
1028
1029 /* Avoid upload, if the texture won't be used this time.
1030 * We still accumulate the damage in texture_damage.
1031 */
1032 if (surface->plane != &surface->compositor->primary_plane)
1033 return;
1034
1035 if (!pixman_region32_not_empty(&surface->texture_damage))
1036 return;
1037
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001038 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001039
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001040 if (!gr->has_unpack_subimage) {
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001041 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1042 surface->pitch, surface->buffer->height, 0,
1043 GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1044 wl_shm_buffer_get_data(surface->buffer));
1045
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001046 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001047 }
1048
1049#ifdef GL_UNPACK_ROW_LENGTH
1050 /* Mesa does not define GL_EXT_unpack_subimage */
1051 glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->pitch);
1052 data = wl_shm_buffer_get_data(surface->buffer);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001053 rectangles = pixman_region32_rectangles(&surface->texture_damage, &n);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001054 for (i = 0; i < n; i++) {
1055 glPixelStorei(GL_UNPACK_SKIP_PIXELS, rectangles[i].x1);
1056 glPixelStorei(GL_UNPACK_SKIP_ROWS, rectangles[i].y1);
1057 glTexSubImage2D(GL_TEXTURE_2D, 0,
1058 rectangles[i].x1, rectangles[i].y1,
1059 rectangles[i].x2 - rectangles[i].x1,
1060 rectangles[i].y2 - rectangles[i].y1,
1061 GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
1062 }
1063#endif
Pekka Paalanenbcdd5792012-11-07 12:25:13 +02001064
1065done:
1066 pixman_region32_fini(&surface->texture_damage);
1067 pixman_region32_init(&surface->texture_damage);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -04001068}
1069
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001070static void
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001071ensure_textures(struct gles2_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001072{
1073 int i;
1074
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001075 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001076 return;
1077
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001078 for (i = gs->num_textures; i < num_textures; i++) {
1079 glGenTextures(1, &gs->textures[i]);
1080 glBindTexture(gs->target, gs->textures[i]);
1081 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001082 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001083 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001084 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1085 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001086 gs->num_textures = num_textures;
1087 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001088}
1089
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001090static void
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001091gles2_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
1092{
1093 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001094 struct gles2_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01001095 struct gles2_surface_state *gs = get_surface_state(es);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001096 EGLint attribs[3], format;
1097 int i, num_planes;
1098
1099 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001100 for (i = 0; i < gs->num_images; i++) {
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001101 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001102 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001103 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001104 gs->num_images = 0;
1105 glDeleteTextures(gs->num_textures, gs->textures);
1106 gs->num_textures = 0;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001107 return;
1108 }
1109
1110 if (wl_buffer_is_shm(buffer)) {
1111 es->pitch = wl_shm_buffer_get_stride(buffer) / 4;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001112 gs->target = GL_TEXTURE_2D;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001113
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001114 ensure_textures(gs, 1);
1115 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001116 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1117 es->pitch, buffer->height, 0,
1118 GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1119 if (wl_shm_buffer_get_format(buffer) == WL_SHM_FORMAT_XRGB8888)
John Kåre Alsaker40684142012-11-13 19:10:25 +01001120 gs->shader = &gr->texture_shader_rgbx;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001121 else
John Kåre Alsaker40684142012-11-13 19:10:25 +01001122 gs->shader = &gr->texture_shader_rgba;
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001123 } else if (gr->query_buffer(gr->egl_display, buffer,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001124 EGL_TEXTURE_FORMAT, &format)) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001125 for (i = 0; i < gs->num_images; i++)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001126 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001127 gs->num_images = 0;
1128 gs->target = GL_TEXTURE_2D;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001129 switch (format) {
1130 case EGL_TEXTURE_RGB:
1131 case EGL_TEXTURE_RGBA:
1132 default:
1133 num_planes = 1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001134 gs->shader = &gr->texture_shader_rgba;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001135 break;
1136 case EGL_TEXTURE_EXTERNAL_WL:
1137 num_planes = 1;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001138 gs->target = GL_TEXTURE_EXTERNAL_OES;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001139 gs->shader = &gr->texture_shader_egl_external;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001140 break;
1141 case EGL_TEXTURE_Y_UV_WL:
1142 num_planes = 2;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001143 gs->shader = &gr->texture_shader_y_uv;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001144 break;
1145 case EGL_TEXTURE_Y_U_V_WL:
1146 num_planes = 3;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001147 gs->shader = &gr->texture_shader_y_u_v;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001148 break;
1149 case EGL_TEXTURE_Y_XUXV_WL:
1150 num_planes = 2;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001151 gs->shader = &gr->texture_shader_y_xuxv;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001152 break;
1153 }
1154
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001155 ensure_textures(gs, num_planes);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001156 for (i = 0; i < num_planes; i++) {
1157 attribs[0] = EGL_WAYLAND_PLANE_WL;
1158 attribs[1] = i;
1159 attribs[2] = EGL_NONE;
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001160 gs->images[i] = gr->create_image(gr->egl_display,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001161 NULL,
1162 EGL_WAYLAND_BUFFER_WL,
1163 buffer, attribs);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001164 if (!gs->images[i]) {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001165 weston_log("failed to create img for plane %d\n", i);
1166 continue;
1167 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001168 gs->num_images++;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001169
1170 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001171 glBindTexture(gs->target, gs->textures[i]);
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001172 gr->image_target_texture_2d(gs->target,
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001173 gs->images[i]);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001174 }
1175
1176 es->pitch = buffer->width;
1177 } else {
1178 weston_log("unhandled buffer type!\n");
1179 }
1180}
1181
Kristian Høgsberg42263852012-09-06 21:59:29 -04001182static void
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001183gles2_renderer_surface_set_color(struct weston_surface *surface,
1184 float red, float green, float blue, float alpha)
1185{
1186 struct gles2_surface_state *gs = get_surface_state(surface);
John Kåre Alsaker40684142012-11-13 19:10:25 +01001187 struct gles2_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001188
1189 gs->color[0] = red;
1190 gs->color[1] = green;
1191 gs->color[2] = blue;
1192 gs->color[3] = alpha;
1193
John Kåre Alsaker40684142012-11-13 19:10:25 +01001194 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001195}
1196
1197static int
1198gles2_renderer_create_surface(struct weston_surface *surface)
1199{
1200 struct gles2_surface_state *gs;
1201
1202 gs = calloc(1, sizeof *gs);
1203
1204 if (!gs)
1205 return -1;
1206
1207 surface->renderer_state = gs;
1208
1209 return 0;
1210}
1211
1212static void
Kristian Høgsberg42263852012-09-06 21:59:29 -04001213gles2_renderer_destroy_surface(struct weston_surface *surface)
1214{
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001215 struct gles2_surface_state *gs = get_surface_state(surface);
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001216 struct gles2_renderer *gr = get_renderer(surface->compositor);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001217 int i;
1218
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001219 glDeleteTextures(gs->num_textures, gs->textures);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001220
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001221 for (i = 0; i < gs->num_images; i++)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001222 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001223
1224 free(gs);
Kristian Høgsberg42263852012-09-06 21:59:29 -04001225}
1226
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001227static const char vertex_shader[] =
1228 "uniform mat4 proj;\n"
1229 "attribute vec2 position;\n"
1230 "attribute vec2 texcoord;\n"
1231 "varying vec2 v_texcoord;\n"
1232 "void main()\n"
1233 "{\n"
1234 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1235 " v_texcoord = texcoord;\n"
1236 "}\n";
1237
1238/* Declare common fragment shader uniforms */
1239#define FRAGMENT_CONVERT_YUV \
1240 " y *= alpha;\n" \
1241 " u *= alpha;\n" \
1242 " v *= alpha;\n" \
1243 " gl_FragColor.r = y + 1.59602678 * v;\n" \
1244 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
1245 " gl_FragColor.b = y + 2.01723214 * u;\n" \
1246 " gl_FragColor.a = alpha;\n"
1247
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001248static const char fragment_debug[] =
1249 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
1250
1251static const char fragment_brace[] =
1252 "}\n";
1253
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001254static const char texture_fragment_shader_rgba[] =
1255 "precision mediump float;\n"
1256 "varying vec2 v_texcoord;\n"
1257 "uniform sampler2D tex;\n"
1258 "uniform float alpha;\n"
1259 "void main()\n"
1260 "{\n"
1261 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001262 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001263
1264static const char texture_fragment_shader_rgbx[] =
1265 "precision mediump float;\n"
1266 "varying vec2 v_texcoord;\n"
1267 "uniform sampler2D tex;\n"
1268 "uniform float alpha;\n"
1269 "void main()\n"
1270 "{\n"
1271 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
1272 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001273 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001274
1275static const char texture_fragment_shader_egl_external[] =
1276 "#extension GL_OES_EGL_image_external : require\n"
1277 "precision mediump float;\n"
1278 "varying vec2 v_texcoord;\n"
1279 "uniform samplerExternalOES tex;\n"
1280 "uniform float alpha;\n"
1281 "void main()\n"
1282 "{\n"
1283 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
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_uv[] =
1287 "precision mediump float;\n"
1288 "uniform sampler2D tex;\n"
1289 "uniform sampler2D tex1;\n"
1290 "varying vec2 v_texcoord;\n"
1291 "uniform float alpha;\n"
1292 "void main() {\n"
1293 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1294 " float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
1295 " float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
1296 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001297 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001298
1299static const char texture_fragment_shader_y_u_v[] =
1300 "precision mediump float;\n"
1301 "uniform sampler2D tex;\n"
1302 "uniform sampler2D tex1;\n"
1303 "uniform sampler2D tex2;\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).x - 0.5;\n"
1309 " float v = texture2D(tex2, v_texcoord).x - 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 texture_fragment_shader_y_xuxv[] =
1314 "precision mediump float;\n"
1315 "uniform sampler2D tex;\n"
1316 "uniform sampler2D tex1;\n"
1317 "varying vec2 v_texcoord;\n"
1318 "uniform float alpha;\n"
1319 "void main() {\n"
1320 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1321 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
1322 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
1323 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001324 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001325
1326static const char solid_fragment_shader[] =
1327 "precision mediump float;\n"
1328 "uniform vec4 color;\n"
1329 "uniform float alpha;\n"
1330 "void main()\n"
1331 "{\n"
1332 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001333 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001334
1335static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001336compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001337{
1338 GLuint s;
1339 char msg[512];
1340 GLint status;
1341
1342 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001343 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001344 glCompileShader(s);
1345 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1346 if (!status) {
1347 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1348 weston_log("shader info: %s\n", msg);
1349 return GL_NONE;
1350 }
1351
1352 return s;
1353}
1354
1355static int
John Kåre Alsaker40684142012-11-13 19:10:25 +01001356shader_init(struct gles2_shader *shader, struct weston_compositor *ec,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001357 const char *vertex_source, const char *fragment_source)
1358{
1359 char msg[512];
1360 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001361 int count;
1362 const char *sources[3];
1363 struct gles2_renderer *renderer =
1364 (struct gles2_renderer *) ec->renderer;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001365
1366 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001367 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
1368
1369 if (renderer->fragment_shader_debug) {
1370 sources[0] = fragment_source;
1371 sources[1] = fragment_debug;
1372 sources[2] = fragment_brace;
1373 count = 3;
1374 } else {
1375 sources[0] = fragment_source;
1376 sources[1] = fragment_brace;
1377 count = 2;
1378 }
1379
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001380 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001381 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001382
1383 shader->program = glCreateProgram();
1384 glAttachShader(shader->program, shader->vertex_shader);
1385 glAttachShader(shader->program, shader->fragment_shader);
1386 glBindAttribLocation(shader->program, 0, "position");
1387 glBindAttribLocation(shader->program, 1, "texcoord");
1388
1389 glLinkProgram(shader->program);
1390 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1391 if (!status) {
1392 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1393 weston_log("link info: %s\n", msg);
1394 return -1;
1395 }
1396
1397 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1398 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
1399 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
1400 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
1401 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
1402 shader->color_uniform = glGetUniformLocation(shader->program, "color");
1403
1404 return 0;
1405}
1406
1407static void
John Kåre Alsaker40684142012-11-13 19:10:25 +01001408shader_release(struct gles2_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001409{
1410 glDeleteShader(shader->vertex_shader);
1411 glDeleteShader(shader->fragment_shader);
1412 glDeleteProgram(shader->program);
1413
1414 shader->vertex_shader = 0;
1415 shader->fragment_shader = 0;
1416 shader->program = 0;
1417}
1418
1419static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001420log_extensions(const char *name, const char *extensions)
1421{
1422 const char *p, *end;
1423 int l;
1424 int len;
1425
1426 l = weston_log("%s:", name);
1427 p = extensions;
1428 while (*p) {
1429 end = strchrnul(p, ' ');
1430 len = end - p;
1431 if (l + len > 78)
1432 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
1433 len, p);
1434 else
1435 l += weston_log_continue(" %.*s", len, p);
1436 for (p = end; isspace(*p); p++)
1437 ;
1438 }
1439 weston_log_continue("\n");
1440}
1441
1442static void
1443log_egl_gl_info(EGLDisplay egldpy)
1444{
1445 const char *str;
1446
1447 str = eglQueryString(egldpy, EGL_VERSION);
1448 weston_log("EGL version: %s\n", str ? str : "(null)");
1449
1450 str = eglQueryString(egldpy, EGL_VENDOR);
1451 weston_log("EGL vendor: %s\n", str ? str : "(null)");
1452
1453 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
1454 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
1455
1456 str = eglQueryString(egldpy, EGL_EXTENSIONS);
1457 log_extensions("EGL extensions", str ? str : "(null)");
1458
1459 str = (char *)glGetString(GL_VERSION);
1460 weston_log("GL version: %s\n", str ? str : "(null)");
1461
1462 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1463 weston_log("GLSL version: %s\n", str ? str : "(null)");
1464
1465 str = (char *)glGetString(GL_VENDOR);
1466 weston_log("GL vendor: %s\n", str ? str : "(null)");
1467
1468 str = (char *)glGetString(GL_RENDERER);
1469 weston_log("GL renderer: %s\n", str ? str : "(null)");
1470
1471 str = (char *)glGetString(GL_EXTENSIONS);
1472 log_extensions("GL extensions", str ? str : "(null)");
1473}
1474
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001475static void
1476log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
1477{
1478 EGLint r, g, b, a;
1479
1480 weston_log("Chosen EGL config details:\n");
1481
1482 weston_log_continue(STAMP_SPACE "RGBA bits");
1483 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
1484 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
1485 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
1486 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
1487 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
1488 else
1489 weston_log_continue(" unknown\n");
1490
1491 weston_log_continue(STAMP_SPACE "swap interval range");
1492 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
1493 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
1494 weston_log_continue(": %d - %d\n", a, b);
1495 else
1496 weston_log_continue(" unknown\n");
1497}
1498
John Kåre Alsaker44154502012-11-13 19:10:20 +01001499static void
1500output_apply_border(struct weston_output *output, struct gles2_renderer *gr)
1501{
1502 output->border.top = gr->border.top;
1503 output->border.bottom = gr->border.bottom;
1504 output->border.left = gr->border.left;
1505 output->border.right = gr->border.right;
1506}
1507
1508WL_EXPORT void
1509gles2_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t height, void *data,
1510 int32_t *edges)
1511{
1512 struct gles2_renderer *gr = get_renderer(ec);
1513 struct weston_output *output;
1514
1515 gr->border.left = edges[0];
1516 gr->border.right = edges[1];
1517 gr->border.top = edges[2];
1518 gr->border.bottom = edges[3];
1519
1520 gr->border.width = width;
1521 gr->border.height = height;
1522
1523 glGenTextures(1, &gr->border.texture);
1524 glBindTexture(GL_TEXTURE_2D, gr->border.texture);
1525 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1526 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1527 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1528 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1529
1530 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1531 width,
1532 height,
1533 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1534 data);
1535
1536 wl_list_for_each(output, &ec->output_list, link)
1537 output_apply_border(output, gr);
1538}
1539
John Kåre Alsaker94659272012-11-13 19:10:18 +01001540static int
1541gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
1542
1543WL_EXPORT int
1544gles2_renderer_output_create(struct weston_output *output,
1545 EGLNativeWindowType window)
1546{
1547 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001548 struct gles2_renderer *gr = get_renderer(ec);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001549 struct gles2_output_state *go = calloc(1, sizeof *go);
1550
1551 if (!go)
1552 return -1;
1553
1554 go->egl_surface =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001555 eglCreateWindowSurface(gr->egl_display,
1556 gr->egl_config,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001557 window, NULL);
1558
1559 if (go->egl_surface == EGL_NO_SURFACE) {
1560 weston_log("failed to create egl surface\n");
1561 free(go);
1562 return -1;
1563 }
1564
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001565 if (gr->egl_context == NULL)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001566 if (gles2_renderer_setup(ec, go->egl_surface) < 0) {
1567 free(go);
1568 return -1;
1569 }
1570
1571 output->renderer_state = go;
1572
John Kåre Alsaker44154502012-11-13 19:10:20 +01001573 output_apply_border(output, gr);
1574
John Kåre Alsaker94659272012-11-13 19:10:18 +01001575 return 0;
1576}
1577
1578WL_EXPORT void
1579gles2_renderer_output_destroy(struct weston_output *output)
1580{
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001581 struct gles2_renderer *gr = get_renderer(output->compositor);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001582 struct gles2_output_state *go = get_output_state(output);
1583
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001584 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001585
1586 free(go);
1587}
1588
1589WL_EXPORT EGLSurface
1590gles2_renderer_output_surface(struct weston_output *output)
1591{
1592 return get_output_state(output)->egl_surface;
1593}
1594
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001595WL_EXPORT void
1596gles2_renderer_destroy(struct weston_compositor *ec)
1597{
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001598 struct gles2_renderer *gr = get_renderer(ec);
1599
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001600 if (gr->has_bind_display)
1601 gr->unbind_display(gr->egl_display, ec->wl_display);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001602
1603 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
1604 eglMakeCurrent(gr->egl_display,
1605 EGL_NO_SURFACE, EGL_NO_SURFACE,
1606 EGL_NO_CONTEXT);
1607
1608 eglTerminate(gr->egl_display);
1609 eglReleaseThread();
1610}
1611
1612static int
1613egl_choose_config(struct gles2_renderer *gr, const EGLint *attribs,
1614 const EGLint *visual_id)
1615{
1616 EGLint count = 0;
1617 EGLint matched = 0;
1618 EGLConfig *configs;
1619 int i;
1620
1621 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
1622 return -1;
1623
1624 configs = calloc(count, sizeof *configs);
1625 if (!configs)
1626 return -1;
1627
1628 if (!eglChooseConfig(gr->egl_display, attribs, configs,
1629 count, &matched))
1630 goto out;
1631
1632 for (i = 0; i < matched; ++i) {
1633 EGLint id;
1634
1635 if (visual_id) {
1636 if (!eglGetConfigAttrib(gr->egl_display,
1637 configs[i], EGL_NATIVE_VISUAL_ID,
1638 &id))
1639 continue;
1640
1641 if (id != *visual_id)
1642 continue;
1643 }
1644
1645 gr->egl_config = configs[i];
1646
1647 free(configs);
1648 return 0;
1649 }
1650
1651out:
1652 free(configs);
1653 return -1;
1654}
1655
1656WL_EXPORT const EGLint gles2_renderer_opaque_attribs[] = {
1657 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1658 EGL_RED_SIZE, 1,
1659 EGL_GREEN_SIZE, 1,
1660 EGL_BLUE_SIZE, 1,
1661 EGL_ALPHA_SIZE, 0,
1662 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1663 EGL_NONE
1664};
1665
1666WL_EXPORT const EGLint gles2_renderer_alpha_attribs[] = {
1667 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1668 EGL_RED_SIZE, 1,
1669 EGL_GREEN_SIZE, 1,
1670 EGL_BLUE_SIZE, 1,
1671 EGL_ALPHA_SIZE, 1,
1672 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1673 EGL_NONE
1674};
1675
1676WL_EXPORT int
1677gles2_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
1678 const EGLint *attribs, const EGLint *visual_id)
1679{
1680 struct gles2_renderer *gr;
1681 EGLint major, minor;
1682
1683 gr = calloc(1, sizeof *gr);
1684
1685 if (gr == NULL)
1686 return -1;
1687
John Kåre Alsakera95b2d62012-11-13 19:10:21 +01001688 gr->base.read_pixels = gles2_renderer_read_pixels;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001689 gr->base.repaint_output = gles2_renderer_repaint_output;
1690 gr->base.flush_damage = gles2_renderer_flush_damage;
1691 gr->base.attach = gles2_renderer_attach;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001692 gr->base.create_surface = gles2_renderer_create_surface;
1693 gr->base.surface_set_color = gles2_renderer_surface_set_color;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001694 gr->base.destroy_surface = gles2_renderer_destroy_surface;
1695
1696 gr->egl_display = eglGetDisplay(display);
1697 if (gr->egl_display == EGL_NO_DISPLAY) {
1698 weston_log("failed to create display\n");
1699 goto err_egl;
1700 }
1701
1702 if (!eglInitialize(gr->egl_display, &major, &minor)) {
1703 weston_log("failed to initialize display\n");
1704 goto err_egl;
1705 }
1706
1707 if (egl_choose_config(gr, attribs, visual_id) < 0) {
1708 weston_log("failed to choose EGL config\n");
1709 goto err_egl;
1710 }
1711
1712 ec->renderer = &gr->base;
1713
1714 return 0;
1715
1716err_egl:
1717 print_egl_error_state();
1718 free(gr);
1719 return -1;
1720}
1721
1722WL_EXPORT EGLDisplay
1723gles2_renderer_display(struct weston_compositor *ec)
1724{
1725 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001726}
1727
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001728static int
1729compile_shaders(struct weston_compositor *ec)
1730{
John Kåre Alsaker40684142012-11-13 19:10:25 +01001731 struct gles2_renderer *gr = get_renderer(ec);
1732
1733 if (shader_init(&gr->texture_shader_rgba, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001734 vertex_shader, texture_fragment_shader_rgba) < 0)
1735 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001736 if (shader_init(&gr->texture_shader_rgbx, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001737 vertex_shader, texture_fragment_shader_rgbx) < 0)
1738 return -1;
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001739 if (gr->has_egl_image_external &&
John Kåre Alsaker40684142012-11-13 19:10:25 +01001740 shader_init(&gr->texture_shader_egl_external, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001741 vertex_shader, texture_fragment_shader_egl_external) < 0)
1742 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001743 if (shader_init(&gr->texture_shader_y_uv, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001744 vertex_shader, texture_fragment_shader_y_uv) < 0)
1745 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001746 if (shader_init(&gr->texture_shader_y_u_v, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001747 vertex_shader, texture_fragment_shader_y_u_v) < 0)
1748 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001749 if (shader_init(&gr->texture_shader_y_xuxv, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001750 vertex_shader, texture_fragment_shader_y_xuxv) < 0)
1751 return -1;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001752 if (shader_init(&gr->solid_shader, ec,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001753 vertex_shader, solid_fragment_shader) < 0)
1754 return -1;
1755
1756 return 0;
1757}
1758
1759static void
1760fragment_debug_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
1761 void *data)
1762{
1763 struct weston_compositor *ec = data;
John Kåre Alsaker40684142012-11-13 19:10:25 +01001764 struct gles2_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001765 struct weston_output *output;
1766
John Kåre Alsaker40684142012-11-13 19:10:25 +01001767 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001768
John Kåre Alsaker40684142012-11-13 19:10:25 +01001769 shader_release(&gr->texture_shader_rgba);
1770 shader_release(&gr->texture_shader_rgbx);
1771 shader_release(&gr->texture_shader_egl_external);
1772 shader_release(&gr->texture_shader_y_uv);
1773 shader_release(&gr->texture_shader_y_u_v);
1774 shader_release(&gr->texture_shader_y_xuxv);
1775 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001776
1777 compile_shaders(ec);
1778
1779 wl_list_for_each(output, &ec->output_list, link)
1780 weston_output_damage(output);
1781}
1782
John Kåre Alsaker94659272012-11-13 19:10:18 +01001783static int
1784gles2_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001785{
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001786 struct gles2_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001787 const char *extensions;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001788 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001789
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001790 static const EGLint context_attribs[] = {
1791 EGL_CONTEXT_CLIENT_VERSION, 2,
1792 EGL_NONE
1793 };
1794
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001795 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1796 weston_log("failed to bind EGL_OPENGL_ES_API\n");
1797 print_egl_error_state();
1798 return -1;
1799 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001800
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001801 log_egl_config_info(gr->egl_display, gr->egl_config);
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001802
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001803 gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001804 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001805 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001806 weston_log("failed to create context\n");
1807 print_egl_error_state();
1808 return -1;
1809 }
1810
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001811 ret = eglMakeCurrent(gr->egl_display, egl_surface,
1812 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001813 if (ret == EGL_FALSE) {
1814 weston_log("Failed to make EGL context current.\n");
1815 print_egl_error_state();
1816 return -1;
1817 }
1818
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001819 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001820
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001821 gr->image_target_texture_2d =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001822 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001823 gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1824 gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1825 gr->bind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001826 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001827 gr->unbind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001828 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001829 gr->query_buffer =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001830 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
1831
1832 extensions = (const char *) glGetString(GL_EXTENSIONS);
1833 if (!extensions) {
1834 weston_log("Retrieving GL extension string failed.\n");
1835 return -1;
1836 }
1837
1838 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
1839 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
1840 return -1;
1841 }
1842
1843 if (strstr(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001844 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001845 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001846 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001847
1848 if (strstr(extensions, "GL_EXT_unpack_subimage"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001849 gr->has_unpack_subimage = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001850
1851 if (strstr(extensions, "GL_OES_EGL_image_external"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001852 gr->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001853
1854 extensions =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001855 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001856 if (!extensions) {
1857 weston_log("Retrieving EGL extension string failed.\n");
1858 return -1;
1859 }
1860
1861 if (strstr(extensions, "EGL_WL_bind_wayland_display"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001862 gr->has_bind_display = 1;
1863 if (gr->has_bind_display) {
1864 ret = gr->bind_display(gr->egl_display, ec->wl_display);
Pekka Paalanen035a0322012-10-24 09:43:06 +03001865 if (!ret)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001866 gr->has_bind_display = 0;
Pekka Paalanen035a0322012-10-24 09:43:06 +03001867 }
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001868
1869 glActiveTexture(GL_TEXTURE0);
1870
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001871 if (compile_shaders(ec))
1872 return -1;
1873
1874 weston_compositor_add_debug_binding(ec, KEY_S,
1875 fragment_debug_binding, ec);
1876
Pekka Paalanen035a0322012-10-24 09:43:06 +03001877 weston_log("GL ES 2 renderer features:\n");
1878 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
1879 ec->read_format == GL_BGRA_EXT ? "BGRA" : "RGBA");
1880 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001881 gr->has_unpack_subimage ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001882 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001883 gr->has_bind_display ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001884
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001885
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001886 return 0;
1887}