2 * Copyright © 2012 Intel Corporation
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.
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.
25 #include "compositor.h"
28 egl_error_string(EGLint code)
30 #define MYERRCODE(x) case x: return #x;
32 MYERRCODE(EGL_SUCCESS)
33 MYERRCODE(EGL_NOT_INITIALIZED)
34 MYERRCODE(EGL_BAD_ACCESS)
35 MYERRCODE(EGL_BAD_ALLOC)
36 MYERRCODE(EGL_BAD_ATTRIBUTE)
37 MYERRCODE(EGL_BAD_CONTEXT)
38 MYERRCODE(EGL_BAD_CONFIG)
39 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
40 MYERRCODE(EGL_BAD_DISPLAY)
41 MYERRCODE(EGL_BAD_SURFACE)
42 MYERRCODE(EGL_BAD_MATCH)
43 MYERRCODE(EGL_BAD_PARAMETER)
44 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
45 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
46 MYERRCODE(EGL_CONTEXT_LOST)
54 print_egl_error_state(void)
59 weston_log("EGL error state: %s (0x%04lx)\n",
60 egl_error_string(code), (long)code);
63 #define max(a, b) (((a) > (b)) ? (a) : (b))
64 #define min(a, b) (((a) > (b)) ? (b) : (a))
65 #define clip(x, a, b) min(max(x, a), b)
66 #define sign(x) ((x) >= 0)
69 calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
70 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
73 GLfloat min_x, max_x, min_y, max_y;
75 surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1,
78 surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2,
80 GLfloat cx1 = rect->x1;
81 GLfloat cx2 = rect->x2;
82 GLfloat cy1 = rect->y1;
83 GLfloat cy2 = rect->y2;
85 GLfloat dist_squared(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
87 GLfloat dx = (x1 - x2);
88 GLfloat dy = (y1 - y2);
89 return dx * dx + dy * dy;
92 void append_vertex(GLfloat x, GLfloat y)
94 /* don't emit duplicate vertices: */
95 if ((n > 0) && (ex[n-1] == x) && (ey[n-1] == y))
102 /* transform surface to screen space: */
103 for (i = 0; i < 4; i++)
104 weston_surface_to_global_float(es, x[i], y[i], &x[i], &y[i]);
106 /* find bounding box: */
107 min_x = max_x = x[0];
108 min_y = max_y = y[0];
110 for (i = 1; i < 4; i++) {
111 min_x = min(min_x, x[i]);
112 max_x = max(max_x, x[i]);
113 min_y = min(min_y, y[i]);
114 max_y = max(max_y, y[i]);
117 /* First, simple bounding box check to discard early transformed
118 * surface rects that do not intersect with the clip region:
120 if ((min_x > cx2) || (max_x < cx1) ||
121 (min_y > cy2) || (max_y < cy1))
124 /* Simple case, bounding box edges are parallel to surface edges,
125 * there will be only four edges. We just need to clip the surface
126 * vertices to the clip rect bounds:
128 if (!es->transform.enabled) {
129 for (i = 0; i < 4; i++) {
130 ex[n] = clip(x[i], cx1, cx2);
131 ey[n] = clip(y[i], cy1, cy2);
137 /* Hard case, transformation applied. We need to find the vertices
138 * of the shape that is the intersection of the clip rect and
139 * transformed surface. This can be anything from 3 to 8 sides.
141 * Observation: all the resulting vertices will be the intersection
142 * points of the transformed surface and the clip rect, plus the
143 * vertices of the clip rect which are enclosed by the transformed
144 * surface and the vertices of the transformed surface which are
145 * enclosed by the clip rect.
147 * Observation: there will be zero, one, or two resulting vertices
148 * for each edge of the src rect.
150 * Loop over four edges of the transformed rect:
152 for (i = 0; i < 4; i++) {
153 GLfloat x1, y1, x2, y2;
159 /* if this vertex is contained in the clip rect, use it as-is: */
160 if ((cx1 <= x1) && (x1 <= cx2) &&
161 (cy1 <= y1) && (y1 <= cy2))
162 append_vertex(x1, y1);
164 /* for remaining, we consider the point as part of a line: */
169 append_vertex(clip(x1, cx1, cx2), clip(y1, cy1, cy2));
170 append_vertex(clip(x2, cx1, cx2), clip(y2, cy1, cy2));
171 } else if (y1 == y2) {
172 append_vertex(clip(x1, cx1, cx2), clip(y1, cy1, cy2));
173 append_vertex(clip(x2, cx1, cx2), clip(y2, cy1, cy2));
176 GLfloat tx[2], ty[2];
179 int intersect_horiz(GLfloat y, GLfloat *p)
183 /* if y does not lie between y1 and y2, no
184 * intersection possible
186 if (sign(y-y1) == sign(y-y2))
191 /* if x does not lie between cx1 and cx2, no
194 if (sign(x-cx1) == sign(x-cx2))
201 int intersect_vert(GLfloat x, GLfloat *p)
205 if (sign(x-x1) == sign(x-x2))
210 if (sign(y-cy1) == sign(y-cy2))
218 m = (y2 - y1) / (x2 - x1);
221 /* check for up to two intersections with the four edges
222 * of the clip rect. Note that we don't know the orientation
223 * of the transformed surface wrt. the clip rect. So if when
224 * there are two intersection points, we need to put the one
225 * closest to x1,y1 first:
228 /* check top clip rect edge: */
229 if (intersect_horiz(cy1, &p)) {
235 /* check right clip rect edge: */
236 if (intersect_vert(cx2, &p)) {
241 goto edge_check_done;
244 /* check bottom clip rect edge: */
245 if (intersect_horiz(cy2, &p)) {
250 goto edge_check_done;
253 /* check left clip rect edge: */
254 if (intersect_vert(cx1, &p)) {
262 append_vertex(tx[0], ty[0]);
263 } else if (tn == 2) {
264 if (dist_squared(x1, y1, tx[0], ty[0]) <
265 dist_squared(x1, y1, tx[1], ty[1])) {
266 append_vertex(tx[0], ty[0]);
267 append_vertex(tx[1], ty[1]);
269 append_vertex(tx[1], ty[1]);
270 append_vertex(tx[0], ty[0]);
275 GLfloat best_x=0, best_y=0;
276 uint32_t d, best_d = (unsigned int)-1; /* distance squared */
277 uint32_t max_d = dist_squared(x2, y2,
278 x[(i+2) % 4], y[(i+2) % 4]);
280 /* if there are no vertices on this line, it could be that
281 * there is a vertex of the clip rect that is enclosed by
282 * the transformed surface. Find the vertex of the clip
283 * rect that is reached by the shortest line perpendicular
284 * to the current edge, if any.
286 * slope of perpendicular is 1/m, so
293 int perp_intersect(GLfloat cx, GLfloat cy, uint32_t *d)
295 GLfloat c2 = cy + cx/m;
296 GLfloat x = (c2 - c) / (m + 1/m);
298 /* if the x position of the intersection of the
299 * perpendicular with the transformed edge does
300 * not lie within the bounds of the edge, then
303 if (sign(x-x1) == sign(x-x2))
306 *d = dist_squared(cx, cy, x, (m * x) + c);
308 /* if intersection distance is further away than
309 * opposite edge of surface region, it is invalid:
317 if (perp_intersect(cx1, cy1, &d)) {
323 if (perp_intersect(cx1, cy2, &d) && (d < best_d)) {
329 if (perp_intersect(cx2, cy2, &d) && (d < best_d)) {
335 if (perp_intersect(cx2, cy1, &d) && (d < best_d)) {
341 if (best_d != (unsigned int)-1) // XXX can this happen?
342 append_vertex(best_x, best_y);
352 texture_region(struct weston_surface *es, pixman_region32_t *region,
353 pixman_region32_t *surf_region)
355 struct weston_compositor *ec = es->compositor;
356 GLfloat *v, inv_width, inv_height;
357 unsigned int *vtxcnt, nvtx = 0;
358 pixman_box32_t *rects, *surf_rects;
359 int i, j, k, nrects, nsurf;
361 rects = pixman_region32_rectangles(region, &nrects);
362 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
364 /* worst case we can have 8 vertices per rect (ie. clipped into
367 v = wl_array_add(&ec->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
368 vtxcnt = wl_array_add(&ec->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
370 inv_width = 1.0 / es->pitch;
371 inv_height = 1.0 / es->geometry.height;
373 for (i = 0; i < nrects; i++) {
374 pixman_box32_t *rect = &rects[i];
375 for (j = 0; j < nsurf; j++) {
376 pixman_box32_t *surf_rect = &surf_rects[j];
378 GLfloat ex[8], ey[8]; /* edge points in screen space */
381 /* The transformed surface, after clipping to the clip region,
382 * can have as many as eight sides, emitted as a triangle-fan.
383 * The first vertex in the triangle fan can be chosen arbitrarily,
384 * since the area is guaranteed to be convex.
386 * If a corner of the transformed surface falls outside of the
387 * clip region, instead of emitting one vertex for the corner
388 * of the surface, up to two are emitted for two corresponding
389 * intersection point(s) between the surface and the clip region.
391 * To do this, we first calculate the (up to eight) points that
392 * form the intersection of the clip rect and the transformed
395 n = calculate_edges(es, rect, surf_rect, ex, ey);
399 /* emit edge points: */
400 for (k = 0; k < n; k++) {
401 weston_surface_from_global_float(es, ex[k], ey[k], &sx, &sy);
406 *(v++) = sx * inv_width;
407 *(v++) = sy * inv_height;
418 triangle_fan_debug(struct weston_surface *surface, int first, int count)
420 struct weston_compositor *compositor = surface->compositor;
425 static int color_idx = 0;
426 static const GLfloat color[][4] = {
427 { 1.0, 0.0, 0.0, 1.0 },
428 { 0.0, 1.0, 0.0, 1.0 },
429 { 0.0, 0.0, 1.0, 1.0 },
430 { 1.0, 1.0, 1.0, 1.0 },
433 nelems = (count - 1 + count - 2) * 2;
435 buffer = malloc(sizeof(GLushort) * nelems);
438 for (i = 1; i < count; i++) {
440 *index++ = first + i;
443 for (i = 2; i < count; i++) {
444 *index++ = first + i - 1;
445 *index++ = first + i;
448 glUseProgram(compositor->solid_shader.program);
449 glUniform4fv(compositor->solid_shader.color_uniform, 1,
450 color[color_idx++ % ARRAY_LENGTH(color)]);
451 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
452 glUseProgram(compositor->current_shader->program);
457 repaint_region(struct weston_surface *es, pixman_region32_t *region,
458 pixman_region32_t *surf_region)
460 struct weston_compositor *ec = es->compositor;
462 unsigned int *vtxcnt;
465 /* The final region to be painted is the intersection of
466 * 'region' and 'surf_region'. However, 'region' is in the global
467 * coordinates, and 'surf_region' is in the surface-local
468 * coordinates. texture_region() will iterate over all pairs of
469 * rectangles from both regions, compute the intersection
470 * polygon for each pair, and store it as a triangle fan if
471 * it has a non-zero area (at least 3 vertices, actually).
473 nfans = texture_region(es, region, surf_region);
475 v = ec->vertices.data;
476 vtxcnt = ec->vtxcnt.data;
479 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
480 glEnableVertexAttribArray(0);
483 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
484 glEnableVertexAttribArray(1);
486 for (i = 0, first = 0; i < nfans; i++) {
487 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
489 triangle_fan_debug(es, first, vtxcnt[i]);
493 glDisableVertexAttribArray(1);
494 glDisableVertexAttribArray(0);
496 ec->vertices.size = 0;
501 weston_compositor_use_shader(struct weston_compositor *compositor,
502 struct weston_shader *shader)
504 if (compositor->current_shader == shader)
507 glUseProgram(shader->program);
508 compositor->current_shader = shader;
512 weston_shader_uniforms(struct weston_shader *shader,
513 struct weston_surface *surface,
514 struct weston_output *output)
518 glUniformMatrix4fv(shader->proj_uniform,
519 1, GL_FALSE, output->matrix.d);
520 glUniform4fv(shader->color_uniform, 1, surface->color);
521 glUniform1f(shader->alpha_uniform, surface->alpha);
523 for (i = 0; i < surface->num_textures; i++)
524 glUniform1i(shader->tex_uniforms[i], i);
528 draw_surface(struct weston_surface *es, struct weston_output *output,
529 pixman_region32_t *damage) /* in global coordinates */
531 struct weston_compositor *ec = es->compositor;
532 /* repaint bounding region in global coordinates: */
533 pixman_region32_t repaint;
534 /* non-opaque region in surface coordinates: */
535 pixman_region32_t surface_blend;
539 pixman_region32_init(&repaint);
540 pixman_region32_intersect(&repaint,
541 &es->transform.boundingbox, damage);
542 pixman_region32_subtract(&repaint, &repaint, &es->clip);
544 if (!pixman_region32_not_empty(&repaint))
547 pixman_region32_subtract(&ec->primary_plane.damage,
548 &ec->primary_plane.damage, &repaint);
550 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
553 weston_compositor_use_shader(ec, &ec->solid_shader);
554 weston_shader_uniforms(&ec->solid_shader, es, output);
557 weston_compositor_use_shader(ec, es->shader);
558 weston_shader_uniforms(es->shader, es, output);
560 if (es->transform.enabled || output->zoom.active)
565 for (i = 0; i < es->num_textures; i++) {
566 glActiveTexture(GL_TEXTURE0 + i);
567 glBindTexture(es->target, es->textures[i]);
568 glTexParameteri(es->target, GL_TEXTURE_MIN_FILTER, filter);
569 glTexParameteri(es->target, GL_TEXTURE_MAG_FILTER, filter);
572 /* blended region is whole surface minus opaque region: */
573 pixman_region32_init_rect(&surface_blend, 0, 0,
574 es->geometry.width, es->geometry.height);
575 pixman_region32_subtract(&surface_blend, &surface_blend, &es->opaque);
577 if (pixman_region32_not_empty(&es->opaque)) {
578 if (es->shader == &ec->texture_shader_rgba) {
579 /* Special case for RGBA textures with possibly
580 * bad data in alpha channel: use the shader
581 * that forces texture alpha = 1.0.
582 * Xwayland surfaces need this.
584 weston_compositor_use_shader(ec, &ec->texture_shader_rgbx);
585 weston_shader_uniforms(&ec->texture_shader_rgbx, es, output);
593 repaint_region(es, &repaint, &es->opaque);
596 if (pixman_region32_not_empty(&surface_blend)) {
597 weston_compositor_use_shader(ec, es->shader);
599 repaint_region(es, &repaint, &surface_blend);
602 pixman_region32_fini(&surface_blend);
605 pixman_region32_fini(&repaint);
609 repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
611 struct weston_compositor *compositor = output->compositor;
612 struct weston_surface *surface;
614 wl_list_for_each_reverse(surface, &compositor->surface_list, link)
615 if (surface->plane == &compositor->primary_plane)
616 draw_surface(surface, output, damage);
620 gles2_renderer_repaint_output(struct weston_output *output,
621 pixman_region32_t *output_damage)
623 struct weston_compositor *compositor = output->compositor;
626 int32_t width, height;
628 width = output->current->width +
629 output->border.left + output->border.right;
630 height = output->current->height +
631 output->border.top + output->border.bottom;
633 glViewport(0, 0, width, height);
635 ret = eglMakeCurrent(compositor->egl_display, output->egl_surface,
636 output->egl_surface, compositor->egl_context);
637 if (ret == EGL_FALSE) {
641 weston_log("Failed to make EGL context current.\n");
642 print_egl_error_state();
646 /* if debugging, redraw everything outside the damage to clean up
647 * debug lines from the previous draw on this buffer:
649 if (compositor->fan_debug) {
650 pixman_region32_t undamaged;
651 pixman_region32_init(&undamaged);
652 pixman_region32_subtract(&undamaged, &output->region,
654 compositor->fan_debug = 0;
655 repaint_surfaces(output, &undamaged);
656 compositor->fan_debug = 1;
657 pixman_region32_fini(&undamaged);
660 repaint_surfaces(output, output_damage);
662 wl_signal_emit(&output->frame_signal, output);
664 ret = eglSwapBuffers(compositor->egl_display, output->egl_surface);
665 if (ret == EGL_FALSE && !errored) {
667 weston_log("Failed in eglSwapBuffers.\n");
668 print_egl_error_state();