compositor: Move surface repaint code to gles2-renderer.c
[profile/ivi/weston.git] / src / gles2-renderer.c
1 /*
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
23 #include <stdlib.h>
24
25 #include "compositor.h"
26
27 static const char *
28 egl_error_string(EGLint code)
29 {
30 #define MYERRCODE(x) case x: return #x;
31         switch (code) {
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)
47         default:
48                 return "unknown";
49         }
50 #undef MYERRCODE
51 }
52
53 static void
54 print_egl_error_state(void)
55 {
56         EGLint code;
57
58         code = eglGetError();
59         weston_log("EGL error state: %s (0x%04lx)\n",
60                 egl_error_string(code), (long)code);
61 }
62
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)
67
68 static int
69 calculate_edges(struct weston_surface *es, pixman_box32_t *rect,
70                 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
71 {
72         int i, n = 0;
73         GLfloat min_x, max_x, min_y, max_y;
74         GLfloat x[4] = {
75                         surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1,
76         };
77         GLfloat y[4] = {
78                         surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2,
79         };
80         GLfloat cx1 = rect->x1;
81         GLfloat cx2 = rect->x2;
82         GLfloat cy1 = rect->y1;
83         GLfloat cy2 = rect->y2;
84
85         GLfloat dist_squared(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
86         {
87                 GLfloat dx = (x1 - x2);
88                 GLfloat dy = (y1 - y2);
89                 return dx * dx + dy * dy;
90         }
91
92         void append_vertex(GLfloat x, GLfloat y)
93         {
94                 /* don't emit duplicate vertices: */
95                 if ((n > 0) && (ex[n-1] == x) && (ey[n-1] == y))
96                         return;
97                 ex[n] = x;
98                 ey[n] = y;
99                 n++;
100         }
101
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]);
105
106         /* find bounding box: */
107         min_x = max_x = x[0];
108         min_y = max_y = y[0];
109
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]);
115         }
116
117         /* First, simple bounding box check to discard early transformed
118          * surface rects that do not intersect with the clip region:
119          */
120         if ((min_x > cx2) || (max_x < cx1) ||
121                         (min_y > cy2) || (max_y < cy1))
122                 return 0;
123
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:
127          */
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);
132                         n++;
133                 }
134                 return 4;
135         }
136
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.
140          *
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.
146          *
147          * Observation: there will be zero, one, or two resulting vertices
148          * for each edge of the src rect.
149          *
150          * Loop over four edges of the transformed rect:
151          */
152         for (i = 0; i < 4; i++) {
153                 GLfloat x1, y1, x2, y2;
154                 int last_n = n;
155
156                 x1 = x[i];
157                 y1 = y[i];
158
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);
163
164                 /* for remaining, we consider the point as part of a line: */
165                 x2 = x[(i+1) % 4];
166                 y2 = y[(i+1) % 4];
167
168                 if (x1 == x2) {
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));
174                 } else {
175                         GLfloat m, c, p;
176                         GLfloat tx[2], ty[2];
177                         int tn = 0;
178
179                         int intersect_horiz(GLfloat y, GLfloat *p)
180                         {
181                                 GLfloat x;
182
183                                 /* if y does not lie between y1 and y2, no
184                                  * intersection possible
185                                  */
186                                 if (sign(y-y1) == sign(y-y2))
187                                         return 0;
188
189                                 x = (y - c) / m;
190
191                                 /* if x does not lie between cx1 and cx2, no
192                                  * intersection:
193                                  */
194                                 if (sign(x-cx1) == sign(x-cx2))
195                                         return 0;
196
197                                 *p = x;
198                                 return 1;
199                         }
200
201                         int intersect_vert(GLfloat x, GLfloat *p)
202                         {
203                                 GLfloat y;
204
205                                 if (sign(x-x1) == sign(x-x2))
206                                         return 0;
207
208                                 y = m * x + c;
209
210                                 if (sign(y-cy1) == sign(y-cy2))
211                                         return 0;
212
213                                 *p = y;
214                                 return 1;
215                         }
216
217                         /* y = mx + c */
218                         m = (y2 - y1) / (x2 - x1);
219                         c = y1 - m * x1;
220
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:
226                          */
227
228                         /* check top clip rect edge: */
229                         if (intersect_horiz(cy1, &p)) {
230                                 ty[tn] = cy1;
231                                 tx[tn] = p;
232                                 tn++;
233                         }
234
235                         /* check right clip rect edge: */
236                         if (intersect_vert(cx2, &p)) {
237                                 ty[tn] = p;
238                                 tx[tn] = cx2;
239                                 tn++;
240                                 if (tn == 2)
241                                         goto edge_check_done;
242                         }
243
244                         /* check bottom clip rect edge: */
245                         if (intersect_horiz(cy2, &p)) {
246                                 ty[tn] = cy2;
247                                 tx[tn] = p;
248                                 tn++;
249                                 if (tn == 2)
250                                         goto edge_check_done;
251                         }
252
253                         /* check left clip rect edge: */
254                         if (intersect_vert(cx1, &p)) {
255                                 ty[tn] = p;
256                                 tx[tn] = cx1;
257                                 tn++;
258                         }
259
260 edge_check_done:
261                         if (tn == 1) {
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]);
268                                 } else {
269                                         append_vertex(tx[1], ty[1]);
270                                         append_vertex(tx[0], ty[0]);
271                                 }
272                         }
273
274                         if (n == last_n) {
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]);
279
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.
285                                  *
286                                  * slope of perpendicular is 1/m, so
287                                  *
288                                  *   cy = -cx/m + c2
289                                  *   c2 = cy + cx/m
290                                  *
291                                  */
292
293                                 int perp_intersect(GLfloat cx, GLfloat cy, uint32_t *d)
294                                 {
295                                         GLfloat c2 = cy + cx/m;
296                                         GLfloat x = (c2 - c) / (m + 1/m);
297
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
301                                          * no intersection:
302                                          */
303                                         if (sign(x-x1) == sign(x-x2))
304                                                 return 0;
305
306                                         *d = dist_squared(cx, cy, x, (m * x) + c);
307
308                                         /* if intersection distance is further away than
309                                          * opposite edge of surface region, it is invalid:
310                                          */
311                                         if (*d > max_d)
312                                                 return 0;
313
314                                         return 1;
315                                 }
316
317                                 if (perp_intersect(cx1, cy1, &d)) {
318                                         best_x = cx1;
319                                         best_y = cy1;
320                                         best_d = d;
321                                 }
322
323                                 if (perp_intersect(cx1, cy2, &d) && (d < best_d)) {
324                                         best_x = cx1;
325                                         best_y = cy2;
326                                         best_d = d;
327                                 }
328
329                                 if (perp_intersect(cx2, cy2, &d) && (d < best_d)) {
330                                         best_x = cx2;
331                                         best_y = cy2;
332                                         best_d = d;
333                                 }
334
335                                 if (perp_intersect(cx2, cy1, &d) && (d < best_d)) {
336                                         best_x = cx2;
337                                         best_y = cy1;
338                                         best_d = d;
339                                 }
340
341                                 if (best_d != (unsigned int)-1)  // XXX can this happen?
342                                         append_vertex(best_x, best_y);
343                         }
344                 }
345
346         }
347
348         return n;
349 }
350
351 static int
352 texture_region(struct weston_surface *es, pixman_region32_t *region,
353                 pixman_region32_t *surf_region)
354 {
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;
360
361         rects = pixman_region32_rectangles(region, &nrects);
362         surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
363
364         /* worst case we can have 8 vertices per rect (ie. clipped into
365          * an octagon):
366          */
367         v = wl_array_add(&ec->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
368         vtxcnt = wl_array_add(&ec->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
369
370         inv_width = 1.0 / es->pitch;
371         inv_height = 1.0 / es->geometry.height;
372
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];
377                         GLfloat sx, sy;
378                         GLfloat ex[8], ey[8];          /* edge points in screen space */
379                         int n;
380
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.
385                          *
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.
390                          *
391                          * To do this, we first calculate the (up to eight) points that
392                          * form the intersection of the clip rect and the transformed
393                          * surface.
394                          */
395                         n = calculate_edges(es, rect, surf_rect, ex, ey);
396                         if (n < 3)
397                                 continue;
398
399                         /* emit edge points: */
400                         for (k = 0; k < n; k++) {
401                                 weston_surface_from_global_float(es, ex[k], ey[k], &sx, &sy);
402                                 /* position: */
403                                 *(v++) = ex[k];
404                                 *(v++) = ey[k];
405                                 /* texcoord: */
406                                 *(v++) = sx * inv_width;
407                                 *(v++) = sy * inv_height;
408                         }
409
410                         vtxcnt[nvtx++] = n;
411                 }
412         }
413
414         return nvtx;
415 }
416
417 static void
418 triangle_fan_debug(struct weston_surface *surface, int first, int count)
419 {
420         struct weston_compositor *compositor = surface->compositor;
421         int i;
422         GLushort *buffer;
423         GLushort *index;
424         int nelems;
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 },
431         };
432
433         nelems = (count - 1 + count - 2) * 2;
434
435         buffer = malloc(sizeof(GLushort) * nelems);
436         index = buffer;
437
438         for (i = 1; i < count; i++) {
439                 *index++ = first;
440                 *index++ = first + i;
441         }
442
443         for (i = 2; i < count; i++) {
444                 *index++ = first + i - 1;
445                 *index++ = first + i;
446         }
447
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);
453         free(buffer);
454 }
455
456 static void
457 repaint_region(struct weston_surface *es, pixman_region32_t *region,
458                 pixman_region32_t *surf_region)
459 {
460         struct weston_compositor *ec = es->compositor;
461         GLfloat *v;
462         unsigned int *vtxcnt;
463         int i, first, nfans;
464
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).
472          */
473         nfans = texture_region(es, region, surf_region);
474
475         v = ec->vertices.data;
476         vtxcnt = ec->vtxcnt.data;
477
478         /* position: */
479         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
480         glEnableVertexAttribArray(0);
481
482         /* texcoord: */
483         glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
484         glEnableVertexAttribArray(1);
485
486         for (i = 0, first = 0; i < nfans; i++) {
487                 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
488                 if (ec->fan_debug)
489                         triangle_fan_debug(es, first, vtxcnt[i]);
490                 first += vtxcnt[i];
491         }
492
493         glDisableVertexAttribArray(1);
494         glDisableVertexAttribArray(0);
495
496         ec->vertices.size = 0;
497         ec->vtxcnt.size = 0;
498 }
499
500 static void
501 weston_compositor_use_shader(struct weston_compositor *compositor,
502                              struct weston_shader *shader)
503 {
504         if (compositor->current_shader == shader)
505                 return;
506
507         glUseProgram(shader->program);
508         compositor->current_shader = shader;
509 }
510
511 static void
512 weston_shader_uniforms(struct weston_shader *shader,
513                        struct weston_surface *surface,
514                        struct weston_output *output)
515 {
516         int i;
517
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);
522
523         for (i = 0; i < surface->num_textures; i++)
524                 glUniform1i(shader->tex_uniforms[i], i);
525 }
526
527 static void
528 draw_surface(struct weston_surface *es, struct weston_output *output,
529              pixman_region32_t *damage) /* in global coordinates */
530 {
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;
536         GLint filter;
537         int i;
538
539         pixman_region32_init(&repaint);
540         pixman_region32_intersect(&repaint,
541                                   &es->transform.boundingbox, damage);
542         pixman_region32_subtract(&repaint, &repaint, &es->clip);
543
544         if (!pixman_region32_not_empty(&repaint))
545                 goto out;
546
547         pixman_region32_subtract(&ec->primary_plane.damage,
548                                  &ec->primary_plane.damage, &repaint);
549
550         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
551
552         if (ec->fan_debug) {
553                 weston_compositor_use_shader(ec, &ec->solid_shader);
554                 weston_shader_uniforms(&ec->solid_shader, es, output);
555         }
556
557         weston_compositor_use_shader(ec, es->shader);
558         weston_shader_uniforms(es->shader, es, output);
559
560         if (es->transform.enabled || output->zoom.active)
561                 filter = GL_LINEAR;
562         else
563                 filter = GL_NEAREST;
564
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);
570         }
571
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);
576
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.
583                          */
584                         weston_compositor_use_shader(ec, &ec->texture_shader_rgbx);
585                         weston_shader_uniforms(&ec->texture_shader_rgbx, es, output);
586                 }
587
588                 if (es->alpha < 1.0)
589                         glEnable(GL_BLEND);
590                 else
591                         glDisable(GL_BLEND);
592
593                 repaint_region(es, &repaint, &es->opaque);
594         }
595
596         if (pixman_region32_not_empty(&surface_blend)) {
597                 weston_compositor_use_shader(ec, es->shader);
598                 glEnable(GL_BLEND);
599                 repaint_region(es, &repaint, &surface_blend);
600         }
601
602         pixman_region32_fini(&surface_blend);
603
604 out:
605         pixman_region32_fini(&repaint);
606 }
607
608 static void
609 repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
610 {
611         struct weston_compositor *compositor = output->compositor;
612         struct weston_surface *surface;
613
614         wl_list_for_each_reverse(surface, &compositor->surface_list, link)
615                 if (surface->plane == &compositor->primary_plane)
616                         draw_surface(surface, output, damage);
617 }
618
619 WL_EXPORT void
620 gles2_renderer_repaint_output(struct weston_output *output,
621                               pixman_region32_t *output_damage)
622 {
623         struct weston_compositor *compositor = output->compositor;
624         EGLBoolean ret;
625         static int errored;
626         int32_t width, height;
627
628         width = output->current->width +
629                 output->border.left + output->border.right;
630         height = output->current->height +
631                 output->border.top + output->border.bottom;
632
633         glViewport(0, 0, width, height);
634
635         ret = eglMakeCurrent(compositor->egl_display, output->egl_surface,
636                              output->egl_surface, compositor->egl_context);
637         if (ret == EGL_FALSE) {
638                 if (errored)
639                         return;
640                 errored = 1;
641                 weston_log("Failed to make EGL context current.\n");
642                 print_egl_error_state();
643                 return;
644         }
645
646         /* if debugging, redraw everything outside the damage to clean up
647          * debug lines from the previous draw on this buffer:
648          */
649         if (compositor->fan_debug) {
650                 pixman_region32_t undamaged;
651                 pixman_region32_init(&undamaged);
652                 pixman_region32_subtract(&undamaged, &output->region,
653                                          output_damage);
654                 compositor->fan_debug = 0;
655                 repaint_surfaces(output, &undamaged);
656                 compositor->fan_debug = 1;
657                 pixman_region32_fini(&undamaged);
658         }
659
660         repaint_surfaces(output, output_damage);
661
662         wl_signal_emit(&output->frame_signal, output);
663
664         ret = eglSwapBuffers(compositor->egl_display, output->egl_surface);
665         if (ret == EGL_FALSE && !errored) {
666                 errored = 1;
667                 weston_log("Failed in eglSwapBuffers.\n");
668                 print_egl_error_state();
669         }
670
671 }