blob: c8dfa4b783d0594ecde25f8e51c1da721fc46861 [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
Daniel Stonec228e232013-05-22 18:03:19 +030023#include "config.h"
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040024
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010025#include <GLES2/gl2.h>
26#include <GLES2/gl2ext.h>
27
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040028#include <stdlib.h>
Kristian Høgsberg25894fc2012-09-05 22:06:26 -040029#include <string.h>
30#include <ctype.h>
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +030031#include <float.h>
32#include <assert.h>
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +020033#include <linux/input.h>
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -040034
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010035#include "gl-renderer.h"
Sam Spilsbury619859c2013-09-13 10:01:21 +080036#include "vertex-clipping.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010037
38#include <EGL/eglext.h>
39#include "weston-egl-ext.h"
Kristian Høgsbergd7c17262012-09-05 21:54:15 -040040
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010041struct gl_shader {
John Kåre Alsaker40684142012-11-13 19:10:25 +010042 GLuint program;
43 GLuint vertex_shader, fragment_shader;
44 GLint proj_uniform;
45 GLint tex_uniforms[3];
46 GLint alpha_uniform;
47 GLint color_uniform;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +030048 const char *vertex_source, *fragment_source;
John Kåre Alsaker40684142012-11-13 19:10:25 +010049};
50
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020051#define BUFFER_DAMAGE_COUNT 2
52
Jason Ekstrande5512d42014-02-04 21:36:38 -060053enum gl_border_status {
54 BORDER_STATUS_CLEAN = 0,
55 BORDER_TOP_DIRTY = 1 << GL_RENDERER_BORDER_TOP,
56 BORDER_LEFT_DIRTY = 1 << GL_RENDERER_BORDER_LEFT,
57 BORDER_RIGHT_DIRTY = 1 << GL_RENDERER_BORDER_RIGHT,
58 BORDER_BOTTOM_DIRTY = 1 << GL_RENDERER_BORDER_BOTTOM,
59 BORDER_ALL_DIRTY = 0xf,
60 BORDER_SIZE_CHANGED = 0x10
61};
62
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050063struct gl_border_image {
64 GLuint tex;
65 int32_t width, height;
66 int32_t tex_width;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050067 void *data;
68};
69
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010070struct gl_output_state {
John Kåre Alsaker94659272012-11-13 19:10:18 +010071 EGLSurface egl_surface;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +020072 pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
Jason Ekstrande5512d42014-02-04 21:36:38 -060073 enum gl_border_status border_damage[BUFFER_DAMAGE_COUNT];
Jason Ekstrand0b61bf42013-10-27 22:24:54 -050074 struct gl_border_image borders[4];
Jason Ekstrande5512d42014-02-04 21:36:38 -060075 enum gl_border_status border_status;
John Kåre Alsaker94659272012-11-13 19:10:18 +010076};
77
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030078enum buffer_type {
79 BUFFER_TYPE_NULL,
80 BUFFER_TYPE_SHM,
81 BUFFER_TYPE_EGL
82};
83
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010084struct gl_surface_state {
John Kåre Alsaker878f4492012-11-13 19:10:23 +010085 GLfloat color[4];
John Kåre Alsaker779b52a2012-11-13 19:10:29 +010086 struct gl_shader *shader;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +010087
88 GLuint textures[3];
89 int num_textures;
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +030090 int needs_full_upload;
Pekka Paalanen81ee3f52012-12-04 15:58:16 +020091 pixman_region32_t texture_damage;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +010092
93 EGLImageKHR images[3];
94 GLenum target;
95 int num_images;
Pekka Paalanenfb003d32012-12-04 15:58:13 +020096
97 struct weston_buffer_reference buffer_ref;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +030098 enum buffer_type buffer_type;
Pekka Paalanen68033ac2012-12-04 15:58:15 +020099 int pitch; /* in pixels */
Alexander Larsson4ea95522013-05-22 14:41:37 +0200100 int height; /* in pixels */
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400101 int y_inverted;
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300102
103 struct weston_surface *surface;
104
105 struct wl_listener surface_destroy_listener;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +0300106 struct wl_listener renderer_destroy_listener;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100107};
108
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100109struct gl_renderer {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100110 struct weston_renderer base;
111 int fragment_shader_debug;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400112 int fan_debug;
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +0300113 struct weston_binding *fragment_binding;
114 struct weston_binding *fan_binding;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100115
116 EGLDisplay egl_display;
117 EGLContext egl_context;
118 EGLConfig egl_config;
John Kåre Alsaker44154502012-11-13 19:10:20 +0100119
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400120 struct wl_array vertices;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400121 struct wl_array vtxcnt;
122
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100123 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
124 PFNEGLCREATEIMAGEKHRPROC create_image;
125 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
126
127 int has_unpack_subimage;
128
129 PFNEGLBINDWAYLANDDISPLAYWL bind_display;
130 PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
131 PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
132 int has_bind_display;
133
134 int has_egl_image_external;
135
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200136 int has_egl_buffer_age;
137
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100138 struct gl_shader texture_shader_rgba;
139 struct gl_shader texture_shader_rgbx;
140 struct gl_shader texture_shader_egl_external;
141 struct gl_shader texture_shader_y_uv;
142 struct gl_shader texture_shader_y_u_v;
143 struct gl_shader texture_shader_y_xuxv;
144 struct gl_shader invert_color_shader;
145 struct gl_shader solid_shader;
146 struct gl_shader *current_shader;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +0300147
148 struct wl_signal destroy_signal;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100149};
John Kåre Alsaker94659272012-11-13 19:10:18 +0100150
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100151static inline struct gl_output_state *
John Kåre Alsaker94659272012-11-13 19:10:18 +0100152get_output_state(struct weston_output *output)
153{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100154 return (struct gl_output_state *)output->renderer_state;
John Kåre Alsaker94659272012-11-13 19:10:18 +0100155}
156
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300157static int
158gl_renderer_create_surface(struct weston_surface *surface);
159
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100160static inline struct gl_surface_state *
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100161get_surface_state(struct weston_surface *surface)
162{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +0300163 if (!surface->renderer_state)
164 gl_renderer_create_surface(surface);
165
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100166 return (struct gl_surface_state *)surface->renderer_state;
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100167}
168
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100169static inline struct gl_renderer *
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100170get_renderer(struct weston_compositor *ec)
171{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100172 return (struct gl_renderer *)ec->renderer;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100173}
174
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400175static const char *
176egl_error_string(EGLint code)
177{
178#define MYERRCODE(x) case x: return #x;
179 switch (code) {
180 MYERRCODE(EGL_SUCCESS)
181 MYERRCODE(EGL_NOT_INITIALIZED)
182 MYERRCODE(EGL_BAD_ACCESS)
183 MYERRCODE(EGL_BAD_ALLOC)
184 MYERRCODE(EGL_BAD_ATTRIBUTE)
185 MYERRCODE(EGL_BAD_CONTEXT)
186 MYERRCODE(EGL_BAD_CONFIG)
187 MYERRCODE(EGL_BAD_CURRENT_SURFACE)
188 MYERRCODE(EGL_BAD_DISPLAY)
189 MYERRCODE(EGL_BAD_SURFACE)
190 MYERRCODE(EGL_BAD_MATCH)
191 MYERRCODE(EGL_BAD_PARAMETER)
192 MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
193 MYERRCODE(EGL_BAD_NATIVE_WINDOW)
194 MYERRCODE(EGL_CONTEXT_LOST)
195 default:
196 return "unknown";
197 }
198#undef MYERRCODE
199}
200
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300201static void
Pekka Paalanen326529f2012-11-27 12:25:25 +0200202gl_renderer_print_egl_error_state(void)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400203{
204 EGLint code;
205
206 code = eglGetError();
207 weston_log("EGL error state: %s (0x%04lx)\n",
208 egl_error_string(code), (long)code);
209}
210
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400211#define max(a, b) (((a) > (b)) ? (a) : (b))
212#define min(a, b) (((a) > (b)) ? (b) : (a))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400213
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300214/*
215 * Compute the boundary vertices of the intersection of the global coordinate
216 * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
217 * 'surf_rect' when transformed from surface coordinates into global coordinates.
218 * The vertices are written to 'ex' and 'ey', and the return value is the
219 * number of vertices. Vertices are produced in clockwise winding order.
220 * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
221 * polygon area.
222 */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400223static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500224calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400225 pixman_box32_t *surf_rect, GLfloat *ex, GLfloat *ey)
226{
Sam Spilsbury619859c2013-09-13 10:01:21 +0800227
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300228 struct clip_context ctx;
229 int i, n;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400230 GLfloat min_x, max_x, min_y, max_y;
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300231 struct polygon8 surf = {
232 { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
233 { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
234 4
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400235 };
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400236
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300237 ctx.clip.x1 = rect->x1;
238 ctx.clip.y1 = rect->y1;
239 ctx.clip.x2 = rect->x2;
240 ctx.clip.y2 = rect->y2;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400241
242 /* transform surface to screen space: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300243 for (i = 0; i < surf.n; i++)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500244 weston_view_to_global_float(ev, surf.x[i], surf.y[i],
245 &surf.x[i], &surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400246
247 /* find bounding box: */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300248 min_x = max_x = surf.x[0];
249 min_y = max_y = surf.y[0];
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400250
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300251 for (i = 1; i < surf.n; i++) {
252 min_x = min(min_x, surf.x[i]);
253 max_x = max(max_x, surf.x[i]);
254 min_y = min(min_y, surf.y[i]);
255 max_y = max(max_y, surf.y[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400256 }
257
258 /* First, simple bounding box check to discard early transformed
259 * surface rects that do not intersect with the clip region:
260 */
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300261 if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
262 (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400263 return 0;
264
265 /* Simple case, bounding box edges are parallel to surface edges,
266 * there will be only four edges. We just need to clip the surface
267 * vertices to the clip rect bounds:
268 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500269 if (!ev->transform.enabled)
Sam Spilsbury619859c2013-09-13 10:01:21 +0800270 return clip_simple(&ctx, &surf, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400271
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300272 /* Transformed case: use a general polygon clipping algorithm to
273 * clip the surface rectangle with each side of 'rect'.
274 * The algorithm is Sutherland-Hodgman, as explained in
275 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
276 * but without looking at any of that code.
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400277 */
Sam Spilsbury619859c2013-09-13 10:01:21 +0800278 n = clip_transformed(&ctx, &surf, ex, ey);
Pekka Paalanen0d64a0f2012-09-11 17:02:05 +0300279
280 if (n < 3)
281 return 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400282
283 return n;
284}
285
286static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500287texture_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400288 pixman_region32_t *surf_region)
289{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500290 struct gl_surface_state *gs = get_surface_state(ev->surface);
291 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400292 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400293 GLfloat *v, inv_width, inv_height;
294 unsigned int *vtxcnt, nvtx = 0;
295 pixman_box32_t *rects, *surf_rects;
296 int i, j, k, nrects, nsurf;
297
298 rects = pixman_region32_rectangles(region, &nrects);
299 surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
300
301 /* worst case we can have 8 vertices per rect (ie. clipped into
302 * an octagon):
303 */
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400304 v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
305 vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400306
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200307 inv_width = 1.0 / gs->pitch;
Alexander Larsson4ea95522013-05-22 14:41:37 +0200308 inv_height = 1.0 / gs->height;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400309
310 for (i = 0; i < nrects; i++) {
311 pixman_box32_t *rect = &rects[i];
312 for (j = 0; j < nsurf; j++) {
313 pixman_box32_t *surf_rect = &surf_rects[j];
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200314 GLfloat sx, sy, bx, by;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400315 GLfloat ex[8], ey[8]; /* edge points in screen space */
316 int n;
317
318 /* The transformed surface, after clipping to the clip region,
319 * can have as many as eight sides, emitted as a triangle-fan.
320 * The first vertex in the triangle fan can be chosen arbitrarily,
321 * since the area is guaranteed to be convex.
322 *
323 * If a corner of the transformed surface falls outside of the
324 * clip region, instead of emitting one vertex for the corner
325 * of the surface, up to two are emitted for two corresponding
326 * intersection point(s) between the surface and the clip region.
327 *
328 * To do this, we first calculate the (up to eight) points that
329 * form the intersection of the clip rect and the transformed
330 * surface.
331 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500332 n = calculate_edges(ev, rect, surf_rect, ex, ey);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400333 if (n < 3)
334 continue;
335
336 /* emit edge points: */
337 for (k = 0; k < n; k++) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500338 weston_view_from_global_float(ev, ex[k], ey[k],
339 &sx, &sy);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400340 /* position: */
341 *(v++) = ex[k];
342 *(v++) = ey[k];
343 /* texcoord: */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500344 weston_surface_to_buffer_float(ev->surface,
345 sx, sy,
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200346 &bx, &by);
347 *(v++) = bx * inv_width;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +0400348 if (gs->y_inverted) {
349 *(v++) = by * inv_height;
350 } else {
351 *(v++) = (gs->height - by) * inv_height;
352 }
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400353 }
354
355 vtxcnt[nvtx++] = n;
356 }
357 }
358
359 return nvtx;
360}
361
362static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500363triangle_fan_debug(struct weston_view *view, int first, int count)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400364{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500365 struct weston_compositor *compositor = view->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100366 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400367 int i;
368 GLushort *buffer;
369 GLushort *index;
370 int nelems;
371 static int color_idx = 0;
372 static const GLfloat color[][4] = {
373 { 1.0, 0.0, 0.0, 1.0 },
374 { 0.0, 1.0, 0.0, 1.0 },
375 { 0.0, 0.0, 1.0, 1.0 },
376 { 1.0, 1.0, 1.0, 1.0 },
377 };
378
379 nelems = (count - 1 + count - 2) * 2;
380
381 buffer = malloc(sizeof(GLushort) * nelems);
382 index = buffer;
383
384 for (i = 1; i < count; i++) {
385 *index++ = first;
386 *index++ = first + i;
387 }
388
389 for (i = 2; i < count; i++) {
390 *index++ = first + i - 1;
391 *index++ = first + i;
392 }
393
John Kåre Alsaker40684142012-11-13 19:10:25 +0100394 glUseProgram(gr->solid_shader.program);
395 glUniform4fv(gr->solid_shader.color_uniform, 1,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400396 color[color_idx++ % ARRAY_LENGTH(color)]);
397 glDrawElements(GL_LINES, nelems, GL_UNSIGNED_SHORT, buffer);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100398 glUseProgram(gr->current_shader->program);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400399 free(buffer);
400}
401
402static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500403repaint_region(struct weston_view *ev, pixman_region32_t *region,
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400404 pixman_region32_t *surf_region)
405{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500406 struct weston_compositor *ec = ev->surface->compositor;
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400407 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400408 GLfloat *v;
409 unsigned int *vtxcnt;
410 int i, first, nfans;
411
412 /* The final region to be painted is the intersection of
413 * 'region' and 'surf_region'. However, 'region' is in the global
414 * coordinates, and 'surf_region' is in the surface-local
415 * coordinates. texture_region() will iterate over all pairs of
416 * rectangles from both regions, compute the intersection
417 * polygon for each pair, and store it as a triangle fan if
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400418 * it has a non-zero area (at least 3 vertices1, actually).
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400419 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500420 nfans = texture_region(ev, region, surf_region);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400421
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400422 v = gr->vertices.data;
423 vtxcnt = gr->vtxcnt.data;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400424
425 /* position: */
426 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
427 glEnableVertexAttribArray(0);
428
429 /* texcoord: */
430 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]);
431 glEnableVertexAttribArray(1);
432
433 for (i = 0, first = 0; i < nfans; i++) {
434 glDrawArrays(GL_TRIANGLE_FAN, first, vtxcnt[i]);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400435 if (gr->fan_debug)
Jason Ekstranda7af7042013-10-12 22:38:11 -0500436 triangle_fan_debug(ev, first, vtxcnt[i]);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400437 first += vtxcnt[i];
438 }
439
440 glDisableVertexAttribArray(1);
441 glDisableVertexAttribArray(0);
442
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -0400443 gr->vertices.size = 0;
444 gr->vtxcnt.size = 0;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400445}
446
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100447static int
448use_output(struct weston_output *output)
449{
450 static int errored;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100451 struct gl_output_state *go = get_output_state(output);
452 struct gl_renderer *gr = get_renderer(output->compositor);
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100453 EGLBoolean ret;
454
455 ret = eglMakeCurrent(gr->egl_display, go->egl_surface,
456 go->egl_surface, gr->egl_context);
457
458 if (ret == EGL_FALSE) {
459 if (errored)
460 return -1;
461 errored = 1;
462 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200463 gl_renderer_print_egl_error_state();
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100464 return -1;
465 }
466
467 return 0;
468}
469
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300470static int
471shader_init(struct gl_shader *shader, struct gl_renderer *gr,
472 const char *vertex_source, const char *fragment_source);
473
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400474static void
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300475use_shader(struct gl_renderer *gr, struct gl_shader *shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400476{
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +0300477 if (!shader->program) {
478 int ret;
479
480 ret = shader_init(shader, gr,
481 shader->vertex_source,
482 shader->fragment_source);
483
484 if (ret < 0)
485 weston_log("warning: failed to compile shader\n");
486 }
487
John Kåre Alsaker40684142012-11-13 19:10:25 +0100488 if (gr->current_shader == shader)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400489 return;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400490 glUseProgram(shader->program);
John Kåre Alsaker40684142012-11-13 19:10:25 +0100491 gr->current_shader = shader;
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400492}
493
494static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100495shader_uniforms(struct gl_shader *shader,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500496 struct weston_view *view,
497 struct weston_output *output)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400498{
499 int i;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500500 struct gl_surface_state *gs = get_surface_state(view->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400501
502 glUniformMatrix4fv(shader->proj_uniform,
503 1, GL_FALSE, output->matrix.d);
John Kåre Alsaker878f4492012-11-13 19:10:23 +0100504 glUniform4fv(shader->color_uniform, 1, gs->color);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500505 glUniform1f(shader->alpha_uniform, view->alpha);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400506
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100507 for (i = 0; i < gs->num_textures; i++)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400508 glUniform1i(shader->tex_uniforms[i], i);
509}
510
511static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500512draw_view(struct weston_view *ev, struct weston_output *output,
513 pixman_region32_t *damage) /* in global coordinates */
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400514{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500515 struct weston_compositor *ec = ev->surface->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100516 struct gl_renderer *gr = get_renderer(ec);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500517 struct gl_surface_state *gs = get_surface_state(ev->surface);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400518 /* repaint bounding region in global coordinates: */
519 pixman_region32_t repaint;
520 /* non-opaque region in surface coordinates: */
521 pixman_region32_t surface_blend;
522 GLint filter;
523 int i;
524
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +0200525 /* In case of a runtime switch of renderers, we may not have received
526 * an attach for this surface since the switch. In that case we don't
527 * have a valid buffer or a proper shader set up so skip rendering. */
528 if (!gs->shader)
529 return;
530
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400531 pixman_region32_init(&repaint);
532 pixman_region32_intersect(&repaint,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500533 &ev->transform.boundingbox, damage);
534 pixman_region32_subtract(&repaint, &repaint, &ev->clip);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400535
536 if (!pixman_region32_not_empty(&repaint))
537 goto out;
538
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400539 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
540
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400541 if (gr->fan_debug) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100542 use_shader(gr, &gr->solid_shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500543 shader_uniforms(&gr->solid_shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400544 }
545
John Kåre Alsaker40684142012-11-13 19:10:25 +0100546 use_shader(gr, gs->shader);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500547 shader_uniforms(gs->shader, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400548
Jason Ekstranda7af7042013-10-12 22:38:11 -0500549 if (ev->transform.enabled || output->zoom.active ||
Pekka Paalanen1fd9c0f2013-11-26 18:19:41 +0100550 output->current_scale != ev->surface->buffer_viewport.scale)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400551 filter = GL_LINEAR;
552 else
553 filter = GL_NEAREST;
554
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100555 for (i = 0; i < gs->num_textures; i++) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400556 glActiveTexture(GL_TEXTURE0 + i);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100557 glBindTexture(gs->target, gs->textures[i]);
558 glTexParameteri(gs->target, GL_TEXTURE_MIN_FILTER, filter);
559 glTexParameteri(gs->target, GL_TEXTURE_MAG_FILTER, filter);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400560 }
561
562 /* blended region is whole surface minus opaque region: */
563 pixman_region32_init_rect(&surface_blend, 0, 0,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -0600564 ev->surface->width, ev->surface->height);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500565 pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400566
Jason Ekstranda7af7042013-10-12 22:38:11 -0500567 /* XXX: Should we be using ev->transform.opaque here? */
568 if (pixman_region32_not_empty(&ev->surface->opaque)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100569 if (gs->shader == &gr->texture_shader_rgba) {
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400570 /* Special case for RGBA textures with possibly
571 * bad data in alpha channel: use the shader
572 * that forces texture alpha = 1.0.
573 * Xwayland surfaces need this.
574 */
John Kåre Alsaker40684142012-11-13 19:10:25 +0100575 use_shader(gr, &gr->texture_shader_rgbx);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500576 shader_uniforms(&gr->texture_shader_rgbx, ev, output);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400577 }
578
Jason Ekstranda7af7042013-10-12 22:38:11 -0500579 if (ev->alpha < 1.0)
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400580 glEnable(GL_BLEND);
581 else
582 glDisable(GL_BLEND);
583
Jason Ekstranda7af7042013-10-12 22:38:11 -0500584 repaint_region(ev, &repaint, &ev->surface->opaque);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400585 }
586
587 if (pixman_region32_not_empty(&surface_blend)) {
John Kåre Alsaker40684142012-11-13 19:10:25 +0100588 use_shader(gr, gs->shader);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400589 glEnable(GL_BLEND);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500590 repaint_region(ev, &repaint, &surface_blend);
Kristian Høgsbergecf6ede2012-09-05 21:59:35 -0400591 }
592
593 pixman_region32_fini(&surface_blend);
594
595out:
596 pixman_region32_fini(&repaint);
597}
598
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400599static void
Jason Ekstranda7af7042013-10-12 22:38:11 -0500600repaint_views(struct weston_output *output, pixman_region32_t *damage)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400601{
602 struct weston_compositor *compositor = output->compositor;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500603 struct weston_view *view;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400604
Jason Ekstranda7af7042013-10-12 22:38:11 -0500605 wl_list_for_each_reverse(view, &compositor->view_list, link)
606 if (view->plane == &compositor->primary_plane)
607 draw_view(view, output, damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400608}
609
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500610static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600611draw_output_border_texture(struct gl_output_state *go,
612 enum gl_renderer_border_side side,
613 int32_t x, int32_t y,
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500614 int32_t width, int32_t height)
615{
Jason Ekstrande5512d42014-02-04 21:36:38 -0600616 struct gl_border_image *img = &go->borders[side];
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500617 static GLushort indices [] = { 0, 1, 3, 3, 1, 2 };
618
619 if (!img->data) {
620 if (img->tex) {
621 glDeleteTextures(1, &img->tex);
622 img->tex = 0;
623 }
624
625 return;
626 }
627
628 if (!img->tex) {
629 glGenTextures(1, &img->tex);
630 glBindTexture(GL_TEXTURE_2D, img->tex);
631
632 glTexParameteri(GL_TEXTURE_2D,
633 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
634 glTexParameteri(GL_TEXTURE_2D,
635 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
636 glTexParameteri(GL_TEXTURE_2D,
637 GL_TEXTURE_MIN_FILTER, GL_NEAREST);
638 glTexParameteri(GL_TEXTURE_2D,
639 GL_TEXTURE_MAG_FILTER, GL_NEAREST);
640 } else {
641 glBindTexture(GL_TEXTURE_2D, img->tex);
642 }
643
Jason Ekstrande5512d42014-02-04 21:36:38 -0600644 if (go->border_status & (1 << side)) {
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500645#ifdef GL_EXT_unpack_subimage
646 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
647 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
648 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
649#endif
650 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
651 img->tex_width, img->height, 0,
652 GL_BGRA_EXT, GL_UNSIGNED_BYTE, img->data);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500653 }
654
655 GLfloat texcoord[] = {
656 0.0f, 0.0f,
657 (GLfloat)img->width / (GLfloat)img->tex_width, 0.0f,
658 (GLfloat)img->width / (GLfloat)img->tex_width, 1.0f,
659 0.0f, 1.0f,
660 };
661
662 GLfloat verts[] = {
663 x, y,
664 x + width, y,
665 x + width, y + height,
666 x, y + height
667 };
668
669 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
670 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
671 glEnableVertexAttribArray(0);
672 glEnableVertexAttribArray(1);
673
674 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
675
676 glDisableVertexAttribArray(1);
677 glDisableVertexAttribArray(0);
678}
679
680static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600681draw_output_borders(struct weston_output *output,
682 enum gl_border_status border_status)
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500683{
684 struct gl_output_state *go = get_output_state(output);
685 struct gl_renderer *gr = get_renderer(output->compositor);
686 struct gl_shader *shader = &gr->texture_shader_rgba;
Jason Ekstrand00b84282013-10-27 22:24:59 -0500687 struct gl_border_image *top, *bottom, *left, *right;
688 struct weston_matrix matrix;
689 int full_width, full_height;
690
Jason Ekstrande5512d42014-02-04 21:36:38 -0600691 if (border_status == BORDER_STATUS_CLEAN)
692 return; /* Clean. Nothing to do. */
693
Jason Ekstrand00b84282013-10-27 22:24:59 -0500694 top = &go->borders[GL_RENDERER_BORDER_TOP];
695 bottom = &go->borders[GL_RENDERER_BORDER_BOTTOM];
696 left = &go->borders[GL_RENDERER_BORDER_LEFT];
697 right = &go->borders[GL_RENDERER_BORDER_RIGHT];
698
699 full_width = output->current_mode->width + left->width + right->width;
700 full_height = output->current_mode->height + top->height + bottom->height;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500701
702 glDisable(GL_BLEND);
703 use_shader(gr, shader);
704
Jason Ekstrand00b84282013-10-27 22:24:59 -0500705 glViewport(0, 0, full_width, full_height);
706
707 weston_matrix_init(&matrix);
708 weston_matrix_translate(&matrix, -full_width/2.0, -full_height/2.0, 0);
709 weston_matrix_scale(&matrix, 2.0/full_width, -2.0/full_height, 1);
710 glUniformMatrix4fv(shader->proj_uniform, 1, GL_FALSE, matrix.d);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500711
712 glUniform1i(shader->tex_uniforms[0], 0);
713 glUniform1f(shader->alpha_uniform, 1);
714 glActiveTexture(GL_TEXTURE0);
715
Jason Ekstrande5512d42014-02-04 21:36:38 -0600716 if (border_status & BORDER_TOP_DIRTY)
717 draw_output_border_texture(go, GL_RENDERER_BORDER_TOP,
718 0, 0,
719 full_width, top->height);
720 if (border_status & BORDER_LEFT_DIRTY)
721 draw_output_border_texture(go, GL_RENDERER_BORDER_LEFT,
722 0, top->height,
723 left->width, output->current_mode->height);
724 if (border_status & BORDER_RIGHT_DIRTY)
725 draw_output_border_texture(go, GL_RENDERER_BORDER_RIGHT,
726 full_width - right->width, top->height,
727 right->width, output->current_mode->height);
728 if (border_status & BORDER_BOTTOM_DIRTY)
729 draw_output_border_texture(go, GL_RENDERER_BORDER_BOTTOM,
730 0, full_height - bottom->height,
731 full_width, bottom->height);
Jason Ekstrand0b61bf42013-10-27 22:24:54 -0500732}
John Kåre Alsaker44154502012-11-13 19:10:20 +0100733
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400734static void
Jason Ekstrande5512d42014-02-04 21:36:38 -0600735output_get_damage(struct weston_output *output,
736 pixman_region32_t *buffer_damage, uint32_t *border_damage)
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200737{
738 struct gl_output_state *go = get_output_state(output);
739 struct gl_renderer *gr = get_renderer(output->compositor);
740 EGLint buffer_age = 0;
741 EGLBoolean ret;
742 int i;
743
744 if (gr->has_egl_buffer_age) {
745 ret = eglQuerySurface(gr->egl_display, go->egl_surface,
746 EGL_BUFFER_AGE_EXT, &buffer_age);
747 if (ret == EGL_FALSE) {
748 weston_log("buffer age query failed.\n");
749 gl_renderer_print_egl_error_state();
750 }
751 }
752
Jason Ekstrande5512d42014-02-04 21:36:38 -0600753 if (buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT) {
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200754 pixman_region32_copy(buffer_damage, &output->region);
Jason Ekstrande5512d42014-02-04 21:36:38 -0600755 *border_damage = BORDER_ALL_DIRTY;
756 } else {
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200757 for (i = 0; i < buffer_age - 1; i++)
Jason Ekstrande5512d42014-02-04 21:36:38 -0600758 *border_damage |= go->border_damage[i];
759
760 if (*border_damage & BORDER_SIZE_CHANGED) {
761 /* If we've had a resize, we have to do a full
762 * repaint. */
763 *border_damage |= BORDER_ALL_DIRTY;
764 pixman_region32_copy(buffer_damage, &output->region);
765 } else {
766 for (i = 0; i < buffer_age - 1; i++)
767 pixman_region32_union(buffer_damage,
768 buffer_damage,
769 &go->buffer_damage[i]);
770 }
771 }
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200772}
773
774static void
775output_rotate_damage(struct weston_output *output,
Jason Ekstrande5512d42014-02-04 21:36:38 -0600776 pixman_region32_t *output_damage,
777 enum gl_border_status border_status)
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200778{
779 struct gl_output_state *go = get_output_state(output);
780 struct gl_renderer *gr = get_renderer(output->compositor);
781 int i;
782
783 if (!gr->has_egl_buffer_age)
784 return;
785
Jason Ekstrande5512d42014-02-04 21:36:38 -0600786 for (i = BUFFER_DAMAGE_COUNT - 1; i >= 1; i--) {
787 go->border_damage[i] = go->border_damage[i - 1];
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200788 pixman_region32_copy(&go->buffer_damage[i],
789 &go->buffer_damage[i - 1]);
Jason Ekstrande5512d42014-02-04 21:36:38 -0600790 }
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200791
Jason Ekstrande5512d42014-02-04 21:36:38 -0600792 go->border_damage[0] = border_status;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200793 pixman_region32_copy(&go->buffer_damage[0], output_damage);
794}
795
796static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100797gl_renderer_repaint_output(struct weston_output *output,
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400798 pixman_region32_t *output_damage)
799{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100800 struct gl_output_state *go = get_output_state(output);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400801 struct weston_compositor *compositor = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100802 struct gl_renderer *gr = get_renderer(compositor);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400803 EGLBoolean ret;
804 static int errored;
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200805 pixman_region32_t buffer_damage, total_damage;
Jason Ekstrande5512d42014-02-04 21:36:38 -0600806 enum gl_border_status border_damage = BORDER_STATUS_CLEAN;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400807
Jason Ekstrand00b84282013-10-27 22:24:59 -0500808 /* Calculate the viewport */
809 glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width,
810 go->borders[GL_RENDERER_BORDER_BOTTOM].height,
811 output->current_mode->width,
812 output->current_mode->height);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400813
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100814 if (use_output(output) < 0)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400815 return;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400816
817 /* if debugging, redraw everything outside the damage to clean up
818 * debug lines from the previous draw on this buffer:
819 */
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400820 if (gr->fan_debug) {
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400821 pixman_region32_t undamaged;
822 pixman_region32_init(&undamaged);
823 pixman_region32_subtract(&undamaged, &output->region,
824 output_damage);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400825 gr->fan_debug = 0;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500826 repaint_views(output, &undamaged);
Kristian Høgsberg8799d412013-05-07 10:50:09 -0400827 gr->fan_debug = 1;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400828 pixman_region32_fini(&undamaged);
829 }
830
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200831 pixman_region32_init(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200832 pixman_region32_init(&buffer_damage);
833
Jason Ekstrande5512d42014-02-04 21:36:38 -0600834 output_get_damage(output, &buffer_damage, &border_damage);
835 output_rotate_damage(output, output_damage, go->border_status);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200836
837 pixman_region32_union(&total_damage, &buffer_damage, output_damage);
Jason Ekstrande5512d42014-02-04 21:36:38 -0600838 border_damage |= go->border_status;
Ander Conselvan de Oliveira8ea818f2012-09-14 16:12:03 +0300839
Jason Ekstranda7af7042013-10-12 22:38:11 -0500840 repaint_views(output, &total_damage);
Ander Conselvan de Oliveirab605c062013-03-05 17:30:28 +0200841
842 pixman_region32_fini(&total_damage);
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +0200843 pixman_region32_fini(&buffer_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400844
Jason Ekstrande5512d42014-02-04 21:36:38 -0600845 draw_output_borders(output, border_damage);
John Kåre Alsaker44154502012-11-13 19:10:20 +0100846
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +0200847 pixman_region32_copy(&output->previous_damage, output_damage);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400848 wl_signal_emit(&output->frame_signal, output);
849
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +0100850 ret = eglSwapBuffers(gr->egl_display, go->egl_surface);
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400851 if (ret == EGL_FALSE && !errored) {
852 errored = 1;
853 weston_log("Failed in eglSwapBuffers.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +0200854 gl_renderer_print_egl_error_state();
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400855 }
856
Jason Ekstrande5512d42014-02-04 21:36:38 -0600857 go->border_status = BORDER_STATUS_CLEAN;
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400858}
Kristian Høgsberg25894fc2012-09-05 22:06:26 -0400859
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100860static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100861gl_renderer_read_pixels(struct weston_output *output,
John Kåre Alsakera95b2d62012-11-13 19:10:21 +0100862 pixman_format_code_t format, void *pixels,
863 uint32_t x, uint32_t y,
864 uint32_t width, uint32_t height)
865{
866 GLenum gl_format;
867
868 switch (format) {
869 case PIXMAN_a8r8g8b8:
870 gl_format = GL_BGRA_EXT;
871 break;
872 case PIXMAN_a8b8g8r8:
873 gl_format = GL_RGBA;
874 break;
875 default:
876 return -1;
877 }
878
879 if (use_output(output) < 0)
880 return -1;
881
882 glPixelStorei(GL_PACK_ALIGNMENT, 1);
883 glReadPixels(x, y, width, height, gl_format,
884 GL_UNSIGNED_BYTE, pixels);
885
886 return 0;
887}
888
Kristian Høgsbergfa1be022012-09-05 22:49:55 -0400889static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100890gl_renderer_flush_damage(struct weston_surface *surface)
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400891{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +0100892 struct gl_renderer *gr = get_renderer(surface->compositor);
893 struct gl_surface_state *gs = get_surface_state(surface);
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500894 struct weston_buffer *buffer = gs->buffer_ref.buffer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500895 struct weston_view *view;
896 int texture_used;
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200897 GLenum format;
898 int pixel_type;
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100899
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700900#ifdef GL_EXT_unpack_subimage
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400901 pixman_box32_t *rectangles;
902 void *data;
903 int i, n;
904#endif
905
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200906 pixman_region32_union(&gs->texture_damage,
907 &gs->texture_damage, &surface->damage);
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200908
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200909 if (!buffer)
910 return;
911
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200912 /* Avoid upload, if the texture won't be used this time.
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200913 * We still accumulate the damage in texture_damage, and
914 * hold the reference to the buffer, in case the surface
915 * migrates back to the primary plane.
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200916 */
Jason Ekstranda7af7042013-10-12 22:38:11 -0500917 texture_used = 0;
918 wl_list_for_each(view, &surface->views, surface_link) {
919 if (view->plane == &surface->compositor->primary_plane) {
920 texture_used = 1;
921 break;
922 }
923 }
924 if (!texture_used)
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200925 return;
926
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +0200927 if (!pixman_region32_not_empty(&gs->texture_damage) &&
928 !gs->needs_full_upload)
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200929 goto done;
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200930
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200931 switch (wl_shm_buffer_get_format(buffer->shm_buffer)) {
932 case WL_SHM_FORMAT_XRGB8888:
933 case WL_SHM_FORMAT_ARGB8888:
934 format = GL_BGRA_EXT;
935 pixel_type = GL_UNSIGNED_BYTE;
936 break;
937 case WL_SHM_FORMAT_RGB565:
938 format = GL_RGB;
939 pixel_type = GL_UNSIGNED_SHORT_5_6_5;
940 break;
941 default:
942 weston_log("warning: unknown shm buffer format\n");
943 format = GL_BGRA_EXT;
944 pixel_type = GL_UNSIGNED_BYTE;
945 }
946
John Kåre Alsaker75cc5712012-11-13 19:10:26 +0100947 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400948
John Kåre Alsaker320711d2012-11-13 19:10:27 +0100949 if (!gr->has_unpack_subimage) {
Neil Robertse5051712013-11-13 15:44:06 +0000950 wl_shm_buffer_begin_access(buffer->shm_buffer);
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200951 glTexImage2D(GL_TEXTURE_2D, 0, format,
Pekka Paalanen68033ac2012-12-04 15:58:15 +0200952 gs->pitch, buffer->height, 0,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200953 format, pixel_type,
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500954 wl_shm_buffer_get_data(buffer->shm_buffer));
Neil Robertse5051712013-11-13 15:44:06 +0000955 wl_shm_buffer_end_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400956
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200957 goto done;
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400958 }
959
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700960#ifdef GL_EXT_unpack_subimage
961 glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, gs->pitch);
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500962 data = wl_shm_buffer_get_data(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300963
964 if (gs->needs_full_upload) {
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700965 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
966 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
Neil Robertse5051712013-11-13 15:44:06 +0000967 wl_shm_buffer_begin_access(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300968 glTexSubImage2D(GL_TEXTURE_2D, 0,
969 0, 0, gs->pitch, buffer->height,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200970 format, pixel_type, data);
Neil Robertse5051712013-11-13 15:44:06 +0000971 wl_shm_buffer_end_access(buffer->shm_buffer);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300972 goto done;
973 }
974
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200975 rectangles = pixman_region32_rectangles(&gs->texture_damage, &n);
Neil Robertse5051712013-11-13 15:44:06 +0000976 wl_shm_buffer_begin_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400977 for (i = 0; i < n; i++) {
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200978 pixman_box32_t r;
979
980 r = weston_surface_to_buffer_rect(surface, rectangles[i]);
981
Kristian Høgsbergce7a5d82013-08-07 09:55:07 -0700982 glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, r.x1);
983 glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
Ander Conselvan de Oliveira0396ba22012-11-28 17:10:26 +0200984 glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
985 r.x2 - r.x1, r.y2 - r.y1,
Tomeu Vizoso12072b62013-08-06 20:05:55 +0200986 format, pixel_type, data);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400987 }
Neil Robertse5051712013-11-13 15:44:06 +0000988 wl_shm_buffer_end_access(buffer->shm_buffer);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400989#endif
Pekka Paalanenbcdd5792012-11-07 12:25:13 +0200990
991done:
Pekka Paalanen81ee3f52012-12-04 15:58:16 +0200992 pixman_region32_fini(&gs->texture_damage);
993 pixman_region32_init(&gs->texture_damage);
Ander Conselvan de Oliveira6be5f432013-06-07 16:52:45 +0300994 gs->needs_full_upload = 0;
Pekka Paalanenfb003d32012-12-04 15:58:13 +0200995
996 weston_buffer_reference(&gs->buffer_ref, NULL);
Kristian Høgsbergb1fd2d62012-09-05 22:13:58 -0400997}
998
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -0400999static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001000ensure_textures(struct gl_surface_state *gs, int num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001001{
1002 int i;
1003
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001004 if (num_textures <= gs->num_textures)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001005 return;
1006
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001007 for (i = gs->num_textures; i < num_textures; i++) {
1008 glGenTextures(1, &gs->textures[i]);
1009 glBindTexture(gs->target, gs->textures[i]);
1010 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001011 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001012 glTexParameteri(gs->target,
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001013 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1014 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001015 gs->num_textures = num_textures;
1016 glBindTexture(gs->target, 0);
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001017}
1018
Kristian Høgsbergfa1be022012-09-05 22:49:55 -04001019static void
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001020gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
1021 struct wl_shm_buffer *shm_buffer)
1022{
1023 struct weston_compositor *ec = es->compositor;
1024 struct gl_renderer *gr = get_renderer(ec);
1025 struct gl_surface_state *gs = get_surface_state(es);
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001026 int pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001027
1028 buffer->shm_buffer = shm_buffer;
1029 buffer->width = wl_shm_buffer_get_width(shm_buffer);
1030 buffer->height = wl_shm_buffer_get_height(shm_buffer);
1031
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001032 switch (wl_shm_buffer_get_format(shm_buffer)) {
1033 case WL_SHM_FORMAT_XRGB8888:
1034 gs->shader = &gr->texture_shader_rgbx;
1035 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
1036 break;
1037 case WL_SHM_FORMAT_ARGB8888:
1038 gs->shader = &gr->texture_shader_rgba;
1039 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
1040 break;
1041 case WL_SHM_FORMAT_RGB565:
1042 gs->shader = &gr->texture_shader_rgbx;
1043 pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
1044 break;
1045 default:
1046 weston_log("warning: unknown shm buffer format\n");
1047 gs->shader = &gr->texture_shader_rgba;
1048 pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
1049 }
1050
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001051 /* Only allocate a texture if it doesn't match existing one.
1052 * If a switch from DRM allocated buffer to a SHM buffer is
1053 * happening, we need to allocate a new texture buffer. */
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001054 if (pitch != gs->pitch ||
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001055 buffer->height != gs->height ||
1056 gs->buffer_type != BUFFER_TYPE_SHM) {
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001057 gs->pitch = pitch;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001058 gs->height = buffer->height;
1059 gs->target = GL_TEXTURE_2D;
1060 gs->buffer_type = BUFFER_TYPE_SHM;
1061 gs->needs_full_upload = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001062 gs->y_inverted = 1;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001063
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001064 gs->surface = es;
1065
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001066 ensure_textures(gs, 1);
1067 glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
1068 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
1069 gs->pitch, buffer->height, 0,
1070 GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1071 }
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001072}
1073
1074static void
1075gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
1076 uint32_t format)
1077{
1078 struct weston_compositor *ec = es->compositor;
1079 struct gl_renderer *gr = get_renderer(ec);
1080 struct gl_surface_state *gs = get_surface_state(es);
1081 EGLint attribs[3];
1082 int i, num_planes;
1083
1084 buffer->legacy_buffer = (struct wl_buffer *)buffer->resource;
1085 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1086 EGL_WIDTH, &buffer->width);
1087 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1088 EGL_HEIGHT, &buffer->height);
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001089 gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
1090 EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001091
1092 for (i = 0; i < gs->num_images; i++)
1093 gr->destroy_image(gr->egl_display, gs->images[i]);
1094 gs->num_images = 0;
1095 gs->target = GL_TEXTURE_2D;
1096 switch (format) {
1097 case EGL_TEXTURE_RGB:
1098 case EGL_TEXTURE_RGBA:
1099 default:
1100 num_planes = 1;
1101 gs->shader = &gr->texture_shader_rgba;
1102 break;
1103 case EGL_TEXTURE_EXTERNAL_WL:
1104 num_planes = 1;
1105 gs->target = GL_TEXTURE_EXTERNAL_OES;
1106 gs->shader = &gr->texture_shader_egl_external;
1107 break;
1108 case EGL_TEXTURE_Y_UV_WL:
1109 num_planes = 2;
1110 gs->shader = &gr->texture_shader_y_uv;
1111 break;
1112 case EGL_TEXTURE_Y_U_V_WL:
1113 num_planes = 3;
1114 gs->shader = &gr->texture_shader_y_u_v;
1115 break;
1116 case EGL_TEXTURE_Y_XUXV_WL:
1117 num_planes = 2;
1118 gs->shader = &gr->texture_shader_y_xuxv;
1119 break;
1120 }
1121
1122 ensure_textures(gs, num_planes);
1123 for (i = 0; i < num_planes; i++) {
1124 attribs[0] = EGL_WAYLAND_PLANE_WL;
1125 attribs[1] = i;
1126 attribs[2] = EGL_NONE;
1127 gs->images[i] = gr->create_image(gr->egl_display,
1128 NULL,
1129 EGL_WAYLAND_BUFFER_WL,
1130 buffer->legacy_buffer,
1131 attribs);
1132 if (!gs->images[i]) {
1133 weston_log("failed to create img for plane %d\n", i);
1134 continue;
1135 }
1136 gs->num_images++;
1137
1138 glActiveTexture(GL_TEXTURE0 + i);
1139 glBindTexture(gs->target, gs->textures[i]);
1140 gr->image_target_texture_2d(gs->target,
1141 gs->images[i]);
1142 }
1143
1144 gs->pitch = buffer->width;
1145 gs->height = buffer->height;
1146 gs->buffer_type = BUFFER_TYPE_EGL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001147 gs->y_inverted = buffer->y_inverted;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001148}
1149
1150static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001151gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001152{
1153 struct weston_compositor *ec = es->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001154 struct gl_renderer *gr = get_renderer(ec);
1155 struct gl_surface_state *gs = get_surface_state(es);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001156 struct wl_shm_buffer *shm_buffer;
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001157 EGLint format;
1158 int i;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001159
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001160 weston_buffer_reference(&gs->buffer_ref, buffer);
1161
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001162 if (!buffer) {
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001163 for (i = 0; i < gs->num_images; i++) {
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001164 gr->destroy_image(gr->egl_display, gs->images[i]);
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001165 gs->images[i] = NULL;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001166 }
John Kåre Alsaker75cc5712012-11-13 19:10:26 +01001167 gs->num_images = 0;
1168 glDeleteTextures(gs->num_textures, gs->textures);
1169 gs->num_textures = 0;
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001170 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001171 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001172 return;
1173 }
1174
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001175 shm_buffer = wl_shm_buffer_get(buffer->resource);
Jason Ekstrand6bd62942013-06-20 20:38:23 -05001176
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001177 if (shm_buffer)
1178 gl_renderer_attach_shm(es, buffer, shm_buffer);
Kristian Høgsberg47229392013-08-07 11:59:54 -07001179 else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource,
Ander Conselvan de Oliveira047e9b92013-06-07 16:52:46 +03001180 EGL_TEXTURE_FORMAT, &format))
1181 gl_renderer_attach_egl(es, buffer, format);
1182 else {
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001183 weston_log("unhandled buffer type!\n");
Pekka Paalanenfb003d32012-12-04 15:58:13 +02001184 weston_buffer_reference(&gs->buffer_ref, NULL);
Ander Conselvan de Oliveiraa9bf1612013-06-07 16:52:44 +03001185 gs->buffer_type = BUFFER_TYPE_NULL;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001186 gs->y_inverted = 1;
Kristian Høgsbergb7b77e62012-09-05 22:38:18 -04001187 }
1188}
1189
Kristian Høgsberg42263852012-09-06 21:59:29 -04001190static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001191gl_renderer_surface_set_color(struct weston_surface *surface,
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001192 float red, float green, float blue, float alpha)
1193{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001194 struct gl_surface_state *gs = get_surface_state(surface);
1195 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001196
1197 gs->color[0] = red;
1198 gs->color[1] = green;
1199 gs->color[2] = blue;
1200 gs->color[3] = alpha;
1201
John Kåre Alsaker40684142012-11-13 19:10:25 +01001202 gs->shader = &gr->solid_shader;
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001203}
1204
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001205static void
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001206surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001207{
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001208 int i;
1209
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001210 wl_list_remove(&gs->surface_destroy_listener.link);
1211 wl_list_remove(&gs->renderer_destroy_listener.link);
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001212
1213 gs->surface->renderer_state = NULL;
1214
1215 glDeleteTextures(gs->num_textures, gs->textures);
1216
1217 for (i = 0; i < gs->num_images; i++)
1218 gr->destroy_image(gr->egl_display, gs->images[i]);
1219
1220 weston_buffer_reference(&gs->buffer_ref, NULL);
1221 pixman_region32_fini(&gs->texture_damage);
1222 free(gs);
1223}
1224
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001225static void
1226surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
1227{
1228 struct gl_surface_state *gs;
1229 struct gl_renderer *gr;
1230
1231 gs = container_of(listener, struct gl_surface_state,
1232 surface_destroy_listener);
1233
1234 gr = get_renderer(gs->surface->compositor);
1235
1236 surface_state_destroy(gs, gr);
1237}
1238
1239static void
1240surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
1241{
1242 struct gl_surface_state *gs;
1243 struct gl_renderer *gr;
1244
1245 gr = data;
1246
1247 gs = container_of(listener, struct gl_surface_state,
1248 renderer_destroy_listener);
1249
1250 surface_state_destroy(gs, gr);
1251}
1252
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001253static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001254gl_renderer_create_surface(struct weston_surface *surface)
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001255{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001256 struct gl_surface_state *gs;
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001257 struct gl_renderer *gr = get_renderer(surface->compositor);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001258
1259 gs = calloc(1, sizeof *gs);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001260 if (!gs)
1261 return -1;
1262
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001263 /* A buffer is never attached to solid color surfaces, yet
1264 * they still go through texcoord computations. Do not divide
1265 * by zero there.
1266 */
1267 gs->pitch = 1;
Stanislav Vorobiovbfbb8e52013-08-29 11:36:44 +04001268 gs->y_inverted = 1;
Pekka Paalanen68033ac2012-12-04 15:58:15 +02001269
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001270 gs->surface = surface;
1271
Pekka Paalanen81ee3f52012-12-04 15:58:16 +02001272 pixman_region32_init(&gs->texture_damage);
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001273 surface->renderer_state = gs;
1274
Ander Conselvan de Oliveiraaa398ae2013-10-25 16:26:33 +03001275 gs->surface_destroy_listener.notify =
1276 surface_state_handle_surface_destroy;
1277 wl_signal_add(&surface->destroy_signal,
1278 &gs->surface_destroy_listener);
1279
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001280 gs->renderer_destroy_listener.notify =
1281 surface_state_handle_renderer_destroy;
1282 wl_signal_add(&gr->destroy_signal,
1283 &gs->renderer_destroy_listener);
1284
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02001285 if (surface->buffer_ref.buffer) {
1286 gl_renderer_attach(surface, surface->buffer_ref.buffer);
1287 gl_renderer_flush_damage(surface);
1288 }
1289
John Kåre Alsaker878f4492012-11-13 19:10:23 +01001290 return 0;
1291}
1292
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001293static const char vertex_shader[] =
1294 "uniform mat4 proj;\n"
1295 "attribute vec2 position;\n"
1296 "attribute vec2 texcoord;\n"
1297 "varying vec2 v_texcoord;\n"
1298 "void main()\n"
1299 "{\n"
1300 " gl_Position = proj * vec4(position, 0.0, 1.0);\n"
1301 " v_texcoord = texcoord;\n"
1302 "}\n";
1303
1304/* Declare common fragment shader uniforms */
1305#define FRAGMENT_CONVERT_YUV \
1306 " y *= alpha;\n" \
1307 " u *= alpha;\n" \
1308 " v *= alpha;\n" \
1309 " gl_FragColor.r = y + 1.59602678 * v;\n" \
1310 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
1311 " gl_FragColor.b = y + 2.01723214 * u;\n" \
1312 " gl_FragColor.a = alpha;\n"
1313
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001314static const char fragment_debug[] =
1315 " gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
1316
1317static const char fragment_brace[] =
1318 "}\n";
1319
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001320static const char texture_fragment_shader_rgba[] =
1321 "precision mediump float;\n"
1322 "varying vec2 v_texcoord;\n"
1323 "uniform sampler2D tex;\n"
1324 "uniform float alpha;\n"
1325 "void main()\n"
1326 "{\n"
1327 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001328 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001329
1330static const char texture_fragment_shader_rgbx[] =
1331 "precision mediump float;\n"
1332 "varying vec2 v_texcoord;\n"
1333 "uniform sampler2D tex;\n"
1334 "uniform float alpha;\n"
1335 "void main()\n"
1336 "{\n"
1337 " gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
1338 " gl_FragColor.a = alpha;\n"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001339 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001340
1341static const char texture_fragment_shader_egl_external[] =
1342 "#extension GL_OES_EGL_image_external : require\n"
1343 "precision mediump float;\n"
1344 "varying vec2 v_texcoord;\n"
1345 "uniform samplerExternalOES tex;\n"
1346 "uniform float alpha;\n"
1347 "void main()\n"
1348 "{\n"
1349 " gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001350 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001351
1352static const char texture_fragment_shader_y_uv[] =
1353 "precision mediump float;\n"
1354 "uniform sampler2D tex;\n"
1355 "uniform sampler2D tex1;\n"
1356 "varying vec2 v_texcoord;\n"
1357 "uniform float alpha;\n"
1358 "void main() {\n"
1359 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1360 " float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
1361 " float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
1362 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001363 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001364
1365static const char texture_fragment_shader_y_u_v[] =
1366 "precision mediump float;\n"
1367 "uniform sampler2D tex;\n"
1368 "uniform sampler2D tex1;\n"
1369 "uniform sampler2D tex2;\n"
1370 "varying vec2 v_texcoord;\n"
1371 "uniform float alpha;\n"
1372 "void main() {\n"
1373 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1374 " float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
1375 " float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
1376 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001377 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001378
1379static const char texture_fragment_shader_y_xuxv[] =
1380 "precision mediump float;\n"
1381 "uniform sampler2D tex;\n"
1382 "uniform sampler2D tex1;\n"
1383 "varying vec2 v_texcoord;\n"
1384 "uniform float alpha;\n"
1385 "void main() {\n"
1386 " float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
1387 " float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
1388 " float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
1389 FRAGMENT_CONVERT_YUV
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001390 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001391
1392static const char solid_fragment_shader[] =
1393 "precision mediump float;\n"
1394 "uniform vec4 color;\n"
1395 "uniform float alpha;\n"
1396 "void main()\n"
1397 "{\n"
1398 " gl_FragColor = alpha * color\n;"
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001399 ;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001400
1401static int
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001402compile_shader(GLenum type, int count, const char **sources)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001403{
1404 GLuint s;
1405 char msg[512];
1406 GLint status;
1407
1408 s = glCreateShader(type);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001409 glShaderSource(s, count, sources, NULL);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001410 glCompileShader(s);
1411 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
1412 if (!status) {
1413 glGetShaderInfoLog(s, sizeof msg, NULL, msg);
1414 weston_log("shader info: %s\n", msg);
1415 return GL_NONE;
1416 }
1417
1418 return s;
1419}
1420
1421static int
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001422shader_init(struct gl_shader *shader, struct gl_renderer *renderer,
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001423 const char *vertex_source, const char *fragment_source)
1424{
1425 char msg[512];
1426 GLint status;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001427 int count;
1428 const char *sources[3];
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001429
1430 shader->vertex_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001431 compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
1432
1433 if (renderer->fragment_shader_debug) {
1434 sources[0] = fragment_source;
1435 sources[1] = fragment_debug;
1436 sources[2] = fragment_brace;
1437 count = 3;
1438 } else {
1439 sources[0] = fragment_source;
1440 sources[1] = fragment_brace;
1441 count = 2;
1442 }
1443
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001444 shader->fragment_shader =
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001445 compile_shader(GL_FRAGMENT_SHADER, count, sources);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001446
1447 shader->program = glCreateProgram();
1448 glAttachShader(shader->program, shader->vertex_shader);
1449 glAttachShader(shader->program, shader->fragment_shader);
1450 glBindAttribLocation(shader->program, 0, "position");
1451 glBindAttribLocation(shader->program, 1, "texcoord");
1452
1453 glLinkProgram(shader->program);
1454 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
1455 if (!status) {
1456 glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
1457 weston_log("link info: %s\n", msg);
1458 return -1;
1459 }
1460
1461 shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
1462 shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
1463 shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
1464 shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
1465 shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
1466 shader->color_uniform = glGetUniformLocation(shader->program, "color");
1467
1468 return 0;
1469}
1470
1471static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001472shader_release(struct gl_shader *shader)
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001473{
1474 glDeleteShader(shader->vertex_shader);
1475 glDeleteShader(shader->fragment_shader);
1476 glDeleteProgram(shader->program);
1477
1478 shader->vertex_shader = 0;
1479 shader->fragment_shader = 0;
1480 shader->program = 0;
1481}
1482
1483static void
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001484log_extensions(const char *name, const char *extensions)
1485{
1486 const char *p, *end;
1487 int l;
1488 int len;
1489
1490 l = weston_log("%s:", name);
1491 p = extensions;
1492 while (*p) {
1493 end = strchrnul(p, ' ');
1494 len = end - p;
1495 if (l + len > 78)
1496 l = weston_log_continue("\n" STAMP_SPACE "%.*s",
1497 len, p);
1498 else
1499 l += weston_log_continue(" %.*s", len, p);
1500 for (p = end; isspace(*p); p++)
1501 ;
1502 }
1503 weston_log_continue("\n");
1504}
1505
1506static void
1507log_egl_gl_info(EGLDisplay egldpy)
1508{
1509 const char *str;
1510
1511 str = eglQueryString(egldpy, EGL_VERSION);
1512 weston_log("EGL version: %s\n", str ? str : "(null)");
1513
1514 str = eglQueryString(egldpy, EGL_VENDOR);
1515 weston_log("EGL vendor: %s\n", str ? str : "(null)");
1516
1517 str = eglQueryString(egldpy, EGL_CLIENT_APIS);
1518 weston_log("EGL client APIs: %s\n", str ? str : "(null)");
1519
1520 str = eglQueryString(egldpy, EGL_EXTENSIONS);
1521 log_extensions("EGL extensions", str ? str : "(null)");
1522
1523 str = (char *)glGetString(GL_VERSION);
1524 weston_log("GL version: %s\n", str ? str : "(null)");
1525
1526 str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1527 weston_log("GLSL version: %s\n", str ? str : "(null)");
1528
1529 str = (char *)glGetString(GL_VENDOR);
1530 weston_log("GL vendor: %s\n", str ? str : "(null)");
1531
1532 str = (char *)glGetString(GL_RENDERER);
1533 weston_log("GL renderer: %s\n", str ? str : "(null)");
1534
1535 str = (char *)glGetString(GL_EXTENSIONS);
1536 log_extensions("GL extensions", str ? str : "(null)");
1537}
1538
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001539static void
1540log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
1541{
1542 EGLint r, g, b, a;
1543
1544 weston_log("Chosen EGL config details:\n");
1545
1546 weston_log_continue(STAMP_SPACE "RGBA bits");
1547 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_RED_SIZE, &r) &&
1548 eglGetConfigAttrib(egldpy, eglconfig, EGL_GREEN_SIZE, &g) &&
1549 eglGetConfigAttrib(egldpy, eglconfig, EGL_BLUE_SIZE, &b) &&
1550 eglGetConfigAttrib(egldpy, eglconfig, EGL_ALPHA_SIZE, &a))
1551 weston_log_continue(": %d %d %d %d\n", r, g, b, a);
1552 else
1553 weston_log_continue(" unknown\n");
1554
1555 weston_log_continue(STAMP_SPACE "swap interval range");
1556 if (eglGetConfigAttrib(egldpy, eglconfig, EGL_MIN_SWAP_INTERVAL, &a) &&
1557 eglGetConfigAttrib(egldpy, eglconfig, EGL_MAX_SWAP_INTERVAL, &b))
1558 weston_log_continue(": %d - %d\n", a, b);
1559 else
1560 weston_log_continue(" unknown\n");
1561}
1562
John Kåre Alsaker44154502012-11-13 19:10:20 +01001563static void
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05001564gl_renderer_output_set_border(struct weston_output *output,
1565 enum gl_renderer_border_side side,
1566 int32_t width, int32_t height,
1567 int32_t tex_width, unsigned char *data)
1568{
1569 struct gl_output_state *go = get_output_state(output);
1570
Jason Ekstrande5512d42014-02-04 21:36:38 -06001571 if (go->borders[side].width != width ||
1572 go->borders[side].height != height)
1573 /* In this case, we have to blow everything and do a full
1574 * repaint. */
1575 go->border_status |= BORDER_SIZE_CHANGED | BORDER_ALL_DIRTY;
1576
1577 if (data == NULL) {
1578 width = 0;
1579 height = 0;
1580 }
1581
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05001582 go->borders[side].width = width;
1583 go->borders[side].height = height;
1584 go->borders[side].tex_width = tex_width;
1585 go->borders[side].data = data;
Jason Ekstrande5512d42014-02-04 21:36:38 -06001586 go->border_status |= 1 << side;
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05001587}
1588
John Kåre Alsaker94659272012-11-13 19:10:18 +01001589static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001590gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001591
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001592static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001593gl_renderer_output_create(struct weston_output *output,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001594 EGLNativeWindowType window)
1595{
1596 struct weston_compositor *ec = output->compositor;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001597 struct gl_renderer *gr = get_renderer(ec);
1598 struct gl_output_state *go = calloc(1, sizeof *go);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001599 int i;
John Kåre Alsaker94659272012-11-13 19:10:18 +01001600
1601 if (!go)
1602 return -1;
1603
1604 go->egl_surface =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001605 eglCreateWindowSurface(gr->egl_display,
1606 gr->egl_config,
John Kåre Alsaker94659272012-11-13 19:10:18 +01001607 window, NULL);
1608
1609 if (go->egl_surface == EGL_NO_SURFACE) {
1610 weston_log("failed to create egl surface\n");
1611 free(go);
1612 return -1;
1613 }
1614
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001615 if (gr->egl_context == NULL)
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001616 if (gl_renderer_setup(ec, go->egl_surface) < 0) {
John Kåre Alsaker94659272012-11-13 19:10:18 +01001617 free(go);
1618 return -1;
1619 }
1620
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001621 for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001622 pixman_region32_init(&go->buffer_damage[i]);
1623
John Kåre Alsaker94659272012-11-13 19:10:18 +01001624 output->renderer_state = go;
1625
1626 return 0;
1627}
1628
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001629static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001630gl_renderer_output_destroy(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001631{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001632 struct gl_renderer *gr = get_renderer(output->compositor);
1633 struct gl_output_state *go = get_output_state(output);
Ander Conselvan de Oliveirab8fcca92012-11-16 17:23:52 +02001634 int i;
1635
1636 for (i = 0; i < 2; i++)
1637 pixman_region32_fini(&go->buffer_damage[i]);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001638
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001639 eglDestroySurface(gr->egl_display, go->egl_surface);
John Kåre Alsaker94659272012-11-13 19:10:18 +01001640
1641 free(go);
1642}
1643
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001644static EGLSurface
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001645gl_renderer_output_surface(struct weston_output *output)
John Kåre Alsaker94659272012-11-13 19:10:18 +01001646{
1647 return get_output_state(output)->egl_surface;
1648}
1649
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001650static void
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001651gl_renderer_destroy(struct weston_compositor *ec)
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001652{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001653 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001654
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001655 wl_signal_emit(&gr->destroy_signal, gr);
1656
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001657 if (gr->has_bind_display)
1658 gr->unbind_display(gr->egl_display, ec->wl_display);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001659
1660 /* Work around crash in egl_dri2.c's dri2_make_current() - when does this apply? */
1661 eglMakeCurrent(gr->egl_display,
1662 EGL_NO_SURFACE, EGL_NO_SURFACE,
1663 EGL_NO_CONTEXT);
1664
1665 eglTerminate(gr->egl_display);
1666 eglReleaseThread();
Scott Moreau976a0502013-03-07 10:15:17 -07001667
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04001668 wl_array_release(&gr->vertices);
Kristian Høgsberg7b9195f2013-05-08 22:38:05 -04001669 wl_array_release(&gr->vtxcnt);
1670
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03001671 weston_binding_destroy(gr->fragment_binding);
1672 weston_binding_destroy(gr->fan_binding);
1673
Scott Moreau976a0502013-03-07 10:15:17 -07001674 free(gr);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001675}
1676
1677static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001678egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001679 const EGLint *visual_id)
1680{
1681 EGLint count = 0;
1682 EGLint matched = 0;
1683 EGLConfig *configs;
1684 int i;
1685
1686 if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
1687 return -1;
1688
1689 configs = calloc(count, sizeof *configs);
1690 if (!configs)
1691 return -1;
1692
1693 if (!eglChooseConfig(gr->egl_display, attribs, configs,
1694 count, &matched))
1695 goto out;
1696
1697 for (i = 0; i < matched; ++i) {
1698 EGLint id;
1699
1700 if (visual_id) {
1701 if (!eglGetConfigAttrib(gr->egl_display,
1702 configs[i], EGL_NATIVE_VISUAL_ID,
1703 &id))
1704 continue;
1705
Kristian Høgsbergc3ea26c2013-09-25 15:46:42 -07001706 if (id != 0 && id != *visual_id)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001707 continue;
1708 }
1709
1710 gr->egl_config = configs[i];
1711
1712 free(configs);
1713 return 0;
1714 }
1715
1716out:
1717 free(configs);
1718 return -1;
1719}
1720
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001721static const EGLint gl_renderer_opaque_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001722 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1723 EGL_RED_SIZE, 1,
1724 EGL_GREEN_SIZE, 1,
1725 EGL_BLUE_SIZE, 1,
1726 EGL_ALPHA_SIZE, 0,
1727 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1728 EGL_NONE
1729};
1730
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001731static const EGLint gl_renderer_alpha_attribs[] = {
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001732 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
1733 EGL_RED_SIZE, 1,
1734 EGL_GREEN_SIZE, 1,
1735 EGL_BLUE_SIZE, 1,
1736 EGL_ALPHA_SIZE, 1,
1737 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
1738 EGL_NONE
1739};
1740
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001741static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001742gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001743 const EGLint *attribs, const EGLint *visual_id)
1744{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001745 struct gl_renderer *gr;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001746 EGLint major, minor;
1747
1748 gr = calloc(1, sizeof *gr);
1749
1750 if (gr == NULL)
1751 return -1;
1752
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001753 gr->base.read_pixels = gl_renderer_read_pixels;
1754 gr->base.repaint_output = gl_renderer_repaint_output;
1755 gr->base.flush_damage = gl_renderer_flush_damage;
1756 gr->base.attach = gl_renderer_attach;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001757 gr->base.surface_set_color = gl_renderer_surface_set_color;
Vasily Khoruzhick52cfd612013-01-08 19:09:01 +03001758 gr->base.destroy = gl_renderer_destroy;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001759
1760 gr->egl_display = eglGetDisplay(display);
1761 if (gr->egl_display == EGL_NO_DISPLAY) {
1762 weston_log("failed to create display\n");
1763 goto err_egl;
1764 }
1765
1766 if (!eglInitialize(gr->egl_display, &major, &minor)) {
1767 weston_log("failed to initialize display\n");
1768 goto err_egl;
1769 }
1770
1771 if (egl_choose_config(gr, attribs, visual_id) < 0) {
1772 weston_log("failed to choose EGL config\n");
1773 goto err_egl;
1774 }
1775
1776 ec->renderer = &gr->base;
Pekka Paalanen7bb65102013-05-22 18:03:04 +03001777 ec->capabilities |= WESTON_CAP_ROTATION_ANY;
Pekka Paalanen4fc5dd02013-05-22 18:03:05 +03001778 ec->capabilities |= WESTON_CAP_CAPTURE_YFLIP;
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001779
Tomeu Vizoso12072b62013-08-06 20:05:55 +02001780 wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
1781
Ander Conselvan de Oliveiraadda00e2013-10-25 16:26:34 +03001782 wl_signal_init(&gr->destroy_signal);
1783
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001784 return 0;
1785
1786err_egl:
Pekka Paalanen326529f2012-11-27 12:25:25 +02001787 gl_renderer_print_egl_error_state();
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001788 free(gr);
1789 return -1;
1790}
1791
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001792static EGLDisplay
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001793gl_renderer_display(struct weston_compositor *ec)
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001794{
1795 return get_renderer(ec)->egl_display;
Kristian Høgsberg3a0de882012-09-06 21:44:24 -04001796}
1797
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001798static int
1799compile_shaders(struct weston_compositor *ec)
1800{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001801 struct gl_renderer *gr = get_renderer(ec);
John Kåre Alsaker40684142012-11-13 19:10:25 +01001802
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001803 gr->texture_shader_rgba.vertex_source = vertex_shader;
1804 gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba;
1805
1806 gr->texture_shader_rgbx.vertex_source = vertex_shader;
1807 gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx;
1808
1809 gr->texture_shader_egl_external.vertex_source = vertex_shader;
1810 gr->texture_shader_egl_external.fragment_source =
1811 texture_fragment_shader_egl_external;
1812
1813 gr->texture_shader_y_uv.vertex_source = vertex_shader;
1814 gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv;
1815
1816 gr->texture_shader_y_u_v.vertex_source = vertex_shader;
1817 gr->texture_shader_y_u_v.fragment_source =
1818 texture_fragment_shader_y_u_v;
1819
Ander Conselvan de Oliveira41a50ea2013-11-27 17:43:51 +02001820 gr->texture_shader_y_xuxv.vertex_source = vertex_shader;
Ander Conselvan de Oliveira1ed73242013-05-17 14:00:40 +03001821 gr->texture_shader_y_xuxv.fragment_source =
1822 texture_fragment_shader_y_xuxv;
1823
1824 gr->solid_shader.vertex_source = vertex_shader;
1825 gr->solid_shader.fragment_source = solid_fragment_shader;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001826
1827 return 0;
1828}
1829
1830static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001831fragment_debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001832 void *data)
1833{
1834 struct weston_compositor *ec = data;
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001835 struct gl_renderer *gr = get_renderer(ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001836 struct weston_output *output;
1837
John Kåre Alsaker40684142012-11-13 19:10:25 +01001838 gr->fragment_shader_debug ^= 1;
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001839
John Kåre Alsaker40684142012-11-13 19:10:25 +01001840 shader_release(&gr->texture_shader_rgba);
1841 shader_release(&gr->texture_shader_rgbx);
1842 shader_release(&gr->texture_shader_egl_external);
1843 shader_release(&gr->texture_shader_y_uv);
1844 shader_release(&gr->texture_shader_y_u_v);
1845 shader_release(&gr->texture_shader_y_xuxv);
1846 shader_release(&gr->solid_shader);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001847
Ander Conselvan de Oliveira03fb4ef2012-12-03 17:08:11 +02001848 /* Force use_shader() to call glUseProgram(), since we need to use
1849 * the recompiled version of the shader. */
1850 gr->current_shader = NULL;
1851
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001852 wl_list_for_each(output, &ec->output_list, link)
1853 weston_output_damage(output);
1854}
1855
Kristian Høgsberg8799d412013-05-07 10:50:09 -04001856static void
1857fan_debug_repaint_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
1858 void *data)
1859{
1860 struct weston_compositor *compositor = data;
1861 struct gl_renderer *gr = get_renderer(compositor);
1862
1863 gr->fan_debug = !gr->fan_debug;
1864 weston_compositor_damage_all(compositor);
1865}
1866
John Kåre Alsaker94659272012-11-13 19:10:18 +01001867static int
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001868gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001869{
John Kåre Alsaker779b52a2012-11-13 19:10:29 +01001870 struct gl_renderer *gr = get_renderer(ec);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001871 const char *extensions;
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001872 EGLBoolean ret;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001873
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001874 static const EGLint context_attribs[] = {
1875 EGL_CONTEXT_CLIENT_VERSION, 2,
1876 EGL_NONE
1877 };
1878
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001879 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
1880 weston_log("failed to bind EGL_OPENGL_ES_API\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001881 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001882 return -1;
1883 }
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001884
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001885 log_egl_config_info(gr->egl_display, gr->egl_config);
Pekka Paalanen9c3fe252012-10-24 09:43:05 +03001886
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001887 gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001888 EGL_NO_CONTEXT, context_attribs);
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001889 if (gr->egl_context == NULL) {
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001890 weston_log("failed to create context\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001891 gl_renderer_print_egl_error_state();
Kristian Høgsberg9793fc72012-09-06 21:07:40 -04001892 return -1;
1893 }
1894
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001895 ret = eglMakeCurrent(gr->egl_display, egl_surface,
1896 egl_surface, gr->egl_context);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001897 if (ret == EGL_FALSE) {
1898 weston_log("Failed to make EGL context current.\n");
Pekka Paalanen326529f2012-11-27 12:25:25 +02001899 gl_renderer_print_egl_error_state();
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04001900 return -1;
1901 }
1902
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001903 log_egl_gl_info(gr->egl_display);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001904
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001905 gr->image_target_texture_2d =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001906 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001907 gr->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1908 gr->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1909 gr->bind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001910 (void *) eglGetProcAddress("eglBindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001911 gr->unbind_display =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001912 (void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001913 gr->query_buffer =
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001914 (void *) eglGetProcAddress("eglQueryWaylandBufferWL");
1915
1916 extensions = (const char *) glGetString(GL_EXTENSIONS);
1917 if (!extensions) {
1918 weston_log("Retrieving GL extension string failed.\n");
1919 return -1;
1920 }
1921
1922 if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
1923 weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
1924 return -1;
1925 }
1926
1927 if (strstr(extensions, "GL_EXT_read_format_bgra"))
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001928 ec->read_format = PIXMAN_a8r8g8b8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001929 else
John Kåre Alsakerf9e710b2012-11-13 19:10:22 +01001930 ec->read_format = PIXMAN_a8b8g8r8;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001931
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07001932#ifdef GL_EXT_unpack_subimage
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001933 if (strstr(extensions, "GL_EXT_unpack_subimage"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001934 gr->has_unpack_subimage = 1;
Kristian Høgsberg1c4f1632013-08-07 12:11:27 -07001935#endif
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001936
1937 if (strstr(extensions, "GL_OES_EGL_image_external"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001938 gr->has_egl_image_external = 1;
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001939
1940 extensions =
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001941 (const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001942 if (!extensions) {
1943 weston_log("Retrieving EGL extension string failed.\n");
1944 return -1;
1945 }
1946
1947 if (strstr(extensions, "EGL_WL_bind_wayland_display"))
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001948 gr->has_bind_display = 1;
1949 if (gr->has_bind_display) {
1950 ret = gr->bind_display(gr->egl_display, ec->wl_display);
Pekka Paalanen035a0322012-10-24 09:43:06 +03001951 if (!ret)
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001952 gr->has_bind_display = 0;
Pekka Paalanen035a0322012-10-24 09:43:06 +03001953 }
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001954
Ander Conselvan de Oliveira1c169ff2013-03-05 17:30:30 +02001955 if (strstr(extensions, "EGL_EXT_buffer_age"))
1956 gr->has_egl_buffer_age = 1;
1957 else
1958 weston_log("warning: EGL_EXT_buffer_age not supported. "
1959 "Performance could be affected.\n");
1960
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001961 glActiveTexture(GL_TEXTURE0);
1962
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001963 if (compile_shaders(ec))
1964 return -1;
1965
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03001966 gr->fragment_binding =
1967 weston_compositor_add_debug_binding(ec, KEY_S,
1968 fragment_debug_binding,
1969 ec);
1970 gr->fan_binding =
1971 weston_compositor_add_debug_binding(ec, KEY_F,
1972 fan_debug_repaint_binding,
1973 ec);
Ander Conselvan de Oliveira27508c22012-11-08 17:20:46 +02001974
Pekka Paalanen035a0322012-10-24 09:43:06 +03001975 weston_log("GL ES 2 renderer features:\n");
1976 weston_log_continue(STAMP_SPACE "read-back format: %s\n",
Pekka Paalanenfe4eacf2013-01-10 16:50:42 +02001977 ec->read_format == PIXMAN_a8r8g8b8 ? "BGRA" : "RGBA");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001978 weston_log_continue(STAMP_SPACE "wl_shm sub-image to texture: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001979 gr->has_unpack_subimage ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001980 weston_log_continue(STAMP_SPACE "EGL Wayland extension: %s\n",
John Kåre Alsaker320711d2012-11-13 19:10:27 +01001981 gr->has_bind_display ? "yes" : "no");
Pekka Paalanen035a0322012-10-24 09:43:06 +03001982
John Kåre Alsaker1b7ad162012-11-13 19:10:19 +01001983
Kristian Høgsberg25894fc2012-09-05 22:06:26 -04001984 return 0;
1985}
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001986
1987WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
1988 .opaque_attribs = gl_renderer_opaque_attribs,
1989 .alpha_attribs = gl_renderer_alpha_attribs,
1990
1991 .create = gl_renderer_create,
1992 .display = gl_renderer_display,
1993 .output_create = gl_renderer_output_create,
1994 .output_destroy = gl_renderer_output_destroy,
1995 .output_surface = gl_renderer_output_surface,
Jason Ekstrand0b61bf42013-10-27 22:24:54 -05001996 .output_set_border = gl_renderer_output_set_border,
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001997 .print_egl_error_state = gl_renderer_print_egl_error_state
1998};